Problem Overview
WinCC 6.0 SP4 (SIMATIC WinCC V6.0 + SP4) provides a powerful Tag Logging archive system that natively handles numeric process values, binary states, and raw/process tags. However, archiving string-typed tags such as batch names, operator IDs, recipe identifiers, lot numbers, or shift descriptions with a time stamp is not directly supported by the standard Tag Logging archive. When the user attempted to configure a string tag as a process value archive, the archive simply refused the data type, and the batch name vanished from the report.
This limitation applies to the classic Tag Logging archive and to the corresponding print/Excel report layouts in the WinCC Report Designer. The archived numeric columns accept BYTE, WORD, INT, REAL, BOOL, and similar data types, but no native STRING column is exposed for time-stamped rows.
This article documents three field-proven methods to capture, persist, and report string-typed batch data with time stamping in WinCC 6.0 SP4:
- WinCC User Archives (a relational table that natively holds string columns).
- An integer code mapping approach using a C-script lookup table.
- An ASCII decomposition approach that stores each character as a numeric byte tag and reconstructs the string at report time.
Why Native String Archiving Is Limited
Internally, Tag Logging stores values in compressed SQL Server tables where each row contains a fixed-size numeric payload plus a millisecond timestamp. The archive configuration dialog in WinCC Explorer (Tag Logging → Archives → Properties) only offers the data types supported by the underlying logging driver. A STRING tag is a WinCC Management Level construct — it exists in the tag database and can be read by scripts and faceplates, but it has no equivalent archive column.
Three practical constraints follow:
- The Tag Logging wizard rejects
STRINGtags in the selection list. - Report Designer table columns and OLE-DB queries against the archive database return numeric payloads only.
- C-script functions such as
GetTagChar()return the live value at execution time but do not write to a time-stamped archive.
The C runtime helpers commonly referenced for numeric conversion are:
| C Function | Purpose | Limitation With Strings |
|---|---|---|
atoi() |
Convert ASCII string to integer | Only works on numeric strings like "10" |
itoa() |
Convert integer to ASCII string | Round-trips integers only; cannot store arbitrary text |
sprintf() |
Format text into a char buffer | Requires pre-allocated buffer (e.g. SysMalloc()) |
SysMalloc(n) |
Allocate n bytes in WinCC script heap | Must be paired with SysFree() to avoid leaks |
GetTagWord() |
Read a WORD tag value | Returns numeric value, not the text representation |
TagSetChar() |
Write a character to a string tag | Writes live; no archive row produced |
None of these primitives writes a string to a time-stamped archive row. The string must first be reduced to a numeric form, then stored through a numeric archive, then reconstructed at report time.
Prerequisites
Before implementing any method, verify the following:
- WinCC Explorer V6.0 SP4 with a running WinCC project (RT or RT-PM).
- Microsoft SQL Server (installed automatically with WinCC) reachable from the WinCC service account.
- The string tag is already declared under WinCC Explorer → Tag Management → [your connection] → String Tags.
- For Method 1, the WinCC User Archives option must be licensed and present (it ships with WinCC V6.0 but check WinCC Information System → Options → User Archives).
- Global Script C editor access (Global Scripts → C-Editor) and rights to add functions under Project Functions.
- The Report Designer is installed (default with WinCC V6.0).
Method 1 — WinCC User Archives
User Archives is a WinCC option that provides a relational table view on top of SQL Server. Each row carries an automatic time stamp and any column can be a string. This is the cleanest method when the batch name is free-form text.
Step 1.1 — Create the User Archive Table
- Open WinCC Explorer and select User Archives in the navigation tree.
- Right-click and choose New User Archive. Name it
UA_BatchReport. - Open the archive editor and define columns:
| Column Name | Data Type | Length | Comment |
|---|---|---|---|
BatchID |
Numeric (32-bit) | — | Auto-incremented primary key |
BatchName |
String | 64 | The free-form batch name |
OperatorID |
String | 16 | Logged-on user |
StartTime |
Date/Time | — | User archive time stamp |
EndTime |
Date/Time | — | User archive time stamp |
ProcessValue1 |
Numeric (32-bit) | — | Optional reference tag value |
Activate the Time Stamp property on the archive; WinCC then writes the system time automatically when a new row is appended.
Step 1.2 — Write a C-Script to Append a Row
Create a project function ArchiveBatchName():
// Project Function: ArchiveBatchName
// Appends the current BatchName string tag to the User Archive UA_BatchReport
{
// Open the archive
UAConnect("UA_BatchReport");
// Read the live string tag
char* szBatch = GetTagChar("BatchName_Tag");
char* szUser = GetTagChar("@CurrentUser");
DWORD dwPV = GetTagWord("ProcessValue1_Tag");
// Move to a new row
UAInsert("UA_BatchReport");
// Set fields
UASetFieldValue("UA_BatchReport", "BatchName", szBatch);
UASetFieldValue("UA_BatchReport", "OperatorID", szUser);
UASetFieldValue("UA_BatchReport", "ProcessValue1", &dwPV);
// Commit
UAWrite("UA_BatchReport");
// Cleanup
SysFree(szBatch);
SysFree(szUser);
UADisconnect("UA_BatchReport");
return 0;
}
UAConnect call returns an error code if the archive name is wrong or the User Archives option is not licensed. Wrap the call in a check using UAGetLastError() when commissioning.Step 1.3 — Trigger on Batch Start
Call ArchiveBatchName() from a button click on the batch faceplate or from a tag-triggered action:
-
Graphics Designer → Button → Event → Mouse Click → C-Action:
ArchiveBatchName(); - Or schedule on a value change of
BatchStart_Tagvia Global Script → Actions.
Method 2 — Integer Code Mapping With Translation Script
If your batch names come from a fixed lookup list (recipe IDs, product codes, or shift codes), storing an integer code in Tag Logging and translating it at report time is the most compact solution.
Step 2.1 — Define the Code List
Maintain the lookup table as a header file under Project Functions:
// Project Function: GetBatchNameByCode
// Returns the string for a given integer batch code.
{
switch (dwCode)
{
case 1: return "BATCH_RED_A";
case 2: return "BATCH_RED_B";
case 3: return "BATCH_GREEN_A";
case 4: return "BATCH_BLUE_001";
case 5: return "BATCH_BLUE_002";
case 9: return "MAINTENANCE_CLEANING";
default: return "UNKNOWN_BATCH";
}
}
Step 2.2 — Archive the Integer Code
Create a process tag BatchCode_Tag of type WORD (unsigned 16-bit) and configure it for archiving in Tag Logging at a 1-second or event-triggered cycle. The archive captures the time stamp automatically.
Step 2.3 — Translate in the Report Designer
Open Report Designer → Batch Report layout. In the table column that should display the batch name, add a Dynamic field bound to the BatchCode_Tag archive column and use a C-action on the field to substitute the text:
// C-Action on report field
{
DWORD dwCode = GetTagWord("BatchCode_Tag");
char* szName = SysMalloc(64);
sprintf(szName, "%s", GetBatchNameByCode(dwCode));
return szName;
}
This returns the human-readable name directly into the printed report or Excel export.
| Code Range | Use Case | Recommended Storage |
|---|---|---|
| 1 – 255 | Static lookup ≤ 255 entries | BYTE / WORD archive column |
| 256 – 65 535 | Larger catalog | WORD archive column |
| > 65 535 | Catalog with auto-incrementing IDs | DWORD archive column |
Method 3 — ASCII Decomposition Into Per-Byte Tags
For free-form strings with no preset vocabulary, decompose each character into its ASCII code (0 – 255) and store it in a numeric archive. The Report Designer then concatenates the bytes back into text.
Step 3.1 — Declare Byte Tags Per Character Slot
For a 16-character batch name, declare:
-
BatchChar_01throughBatchChar_16asBYTEtags
Configure each one as a process value archive in Tag Logging with a 500 ms acquisition cycle. Total archive growth: 16 bytes × 1 728 samples/hour ≈ 28 KB/hour — manageable for multi-month retention.
Step 3.2 — Decompose on Batch Start
// Project Function: DecomposeBatchName
{
char* szBatch = GetTagChar("BatchName_Tag");
int nLen = strlen(szBatch);
int i;
BYTE bZero = 0;
for (i = 0; i < 16; i++)
{
if (i < nLen)
{
BYTE bChar = (BYTE)szBatch[i];
char szTag[32];
sprintf(szTag, "BatchChar_%02d", i + 1);
SetTagByte(szTag, bChar);
}
else
{
// Pad remainder with 0 (null terminator equivalent)
char szTag[32];
sprintf(szTag, "BatchChar_%02d", i + 1);
SetTagByte(szTag, bZero);
}
}
SysFree(szBatch);
return 0;
}
Step 3.3 — Reconstruct in the Report
// C-Action in report designer field
{
char szOut[32];
int i;
memset(szOut, 0, sizeof(szOut));
for (i = 0; i < 16; i++)
{
char szTag[32];
sprintf(szTag, "BatchChar_%02d", i + 1);
BYTE b = GetTagByte(szTag);
if (b == 0) break;
szOut[i] = (char)b;
}
char* szRet = SysMalloc(strlen(szOut) + 1);
strcpy(szRet, szOut);
return szRet;
}
| String Length | Byte Tags Required | Archive Size / Hour @ 500 ms |
|---|---|---|
| 8 chars | 8 | ~14 KB |
| 16 chars | 16 | ~28 KB |
| 32 chars | 32 | ~56 KB |
| 64 chars | 64 | ~112 KB |
Configuring the Batch Report With Time Stamping
Regardless of the storage method, the report layout requires these elements:
- Open Report Designer → File → New → Batch Report.
- Insert a Time Stamp Column from Dynamic Dialog → Archive Tags → [your archive]. Bind to
TimeStampwith the formatyyyy-MM-dd hh:mm:ss.000. - Insert a column for each numeric value archive (Method 2:
BatchCode_Tag; Method 3: eachBatchChar_NN; Method 1: nothing — the string is read directly from the User Archive OLE-DB query). - For Method 1 in Report Designer, choose Insert → Database Connection → User Archive and select
UA_BatchReport. Drop theBatchName,StartTime, andEndTimecolumns onto the layout. - Save the layout as
@Batch_Report.rpland assign it as the scheduled print job in WinCC Explorer → Print Jobs.
Verification Steps
After commissioning, perform the following checks:
-
Tag write check: In WinCC Explorer → Tag Management, set
BatchName_Tagto"TEST_RUN_001". Confirm the value displays in the Graphics Designer faceplate. - Script execution check: Click the Archive Batch button. In the global script diagnostic window, watch for the function call log.
-
Database check: Open SQL Server Management Studio, connect to the WinCC instance, and query:
SELECT * FROM UA_BatchReport ORDER BY BatchID DESC;— confirm the row exists with the expected string and time stamp. - Report print check: Trigger the print job manually and inspect the generated PDF. Verify the BatchName column is populated, the time stamp matches the trigger moment to within ±1 s, and no field is blank.
-
Unicode / non-ASCII check: If batch names contain non-Latin characters, confirm the SQL Server collation is set to
SQL_Latin1_General_CP1_CI_ASorLatin1_General_100_CI_AS_SC; otherwise non-Latin characters appear as?in the report.
Troubleshooting Matrix
| Symptom | Likely Root Cause | Resolution |
|---|---|---|
| Tag Logging rejects the string tag in the selection dialog | Native limitation; not a configuration error | Apply one of the three methods above |
UAConnect() returns error code 0x8004xxxx |
User Archives option not licensed | Reinstall the option or migrate to Method 2/3 |
| Script compiles but the archive row is empty |
UASetFieldValue called before UAInsert
|
Reorder: insert row → set fields → write |
Report Designer shows ? for non-ASCII names |
Collation or code page mismatch | Switch SQL collation to Latin1_General_100_CI_AS_SC |
| Archived codes do not match the printed name | Code list updated in runtime but report layout caches old lookup | Reload the layout from the project; restart the WinCC runtime |
| High disk growth after switching to Method 3 | Acquisition cycle too tight or string too long | Raise cycle to 5 s and limit string to 32 chars |
| Memory leak in long-running scripts |
SysMalloc() without matching SysFree()
|
Audit every SysMalloc and free after use |
| Time stamp is off by hours | WinCC service running in a different time zone or DST not handled | Set Windows time zone, disable DST auto-adjust on the WinCC server |
Method Selection Checklist
| Decision Criterion | Method 1 (User Archives) | Method 2 (Code Mapping) | Method 3 (ASCII Bytes) |
|---|---|---|---|
| Free-form strings | Yes | No | Yes |
| Fixed batch list | Yes | Best fit | Possible |
| License available | Requires User Archives | No extra license | No extra license |
| Multiple string fields | Easiest to extend | One code per field | Many byte tags per field |
| Reporting complexity | Low | Medium | Medium-High |
| Disk footprint | Low | Lowest | Highest |
| Unicode support | Yes (with collation) | Yes (codes only) | Limited to single-byte scripts |
Why does WinCC 6.0 SP4 refuse to archive a STRING tag in Tag Logging?
The classic Tag Logging archive in WinCC V6.x writes compressed rows to SQL Server with a fixed numeric payload. STRING is a Management-Level data type, not a logging-supported one, so the selection dialog does not list it. Use a User Archive, an integer code, or ASCII byte decomposition to persist the value with a time stamp.
Can I use itoa() or atoi() to round-trip a batch name through an integer archive?
No. atoi() and itoa() convert between numeric strings (e.g. "10") and integers. They cannot reverse arbitrary text such as "BATCH_RED_A". For free-form text, use User Archives (Method 1) or ASCII decomposition (Method 3); for fixed lists, use a code lookup (Method 2).
How do I display the BatchName column in the WinCC Report Designer?
For Method 1, insert a User Archive database connection in the layout and drop the BatchName column. For Methods 2 and 3, bind the field to the archive column of the integer or byte tag and add a C-action that calls GetBatchNameByCode() or concatenates the byte array back into a string.
How many bytes does Method 3 consume on disk?
Each byte tag produces roughly 14 KB per hour at a 500 ms acquisition cycle (1 728 samples × 8 bytes). A 16-character batch name therefore uses about 28 KB per hour per logged event. Raise the acquisition cycle to 5 s or limit the string length to 32 characters if disk retention is critical.
Do these methods work on WinCC V7.x or WinCC Professional?
Yes. User Archives, code mapping, and byte decomposition continue to work on WinCC V7.x and on WinCC Professional (TIA Portal) with minor API adjustments. WinCC Professional additionally offers the "Archive" data type for some string tags, but classic Tag Logging still follows the same numeric model, so the workarounds remain valid for legacy migration projects.