Troubleshooting Chart Dataset Checkbox Selection Logic

Ryan Tanaka7 min read
HMI / SCADAOther ManufacturerTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

The panel shows seven selected checkboxes, prints 7, builds the first exec dbo.usp_TankHistory command, and then stops. The chart never processes the remaining selections because the script throws an exception at chart.setDatasetEnabled(dataset.name, len(selectedCheckboxes)>0). Start there. The loop and query construction are not the first fault.

Start with the first exception

Read the script output in execution order:

  1. print len(selectedCheckboxes) reports 7.
  2. The first loop pass builds and prints exec dbo.usp_TankHistory '999','Level'.
  3. The call to chart.setDatasetEnabled(...) fails.
  4. The exception terminates the event script, so the loop never reaches the second checkbox.

The single printed query does not prove that iteration is broken. It proves that execution reached the first iteration and stopped at the following statement.

Panel or debug symptom Cause to check
Selected count prints 7 All seven checkbox objects currently have a true selected property. This is independent of dataset configuration.
Only the first query prints An exception immediately after the first print aborts the event script.
Failure occurs at dataset.name dataset is not assigned anywhere in the shown script.
Dataset will not accept Query The configured dataset has no Query property to mutate.
Every selected dataset receives an enabled value of true len(selectedCheckboxes)>0 describes the whole collection, not the checkbox associated with one dataset.

Capture the complete exception text and line number. If the failure still points to setDatasetEnabled, inspect the first argument before changing SQL or database permissions.

Check the dataset identifier passed to the chart

The first argument to chart.setDatasetEnabled must identify a dataset configured on that chart. The failing script passes dataset.name, but no statement creates or assigns dataset.

That is not a database fault. Changing the stored procedure, query text, or refresh call will not define the missing object.

  • If the runtime reports that dataset is undefined, remove that reference and obtain the configured dataset name from the controlling checkbox.
  • If the runtime instead reports that the named dataset does not exist, compare the value character-for-character with the name entered in the chart customizer.
  • If the chart lookup fails, verify that Chart is a child of the container used by getComponent("Chart").

Use a dedicated checkbox property named DSName. Do not depend on the checkbox component name or visible label unless you intentionally make that text identical to the chart dataset name. Component identity, operator-facing text, and stored-procedure arguments serve different purposes and should remain separate.

Read the Boolean argument correctly

The second argument in setDatasetEnabled is a Boolean. The expression len(selectedCheckboxes)>0 evaluates to true when at least one checkbox is selected and false when none are selected. It is therefore a valid Boolean expression.

It is the wrong Boolean for this design. Each dataset is controlled by one checkbox, while that expression reports the state of the entire group. With seven selected boxes, it evaluates to true on every attempted loop pass. With one selected box, it still evaluates to true. It never says whether the current dataset's checkbox is selected.

Read the state change for the checkbox that raised the event:

  • event.stateChange == event.SELECTED: enable that checkbox's mapped dataset.
  • Any other state change: disable that mapped dataset.

This one-to-one decision removes the need to scan cntDatasets, build selectedCheckboxes, or index the list with cbNum.

Map one checkbox to one dataset

Build a total of seven checkbox controls for the seven chart datasets. Give every checkbox a String custom property called DSName, then enter the corresponding chart dataset name in that property.

Check these readings in order:

  1. Read event.source.getPropertyValue("DSName"). A blank value means the checkbox has no mapping; fill it in before checking the chart.
  2. Compare the returned text with the chart customizer. A mismatch means the event is targeting a nonexistent or different dataset.
  3. Read event.stateChange. If it equals event.SELECTED, the required enabled state is true; otherwise it is false.
  4. Locate the chart from the checkbox parent. If the controls and chart do not share that parent, correct the component path rather than changing the dataset name.

Use seven controls in total. Literally creating one checkbox and then adding seven copies would produce eight controls, which conflicts with the stated seven-dataset design.

Bind the queries before toggling visibility

Configure the seven datasets on the chart and bind each dataset to its stored-procedure query. Dataset enablement should control whether a configured series is active; it should not also create the dataset's query definition at runtime.

The installation description permits two query layouts:

  • A shared procedure such as dbo.usp_TankHistory, with the tank and graphed value supplied as its two arguments.
  • A separate stored procedure for each dataset, with each chart dataset bound to its corresponding procedure.

Choose the layout that matches the database implementation. In either case, keep the dataset binding permanent and supply the changing tank value through the binding. Configure the graphed-value argument separately for each dataset when using the shared procedure.

The tank identifier is available both as root-container property strTank and as label text from lblTank. Select one authoritative source. Reading the display label works only while that text remains an exact representation of the database argument; using the data property avoids coupling query behavior to operator-facing formatting.

The original script also says the procedure value comes from a checkbox label but passes checkbox.name. Those are not inherently the same value. Store the procedure argument in a dedicated property or fix it in the dataset binding so a label edit cannot change database behavior.

Do not call dataset.setPropertyValue("Query", query) when the dataset has no Query property. Adding an unrelated custom property with that name would not automatically convert it into an executable query binding. String concatenation also makes quote handling and parameter validation part of the event script; bind query parameters through the platform's query configuration instead.

Replace the collection loop with the item event

Place this script on each checkbox's itemStateChanged event:

isChecked = event.stateChange == event.SELECTED
dsName = event.source.getPropertyValue("DSName")
chart = event.source.parent.getComponent("Chart")
chart.setDatasetEnabled(dsName, isChecked)

The mechanism is direct:

  • event.source identifies the checkbox the operator changed.
  • DSName supplies the matching chart dataset identifier.
  • isChecked supplies the Boolean enabled state.
  • setDatasetEnabled changes only that dataset.

Remove the selection-list loop, runtime Query assignment, and per-click fpmi.db.refresh call from this visibility event. Query refresh belongs to the dataset binding and its parameter changes. Checkbox state belongs to series enablement.

If the checkbox and chart are not siblings, adjust only the chart component lookup. Keep the mapping and Boolean logic unchanged.

Run the resolving procedure and verify each branch

  1. Create a clean chart screen instead of carrying forward logic designed for a more complex reusable chart example.
  2. Add seven datasets with the chart customizer. Confirm every configured name exactly.
  3. Bind each dataset to the required stored procedure. Supply the tank and graphed-value arguments through the binding design.
  4. Create seven checkboxes in total. Add the String custom property DSName to each and enter one chart dataset name per checkbox.
  5. Add the four-line itemStateChanged script to every checkbox.
  6. Open the window with a known tank value. Confirm the binding receives the intended string from strTank or lblTank, whichever was chosen as authoritative.
  7. Select one checkbox. Verify that only its mapped series appears and that no script exception is logged.
  8. Select a second checkbox. Verify that both series remain visible; the first must not be reset.
  9. Clear the first checkbox. Verify that only its series disappears.
  10. Exercise all seven controls individually. Record any DSName that does not resolve to a configured dataset.

If a series enables but has no points, the checkbox logic has completed its job. Check the bound procedure arguments, returned timestamp column, returned value column, and dataset-to-axis configuration next. If toggling still throws an exception, inspect the component path and exact dataset identifier before touching the SQL.

FAQ

How do I fix an error on chart.setDatasetEnabled?

Replace the unassigned dataset.name reference with the mapped name from event.source.getPropertyValue("DSName"). Confirm that the returned string exactly matches a dataset configured on the chart.

How do I make each checkbox control only one chart dataset?

Add a String property named DSName to each checkbox and map it to one dataset. Pass event.stateChange == event.SELECTED as the enabled value.

How do I pass the tank and graph value to the stored procedure?

Bind each chart dataset to its procedure and supply both arguments through the query binding. Use one authoritative tank property, and keep the graph value in a dedicated binding or custom property rather than deriving it from display text.

How do I verify that the checkbox fix worked?

Toggle all seven checkboxes one at a time, confirm that only the mapped series changes, and check that the event produces no exception. If a series is enabled but empty, inspect its procedure arguments and returned columns.

How do I know when to stop troubleshooting and escalate?

Stop when a valid DSName, correct component path, and direct Boolean state still produce a repeatable chart API exception, or when a correctly parameterized binding fails outside the checkbox event. Save the complete exception, chart dataset configuration, binding definition, component hierarchy, and the smallest reproducing window, then contact the platform manufacturer's official support channel.

Back to blog