How to show a progress bar in a NetSuite saved search

Add a Formula (HTML) column that turns Planned Work and Actual Work into a colored bar and percent, red when a project task runs over plan.

The quick answer

Edit the saved search, open the Results subtab, and add a column row with Formula (HTML) in Field. Its formula builds a small piece of HTML for each row: a gray track with a colored fill whose width is Actual Work divided by Planned Work, capped at 100%, followed by the percent. A nested CASE makes the fill red once actual passes plan, and a guard returns a message instead of dividing by zero. Give the column a Custom Label, click Add, preview, and save. Use Formula (HTML). Formula (Text) treats the result as text, so the markup shows up as literal characters.

The screenshots show sample data. Person and operating-company names are fictional. Use your own search and fields when following the steps.

Before you start

HTML formula columns need two things in the account:

  • The HTML Formulas in Search feature, under Setup > Company > Enable Features on the Analytics subtab.
  • The Create HTML Formulas in Search permission on the role you build the search with. An administrator adds it on the role's Permissions tab, Setup subtab. Without it you can't add a Formula (HTML) column, and editing a search that already has one may drop that column or leave you saving a copy.

You also need project tasks in the account, a role that can see them, and permission to edit the saved search.

This example starts from an existing Project Task saved search called Task Hours by Project. It has one criterion, Project is Delta Ridge Utility District : PRJ-218 Filter Plant Retrofit, and four result columns: Name, Project, Planned Work, and Actual Work.

The same pattern works for any two numbers on one row, like quantity received against quantity ordered. Swap the field IDs and the labels.

01. Preview the hours as numbers

From Reports > Saved Searches > All Saved Searches (or Lists > Search > Saved Searches, depending on your role's menus), find Task Hours by Project and click Edit. The Criteria subtab has the single Project filter.

The search has one criterion: Project is Delta Ridge Utility District : PRJ-218 Filter Plant Retrofit.

Click Preview to see the starting point. In this sample data it's Total: 5. Site Survey has 12 of 16 planned hours, Pump Skid Installation 48 of 40, Control Wiring 6 of 24, Commissioning 0 of 20, and Operator Training 0 of 0. It's all there, but you have to do the math on every row to spot the task that ran over.

Before the change: five tasks with Planned Work and Actual Work as plain numbers.

02. Add a Formula (HTML) column

Click Return To Criteria and open the Results subtab. Under Columns, click Add Row, open the Field list, and choose Formula (HTML). The other formula types sit right above it.

Choose Formula (HTML) in the Field list for the new column row.

The row's Formula cell becomes editable, with a small button beside it that opens the formula popup. You can type in the cell, but the popup gives you room for a long formula. Leave Summary Type blank on this row. The bar is worked out per task, so the search should return one row per task, not grouped totals.

With Formula (HTML) chosen, the Formula cell has a button that opens the formula popup.

03. Write the progress-bar formula

Click the button beside Formula. In the Saved Project Task Search popup, type this in Formula:

CASE WHEN NVL({plannedwork},0) = 0 THEN 'No planned hours' ELSE '<div style="display:inline-block;vertical-align:middle;width:120px;height:12px;background:#d6dbe1;"><div style="height:12px;width:' || TO_CHAR(ROUND(LEAST(100, 100 * NVL({actualwork},0) / {plannedwork}))) || '%;background:' || CASE WHEN NVL({actualwork},0) > {plannedwork} THEN '#d9534f' ELSE '#5cb85c' END || ';"></div></div> ' || TO_CHAR(ROUND(100 * NVL({actualwork},0) / {plannedwork})) || '%' END

Here's what each part does:

  • CASE WHEN NVL({plannedwork},0) = 0 THEN 'No planned hours' catches tasks with no plan before any division runs.
  • The outer div is the gray track, 120 pixels wide. The inner div is the fill.
  • LEAST(100, ...) caps the fill width at 100% so it stays inside the track. The label after the bar uses the uncapped value, so an over-plan task can read 120%.
  • The nested CASE picks red (#d9534f) when Actual Work is more than Planned Work and green (#5cb85c) otherwise.
  • NVL({actualwork},0) treats a blank Actual Work as 0.
  • TO_CHAR turns the computed numbers into text so they can be joined to the markup with ||.

Everything in the markup is fixed text or a computed number. Don't join free-text fields into HTML like this without thinking about what users could type into them.

{plannedwork} and {actualwork} are the field IDs for Planned Work and Actual Work on a Project Task search. To confirm an ID for your own search type, choose the field in the popup's Field list and NetSuite inserts it into the formula.

The formula popup with the full formula typed. The box shows its last lines, ending in || '%' END.

Click Set to close the popup. Then type Progress in Custom Label and click Add on the row. The new row reads Formula (HTML), the formula, and Progress.

The added row: Formula (HTML), the formula, and the custom label Progress.

04. Preview the progress bars

Click Preview. Total: 5 hasn't changed, and the new Progress column draws a bar on every row. Site Survey's green fill is three-quarters across with 75%, and Control Wiring shows a quarter fill with 25%.

After the change: the same five tasks, now with a Progress bar and percent on each row.
Pump Skid Installation used 48 of 40 hours. The bar is capped at full width and turns red, and the label reads 120%.

Check the result

  1. The total matches the preview from step 01. Here it's Total: 5 both times.
  2. Pump Skid Installation, 48 of 40 hours, shows a full red bar and 120%.
  3. Commissioning, 0 of 20 hours, shows an empty gray track and 0%.
  4. Operator Training, 0 planned hours, reads No planned hours instead of an error.

Preview doesn't save anything. Click Return To Criteria, then Save. The saved results open with an Edit this Search button (shown here because this role can edit the search) and the same five bars, so everyone who runs Task Hours by Project sees the Progress column.

After saving, the results open with Edit this Search and keep the Progress column.

Check the bars again under the roles that will run the search. The bar is only for reading. Keep Planned Work and Actual Work in the results, or add a Formula (Numeric) or Formula (Percent) column, when people need to sort, filter, or export the values. An export of the HTML column may contain the markup instead of a bar.

This percent is Actual Work divided by Planned Work. It isn't the task's Percent Work Complete field, which NetSuite calculates its own way.

Common questions

Why does my HTML show up as text instead of a bar?

The column is probably Formula (Text). It treats the result as text and prints the <div> markup as characters. Change the row's Field to Formula (HTML) and keep the same formula.

What permission do I need to add an HTML formula?

The account needs the HTML Formulas in Search feature turned on, and your role needs Create HTML Formulas in Search. Without the permission you can't add the column, and editing a search that already has one may remove it.

How does the formula avoid dividing by zero?

NVL({plannedwork},0) = 0 is checked first. When a task has no planned hours, the formula returns No planned hours and never reaches the division. That's what Operator Training shows with 0 of 0.

Why does Pump Skid Installation read 120% when the bar isn't any wider?

LEAST(100, ...) caps only the fill width, so the bar can't spill out of its 120-pixel track. The label uses the uncapped value, so 48 of 40 hours shows a full red bar and 120%.

Can I sort, filter, or export by the progress bar?

Not in any useful way. The bar is HTML for reading on screen, and an export may contain the markup. Keep Planned Work and Actual Work, or add a Formula (Numeric) or Formula (Percent) column with the same division, for sorting and exports.

Can I use this for other numbers or change the colors?

Yes. Swap {plannedwork} and {actualwork} for another pair on the same row, like quantity received against quantity ordered, and keep the zero check and the cap. The colors are the hex values in the nested CASE. Add another WHEN if you want a yellow band before a row goes red.