Indirect Addressing in WinCC 7.4: VBS Scripts and Unified Alternatives
Indirect addressing is a long-standing requirement for HMI/SCADA engineers who need to bind a single display object to many similar process values without manually configuring one tag per datapoint. Operators want to page through dozens of valve states, alarm groups, or motor currents using one faceplate, while engineering wants one tag structure, one script, and one screen rather than hundreds of duplicated graphic objects.
Siemens addressed this in two distinct generations of HMI software. The classical runtime WinCC V7.4 / V7.5 (TIA-adjacent but still based on the original WinCC Explorer and Graphics Designer) does not implement a syntax like DB[db_addr].DBW[word_addr]. The newer WinCC Unified (V16 onward, current documentation set at V20) does, via the Indirect Addressing mechanism documented under "Configuring tags > Basics > Indirect addressing". Engineers working on V7.4 projects therefore have to choose between three practical paths:
- A VBS global-script approach that computes the tag name at runtime and reads or writes it through the HMIRuntime tag interface.
- An indirect attribute connection on a single object property that resolves a tag from a configurable index.
- A migration to a WinCC Unified RT project where the property or function parameter accepts an index directly.
This reference covers each method, the exact syntax, an end-to-end valve-overview screen example, and a side-by-side comparison so the correct solution can be selected for the plant.
1. WinCC Addressing Model: Why Direct Indirection Fails in V7.x
WinCC V7.x stores tag configuration in the SQL-based project database at design time. Every tag name, datatype, AS address (e.g. DB100.DBW0), and update cycle is fully resolved when the project is compiled and downloaded to the runtime. The graphics designer then binds object properties to tag names stored as static strings inside the picture file (.pdl).
When the runtime evaluates a picture, the Graphics Designer substitutes the configured tag name verbatim and hands it to the data manager. Because the substitution happens once per picture load and is then cached, the runtime cannot later resolve a token such as DB[db_addr].DBW[word_addr] where the bracketed indices are runtime variables. The parser simply has no rule for square-bracketed indices inside a tag name; the name is not a string template, it is an opaque reference.
struct.member paths only. It does not accept expressions, arithmetic, or index substitution inside a tag-name string. Attempting to enter "DB" & i & ".DBW" & j directly into the tag name field results in a configuration error: the tag is reported as "Address not valid".
Two structural limits follow:
- Tag addresses are bound at compile time. The data manager does not support symbolic indirection across DB numbers.
- Object property dynamizations store the resolved tag name. There is no native TagPrefix/TagSuffix property on a graphic object that the runtime re-evaluates each cycle.
These limits are not bugs; they are consequences of the V7.x configuration model. Workarounds must therefore live either in scripts (which execute in the runtime and can build tag names) or in indirect connections (where the dynamization itself carries an index parameter).
2. Method 1: VBS Global Script Indirect Read/Write
The most flexible and widely deployed pattern in WinCC V7.4 uses a public function in a VBS Global Script. The function builds the tag name string at runtime, then calls HMIRuntime.Tags to read or write it. Because the tag is referenced through the data manager interface and not through the parser, the tag name is allowed to be an expression.
2.1 Create a public VBS module
In WinCC Explorer, open Global Script > VBS Editor. Create a new module, for example modIndirect, and add a procedure marked Public:
2.2 Important constraints on tag naming
The string built by the script must match a tag that exists in the WinCC tag management. There is no symbolic PLC address resolution at the data-manager boundary; the tag is a WinCC-internal object. Two valid approaches exist:
-
Pre-create all tags. Add
DB100.DBW0,DB100.DBW2,DB100.DBW4... as separate tags in the tag management. The script selects which one to access by name. This is the recommended approach for production systems because tag diagnostics, archive configuration, and security all remain intact per tag. -
Use a struct tag. If the PLC exposes an S7 data block as a UDT or a struct, declare it once as a struct tag in WinCC and read
MyStruct.field(i). Note that V7.x struct element access is by literal field name, not by index, so this is not a true substitute for the bracket syntax but can be combined with VBS to pick elements dynamically.
2.3 Calling the function from a picture event
On any object property dynamization or button event, switch the trigger type to VBS Action and call the global function:
The function call is global; it does not require any prefix because the module is loaded into the runtime script engine.
2.4 Update-cycle caveat
Unlike a tag-direct property dynamization that runs on a configured update cycle (e.g. 1 s), a VBS function call runs only when triggered. To refresh a faceplate every second, attach the read to a cyclic trigger:
- In the picture, configure an invisible timer or use the picture's own update cycle.
- Select the event Update > 1 s on the picture window.
- Attach a VBS action that re-reads the relevant tag indices and writes them to internal tags that drive the object properties.
HMIRuntime.Tags(...).Read call allocates an internal object and forces a data-manager lookup. Calling it 32 times per second on a 1 s cycle is fine; calling it 5 000 times per second is not. Batch reads using TagSet (a collection of tags) reduce overhead by up to 60 %.
2.5 Using TagSet for bulk indirect reads
A TagSet performs a single bulk fetch and reduces tag-manager round-trips from N to 1.
3. Method 2: Indirect Attribute Addressing on Object Properties
WinCC V7.x supports a feature called indirect attribute addressing on dynamizations of object properties. Instead of binding a property to a fixed tag, you bind it to an expression that names a tag. The expression can include an index variable from the same picture.
3.1 Configuration steps
- Create an internal integer tag, e.g.
ValveIndex(32-bit, update cycle "On change"). - Place a valve faceplate (a custom graphic object) on the picture.
- Open the property dynamization of the faceplate's Status property (the Boolean that drives the color).
- Choose dynamization type Tag connection.
- Check the box Indirect on the tag selection dialog.
- Enter the expression
"Valve_DB100" & ValveIndexin the indirect field. The referenced tagsValve_DB100_0,Valve_DB100_1, ... must exist in the tag manager.
At runtime, when ValveIndex changes from 5 to 6, the dynamization re-resolves the tag name and re-binds to Valve_DB100_6. The faceplate shows valve 6 with no additional scripting.
3.2 Naming convention for indirect attributes
| Index | Tag name in WinCC | Indirect expression |
|---|---|---|
| 0 | Valve_DB100_0 |
"Valve_DB100_" & ValveIndex |
| 1 | Valve_DB100_1 |
"Valve_DB100_" & ValveIndex |
| 31 | Valve_DB100_31 |
"Valve_DB100_" & ValveIndex |
3.3 Limitations of indirect attribute addressing
- Only the tag name is indirect. The data type is fixed at design time; all referenced tags must have the same type.
- The feature is available on a per-property basis. If the same object reads four properties (status, command, feedback, alarm), four separate indirect bindings are required.
- It cannot address a sub-element of a tag (e.g.
myStruct.element(i)); the indirection is on the tag name as a whole. - It cannot address arbitrary word offsets inside a DB. The PLC-side address (
DB100.DBW0) is captured per tag.
4. Method 3: Native Indirect Addressing in WinCC Unified
WinCC Unified (TIA Portal V16+, current documentation V20) ships a runtime engine that resolves indirection directly. The dynamization dialog for object properties, the parameter input of system functions, and the expressions inside the new JavaScript-style scripting all accept an index reference. According to the Siemens TIA Portal Help "Indirect addressing (RT Unified)":
With indirect addressing, the process value of a dynamized object property or parameter of a system function is only determined during runtime.
4.1 Syntax in WinCC Unified
Indirection is configured via the property's dynamization dialog:
- Open the property of the object (for example Process value on a Bar element).
- Select the dynamization source Tag.
- In the dialog, click Indirect addressing.
- Define a name fragment, e.g.
Motor_Current, and bind an index tagMotorIndex. The runtime will resolve toMotor_Current[0],Motor_Current[1], ...
Under the hood, Unified supports two flavours:
| Flavour | Where used | Index syntax | Example |
|---|---|---|---|
| Array index | Tags declared as array | Tag[i] |
ValveStatus[ValveIndex] |
| Name fragment | Indirect on tag name | Prefix<index> |
Valve_DB100_<idx> |
4.2 Scripting in Unified
Unified uses JavaScript instead of VBS. A read becomes:
The expression Tags("Valve_DB100_" + idx) is functionally identical to the V7.x HMIRuntime.Tags(sTag) pattern but is integrated into the V20 script engine without the VBS COM-object overhead.
5. WinCC V7.4 vs WinCC Unified: Indirect Addressing Capabilities
| Capability | WinCC V7.4 / V7.5 | WinCC Unified (V17+) |
|---|---|---|
| DB[db].DBW[word] literal syntax | Not supported | Not literal, but achieved via index + array tag |
| VBS Global Script with computed tag name | Supported | Supported (VBS) and JS |
| Indirect attribute on property | Supported (tag-name only) | Supported (tag-name or array index) |
Array-index access tag[i]
|
Limited, via struct + literal field name | Native on array tags |
| Bulk read optimization (TagSet) | Yes | Yes (Tags(...) collection) |
| Performance per indirection call | ~0.5 ms (COM alloc) | ~0.1 ms (native) |
| Browser-based runtime | No (WinCC RT only) | Yes (Unified RT) |
| Configuration tool | WinCC Explorer | TIA Portal |
6. Practical Implementation: 32-Valve Status Overview Screen
The original poster's use case was a screen that shows the status of many valves with only a few tags and one structure. The following pattern satisfies that on WinCC V7.4.
6.1 PLC layout
In the S7-300/400/1500 program, lay the valve states out in a DB so that each valve occupies one bit. Example: DB100.DBX0.0 ... DB100.DBX3.7 = 32 valves in 4 bytes. Commands live in DB101.DBX0.0 ... DB101.DBX3.7. Each word can also be referenced by word offset for diagnostic logging.
6.2 Tag declaration in WinCC
| WinCC tag | PLC address | Type | Cycle |
|---|---|---|---|
ValveStatus_0 |
DB100.DBX0.0 |
Binary | 1 s |
ValveStatus_1 |
DB100.DBX0.1 |
Binary | 1 s |
| ... | ... | ... | ... |
ValveStatus_31 |
DB100.DBX3.7 |
Binary | 1 s |
ValveCmd_0 ... ValveCmd_31
|
DB101.DBX0.0 ... DB101.DBX3.7
|
Binary | On change |
ValveIndex |
Internal | Unsigned 32 | On change |
6.3 The faceplate graphic object
Build one custom graphic object called @ValveFaceplate.pdl with the following properties exposed as interface attributes:
| Property | Type | Bound to |
|---|---|---|
Status |
Binary | Indirect on tag name |
CmdOpen |
Binary | Indirect on tag name |
Index |
Unsigned 16 | Constant at instance time |
6.4 Placing 32 instances on one picture
Insert the faceplate 32 times. Each instance receives a different constant Index (0..31). Inside the faceplate, the Status property is dynamized with indirect addressing using the expression "ValveStatus_" & Index. The picture itself contains no VBS - the indirection is resolved entirely by the dynamization engine.
6.5 Alternative: one faceplate, one screen, page through valves
Place a single faceplate instance and use two buttons (Prev, Next) to increment ValveIndex:
The faceplate's Status dynamization reacts on the next 1 s update cycle and shows the new valve. This is the lowest-tag-count solution and matches the original requirement of "only a few tags".
7. Performance and Runtime Considerations
7.1 Tag cache hit ratio
Each unique tag name referenced via HMIRuntime.Tags(...) is added to the runtime tag cache. Repeated reads of the same name are O(1) after the first lookup. Indirect addressing therefore does not slow steady-state operation; it only pays the lookup cost on the first call per name.
7.2 Script runtime vs update cycle
WinCC V7.x limits VBS execution time per cycle to 1 second by default. A bulk read of 256 tags via TagSet typically completes in 15-40 ms. Reading the same 256 tags via 256 individual HMIRuntime.Tags(...).Read calls takes 200-400 ms and risks cycle-time overruns.
7.3 Update cycles vs trigger events
A VBS dynamization is best attached to a cyclic trigger with a period matching the fastest change you need to display. 1 s is the typical default; 250 ms is achievable on a modern PC for a few hundred tag calls.
8. Migration Path from WinCC V7.4 to WinCC Unified
For greenfield projects or major retrofits, migrate the indirection-heavy screens to Unified. The migration is not automatic (no direct converter exists from V7.x PDLs to Unified screens), but the script and tag logic transfers with minimal changes:
- Recreate tag structures in TIA Portal. Convert per-bit valve tags to a single array tag
ValveStatus[0..31]. - In the Unified screen, dynamize the faceplate
Statusproperty directly with the array elementValveStatus[Index]; no indirect expression is required because array indexing is native. - Replace VBS with JavaScript using the equivalent Unified scripting API.
Result: same operator view, ~80 % fewer WinCC tags (one array vs 32 individual bit tags), no VBS overhead.
9. Diagnostic Checklist and Common Faults
| Symptom | Likely cause | Fix |
|---|---|---|
| Tag value is always 0 after indirect read | Tag name does not exist in tag management | Verify with WinCC Information > Tag Simulation; add missing tag |
| Runtime error "Object variable not set" | Spelling error in computed name; tag not loaded because area not activated | Check package, channel diagnosis, ASCII trace of sTag |
| Indirect property shows stale value after index change | Property dynamization has wrong cycle or "On change" trigger but index tag has same value | Set cycle to "On change" and force index to write on every click |
| Slow screen open | Too many unique tag names created at picture load | Pre-create tags once, reuse via indirect; avoid generating new names per cycle |
| VBS action "Cycle time exceeded" alarm | Per-tag read loop too large | Switch to TagSet bulk read |
| Faceplate flickers at 1 Hz | Update cycle too low and value really is changing | Add hysteresis or deadband filter on the PLC side |
10. Summary of Recommended Approaches
- Keep the project on WinCC V7.4 with minimal change: use indirect attribute addressing on a single faceplate instance plus a button-driven index tag. Zero VBS, simplest debugging.
- Keep the project on WinCC V7.4 with maximum flexibility: use VBS Global Script and TagSet for computed-name reads. Best when multiple offsets are paged through programmatically.
- Migrate to WinCC Unified: use native array indexing. Best long-term answer; eliminates indirection code entirely and reduces tag count.
The DB[db_addr].DBW[word_addr] style used in WinCC Flexible and STEP 7 source code is a compile-time notation, not a runtime expression. On WinCC V7.x it must be rewritten as either a generated tag name, an indirect dynamization, or - on Unified - a true array index. All three patterns are documented and production-proven; the choice depends on project scale, runtime host, and migration horizon.
Does WinCC V7.4 support DB[db].DBW[word] indirect tag syntax?
No. The WinCC V7.x Graphics Designer parses tag names verbatim at compile time and accepts no index substitution. Use VBS Global Scripts, indirect attribute addressing on object properties, or migrate to WinCC Unified for native indirection.
How do I read an arbitrary DB word from VBS in WinCC V7.4?
Build the tag name string and call the data manager: Set o = HMIRuntime.Tags("DB100.DBW" & iWord): o.Read: v = o.Value. The tag DB100.DBW<iWord> must exist in the WinCC tag management. Use a TagSet for bulk reads to reduce round-trip overhead.
What is the difference between indirect attribute addressing and VBS indirection?
Indirect attribute addressing is configured at design time on a single object property and re-resolves the tag name when the index variable changes, with no script. VBS indirection lets you compute the tag name in code and is more flexible (multiple properties, conditional names, looping) but adds runtime overhead.
Does WinCC Unified support DB[db].DBW[word] syntax?
Unified does not use that literal syntax, but it provides native array indexing (Tag[i]) and indirect addressing on object properties and system-function parameters, which together cover the same use case without VBS or pre-declared tag lists.
How can I show 32 valves on one screen using only a few tags?
Create one internal index tag ValveIndex (0..31) and one faceplate with indirect attribute addressing bound to "ValveStatus_" & ValveIndex. Use Next/Prev buttons to step the index; the runtime re-binds automatically each cycle.