Problem Statement: Identifying the Top-Level Compound Group from a Nested Child
On Siemens HMI panels configured with WinCC in the TIA Portal (Comfort Panels, Unified Comfort Panels, and WinCC Runtime Advanced / Professional), a common engineering pattern is to assemble a complex symbol from multiple primitives, then group the primitives into a single selectable object. When the same compound symbol is reused dozens or hundreds of times on a process screen, each instance is typically renamed at the top group level (for example ES123, ES124, ES125) so that event handlers, dynamization functions, and tag prefixes can be derived from the instance name.
The problem surfaces when a VBScript function is attached to a deeply nested child element of the compound group (for example, a small valve disc embedded inside a larger frame that also contains a label and a unit readout). At runtime, the VBS handler receives the innermost clicked object via the implicit Item reference, but the built-in Item.Parent traversal either:
- Stops at the first enclosing group (returning the immediate subgroup name, not the top-level compound group), or
- Returns the surrounding picture (
Screen) when the child is already inside the top-level group.
The engineer therefore cannot reliably resolve the name ES123 from inside a single shared VBS function, breaking the pattern of "one function, many renamed instances."
Root Cause: How the WinCC Object Model Exposes Groups
To choose the correct fix it is necessary to understand exactly what the WinCC VBS object model exposes at the moment an event fires. The model follows the TIA Portal WinCC documentation for the WinCC VBScript object model and the Graphics Designer help.
The Implicit Item Reference
Every VBS action, dynamization, or event configured on a screen object receives an implicit parameter named Item that points to the object the script is bound to. The Item object exposes:
-
Item.ObjectName— the configured Name property of the object that owns the script (for a group, the group name; for a primitive, the primitive name). -
Item.Parent— the parent in the Graphics Designer hierarchy. For a primitive nested in one group,Item.Parentis the group. For an object at the top level of the screen,Item.Parentis the picture itself. -
Item.Type— the runtime type identifier, useful for filtering withTypeName(Item)or comparing against known group types.
Group Hierarchy vs. Picture Hierarchy
A compound group created in the Graphics Designer is a single object whose ObjectName is whatever the engineer typed in the Name field. Its children are the original primitives or subgroups, but the parent of the top-level group is the picture, not another group. This is the structural reason that:
-
Item.Parent.ObjectNameon a top-level group returns the picture name (for exampleScreen_1), notES123. - Climbing a fixed number of
.Parentlevels (e.g.Item.Parent.Parent.ObjectName) is not portable, because the same compound group may be instanced with different nesting depths in different screens.
Solution 1 — Walk the Parent Chain Until a Group Is Found
The most portable approach is to walk .Parent repeatedly until the runtime detects that the parent is the picture rather than a group. The TypeName of the picture is Screen (or HmiScreen on Unified panels), so the walk terminates at the first object whose TypeName is not a group type.
' VBS action: GetTopGroupName
' Returns the ObjectName of the topmost group that contains Item.
Function GetTopGroupName(obj)
Dim cur
Set cur = obj
Do While Not (cur Is Nothing)
' Stop when the next parent is no longer a group
If IsNull(cur.Parent) Then
GetTopGroupName = cur.ObjectName
Exit Function
End If
If TypeName(cur.Parent) = "Screen" Or _
TypeName(cur.Parent) = "HmiScreen" Or _
TypeName(cur.Parent) = "Document" Then
GetTopGroupName = cur.ObjectName
Exit Function
End If
Set cur = cur.Parent
Loop
GetTopGroupName = ""
End Function
' Usage in a mouse-click action on a nested valve symbol:
Dim topName
topName = GetTopGroupName(Item)
HMIRuntime.Trace "Top group is: " & topName & vbCrLf
Place the function in a project-wide script module (Project library → Scripts → Standard modules) so it is available to every screen. The shared function can then be called from any dynamization, mouse event, or value-change event.
Solution 2 — Use a Custom User-Defined Property on the Compound Group
Walking .Parent is reliable but adds runtime overhead on every event. A cleaner design is to store the name on the group itself using a user-defined property and read it directly from the child.
Step-by-Step Configuration
- In the Graphics Designer, select the top-level compound group.
- Open Properties > Miscellaneous and click the User-defined category.
- Add a new property, e.g.
CompoundNameof typeString. - Set its value to the same string as the group Name (for example
ES123). - From the nested child's VBS handler, read
Item.Parent.CompoundName— but only if the immediate parent is the group, otherwise walk one level up.
' Read the custom property from the top-level group containing Item
Function GetCompoundName(obj)
Dim cur, probe
Set cur = obj
Do While Not (cur Is Nothing)
On Error Resume Next
probe = cur.CompoundName
If Err.Number = 0 And probe <> "" Then
GetCompoundName = probe
Exit Function
End If
On Error Goto 0
If TypeName(cur) = "Screen" Or TypeName(cur) = "HmiScreen" Then Exit Do
Set cur = cur.Parent
Loop
GetCompoundName = ""
End Function
User-defined properties are visible in VBS exactly as built-in properties, and the runtime evaluates them with a simple lookup rather than a hierarchy walk. This is the recommended pattern for screens with hundreds of compound groups.
Solution 3 — Pass the Group Name as an Explicit Parameter
When the click target is fixed (for example, the click is on the top group itself, not on a child), the VBS function can simply read Item.ObjectName — no traversal is needed. The trade-off is that the clickable hit area becomes the bounding box of the entire group, which may be undesirable when the group contains a large invisible frame.
To keep the click on a small child but still pass the group name, configure the dynamization as a function call instead of a direct VBS action:
- Create a function
ColorByTag(groupName, state)in a project script module. - On the nested child's Appearance dynamization, choose Dynamization → Function → ColorByTag.
- For the
groupNameargument, bind it to the top group's name (drag the group onto the parameter slot, or type the literal name once and replicate by renaming the group instance).
This approach avoids both traversal and custom properties, but it requires the engineer to bind the parameter explicitly for every instance, so it scales less well than Solution 1 or Solution 2.
Comparison of the Three Solutions
| Criterion | Solution 1: Parent walk | Solution 2: User-defined property | Solution 3: Explicit parameter |
|---|---|---|---|
| Configuration effort | None per instance | One user-defined property per group type | One parameter binding per instance |
| Runtime cost | Several .Parent calls per event |
One property lookup | No traversal |
| Scales to many instances | Yes | Yes | Limited (manual binding) |
| Robust to nesting changes | Yes (terminates on picture) | Yes (property moves with group) | Yes (parameter is explicit) |
| Requires fixed click target | No | No | Yes (parameter must be bound) |
| Best for | Ad-hoc debugging, prototypes | Production screens with hundreds of instances | A handful of named instances |
Verification Procedure
After implementing any of the solutions above, run the following verification sequence in the WinCC Runtime to confirm the correct top-group name is returned.
- Compile and download the project to the HMI panel (or start the WinCC Runtime simulation on the engineering station).
- Open the screen that contains the compound groups and open the diagnostic trace window (Start → Programs → Siemens Automation → WinCC → Trace Viewer, or use
HMIRuntime.Trace). - Click on a nested child of a renamed compound group (for example, the valve disc inside
ES123). The trace should displayTop group is: ES123. - Click on a child of a different compound group (
ES124) and confirm the trace returnsES124— this proves the function is reading the instance name and not a hard-coded value. - Click on a child of an unnamed or default-named group and confirm the function returns the actual default name (e.g.
Group1) without raising an error. - For Solution 2, change the value of the
CompoundNameuser-defined property at runtime (via a tag connection) and verify the dynamization follows — this confirms the property is being read, not the static group name.
Edge Cases and Field-Proven Caveats
1. Group vs. Faceplate vs. Screen Window
If the compound symbol is implemented as a faceplate (an instance of a faceplate type) rather than a simple group, the Item reference in a faceplate script refers to the faceplate instance, and the top-level container is a screen window. Item.Parent from inside a faceplate instance is the screen window, not the screen. For faceplates, prefer Solution 2 with a tag-prefix tag of the faceplate type, or use the HmiRuntime APIs to resolve the container name explicitly.
2. Renamed vs. Default Group Names
The Graphics Designer assigns sequential default names (Group1, Group2...) when the engineer does not explicitly rename. Item.ObjectName returns these defaults verbatim. The traversal solutions still work, but any tag-derivation logic (for example, "T" & Mid(name, 3) to map ES123 → T123) must be guarded against empty or default names.
3. Touch Targets Smaller Than the Group
Moving the click event from the large top group to a small child (as in the original use case) reduces accidental hits on adjacent valves. The trade-off is that the entire bounding box of the child becomes the hit area, including transparent areas. To shrink the hit area to a small visible shape, embed only the visible valve disc as the click target and keep the frame and label as non-interactive group members.
4. Runtime vs. Configuration Behavior
In the Engineering System (ES) preview of a VBS function bound to a screen object, the Item reference is the same as at runtime, so the function can be unit-tested from the script editor. Trace output, however, only appears in the Runtime; the ES does not collect it. Plan trace-based verification for the RT simulation rather than the ES preview.
5. Unified vs. Classic Comfort Panels
On Unified Comfort Panels (WinCC Unified, TIA Portal V17 and later), the VBScript object model is the same in concept but the type names may differ (for example, HmiScreen rather than Screen). The traversal logic above accounts for both. If a project must run on both classic Comfort Panels and Unified Panels, wrap the type-name comparison in a small helper that returns True for any of the known picture types.
Troubleshooting Matrix
| Symptom | Likely cause | Fix |
|---|---|---|
Function returns the picture name (e.g. Screen_1) |
Walk terminated too early; picture type not recognized | Add the project's picture type to the TypeName check in Solution 1 |
Function returns the immediate subgroup name (e.g. Group3) |
Walk stopped at first group; only one .Parent step taken |
Use the full Do loop in Solution 1; confirm cur.Parent is not null |
| Function returns empty string | Top group has no name, or the custom property is unset | Rename the group; or set the user-defined CompoundName property (Solution 2) |
Runtime error "Object doesn't support this property or method" on cur.CompoundName
|
The user-defined property was not added to the group in the Graphics Designer | Re-open the group, add the property under Miscellaneous → User-defined, recompile, download |
| Tag prefix derived from the name is wrong at runtime but correct in the ES | Tag prefix logic was hard-coded for a single instance, not derived from Item.ObjectName
|
Replace hard-coded strings with a function call that returns the prefix from the resolved name |
| Click on a frame around the valve hits the wrong valve | Click target is the large top group, hit area overlaps neighbours | Move the click event to the small visible child inside the group and use Solution 1 or 2 to recover the name |
Best-Practice Recommendation
For production screens that replicate a compound symbol many times and rely on the symbol name to drive tag prefixes, faceplate instances, or color dynamization, the recommended pattern is:
- Add a single user-defined string property (e.g.
CompoundName) on the top-level group inside the Graphics Designer master. - Set
CompoundNameequal to the group Name for every instance, either by hand or via a small project script that runs on screen load. - Place a single shared VBS function in a project-wide standard module that walks
.Parentuntil it finds an object with a non-emptyCompoundName, falling back toObjectNameif the property is absent (so the function works on legacy groups that have not yet been migrated). - Bind click events and dynamizations to the small visible child, not to the large bounding group, to keep the hit area tight and predictable.
This combination keeps the click target small, the name resolution O(1) in the common case, and the function portable across nesting depths and across classic Comfort / Unified panels.
FAQ
Why does Item.Parent.ObjectName on a nested child return the picture name and not the compound group?
In the WinCC VBScript object model, Item.Parent returns the immediate parent in the Graphics Designer hierarchy. The immediate parent of a top-level compound group is the picture itself (type Screen or HmiScreen), so reading Item.Parent.ObjectName yields the picture name, not the group name. Walk the chain in a loop until the parent is no longer a group to find the top-level compound group.
How do I add a custom property to a group in the Graphics Designer?
Select the group, open its Properties dialog, switch to the Miscellaneous → User-defined category, click Add, and define a string property (for example CompoundName). The property is then readable from VBS as obj.CompoundName on the group and on any object inside it that walks up to the group.
Does the same VBS function work on both Comfort Panels and Unified Comfort Panels?
Yes, provided the function uses type-name checks that cover both the classic picture type (Screen) and the Unified picture type (HmiScreen). Wrap the comparison in a helper that returns True for any known picture type so the loop terminates correctly on both platforms.
Can I derive a tag name from the group name inside a single shared VBS function?
Yes. Once the top-level group name is resolved (for example ES123), use string functions to extract the trailing numeric portion and concatenate a prefix: tagName = "T" & Mid(topName, 3). Guard the extraction against empty or default group names to avoid generating invalid tag references at runtime.
What is the difference between a group and a faceplate for this scenario?
A group is a single object that contains primitives and subgroups; it lives entirely on one screen and has a flat ObjectName. A faceplate is a typed, reusable instance with its own property interface and tag-prefix mechanism; inside a faceplate, Item.Parent is a screen window, not the host screen. The traversal solutions above target groups; for faceplates, prefer tag-prefix tags and the faceplate type's own property interface.