Overview
Siemens WinCC stores every archived process tag in a Microsoft SQL Server database (SQL Server 2005, 2008, 2012, 2016, 2019, or 2022 depending on the WinCC version installed). Although the raw tables look like ordinary SQL tables, the timestamp column is a WinCC-proprietary floating-point value counting seconds since 1970-01-01, and the archive is split into compressed (TAG_<Name>_0) and uncompressed (TAG_<Name>) partitions that rotate by time. Direct T-SQL queries therefore return values that look plausible but cannot be plotted, exported, or post-processed without an additional translation layer.
This technical reference shows how to wire a WinCC picture button to a VBScript action that opens the WinCC OLE DB Provider, runs a SQL query that returns the last 10 minutes of one or more tags from the Process Value Archive, converts WinCC time stamps to local time, and writes the result to a CSV file on disk. A parallel section covers the ANSI-C scripting variant, and a final section maps the same workflow to WinCC Runtime Professional (TIA Portal V16–V20) using the documented user-archive OLE DB query pattern.
Prerequisites
- WinCC V7.0 SP3 or later (V7.4, V7.5, or V7.5 SP2 recommended for newer SQL Server editions) or WinCC Runtime Professional V16/V17/V18/V19/V20 inside TIA Portal.
- SQL Server 2005 or higher installed locally or on a reachable server. WinCC Runtime owns the catalog
CC_<ProjectName>_<Suffix>R(for exampleCC_Process_22R). - A configured Process Value Archive with at least one tag in WinCC Explorer / TIA Portal that is logging at a 1-second or 1-minute cycle.
- WinCC runtime user must have
db_ownerrights on the runtime catalog. On SQL Server 2005 this is granted withsp_addrolemember 'db_owner', '<WinCCUser>'. - Graphics designer access to the picture and the button object.
- Local or UNC write access for the WinCC runtime user to the destination folder (for example
C:\Reports\).
E_FAIL when you try to read RealValue.Process Value Archive Architecture
WinCC writes each Process Value Archive into a pair of SQL tables per partition:
| Table | Content | Retention |
|---|---|---|
TAG_<ArchiveName>_0 |
Compressed values (min/max/average/peak) | Long-term (days/months/years) |
TAG_<ArchiveName>_1 |
Uncompressed values (every change/event) | Short-term (hours/days) |
TAG_<ArchiveName>_2 .. _N |
Optional overflow partitions | Rotated by archive configuration |
The compressed table is the correct one to query for trend reports because it survives the rotation of _1. Each row carries the columns Timestamp (float, seconds since 1970-01-01 UTC), RealValue (double), Quality (tinyint, 0xC0 = Good, 0x40 = Bad), and Flags (tinyint, 0x80 = substituted value, 0x40 = time-jumped value).
OLE DB Provider Connection Strings
The WinCC OLE DB Provider (WinCCOLEDBProvider.1) is registered automatically by the WinCC installation. Two connection strings cover the typical cases:
| Scenario | Connection String |
|---|---|
| Local runtime, default instance | Provider=WinCCOLEDBProvider.1;Catalog=CC_<ProjectName>_<Suffix>R;Data Source=.\WinCC |
| Remote runtime, named SQL instance | Provider=WinCCOLEDBProvider.1;Catalog=CC_<ProjectName>_<Suffix>R;Data Source=<Server>\<Instance> |
| User archives (RT Professional / WinCC V7) | Provider=WinCCOLEDBProvider.1;Catalog=CC_<ProjectName>_<Suffix>R;Data Source=.\WinCC |
For RT Professional the same provider is used. The official Siemens documentation for user-archive queries via MS OLE DB Provider is referenced at the end of this article.
Implementing the CSV Export Button (VBScript)
Open Graphics Designer, select the button object, and navigate to Events → Mouse → Click. Right-click, select "VBS Action", and paste the following script. It opens the OLE DB connection, runs a parameterized query for the last ten minutes of three example tags, converts WinCC time stamps to local time, and writes the result to a timestamped CSV file.
' OnClick event of "Export CSV" button
Option Explicit
Sub OnClick(ByVal Item)
Dim sConn, oConn, oRS, oCmd
Dim sSQL, sCSV, sFile, sLine
Dim fso, oFile, dStart, dEnd
Dim iQuality
' --- 1. Build connection string -----------------------------------
sConn = "Provider=WinCCOLEDBProvider.1;" & _
"Catalog=CC_Process_22R;" & _
"Data Source=.\WinCC"
' --- 2. Compute the 10-minute rolling window ----------------------
dEnd = DateAdd("s", Now, #1970-01-01#) ' current time in WinCC format
dStart = DateAdd("n", -10, dEnd) ' 10 minutes back
' --- 3. Build parameterized SQL ------------------------------------
sSQL = "SELECT Timestamp, RealValue, Quality, Flags " & _
"FROM TAG_PVArchive_0 " & _
"WHERE Timestamp BETWEEN " & dStart & " AND " & dEnd & _
" AND (ValueID = (SELECT ValueID FROM PVDATAMANAGER " & _
" WHERE TagName = 'Plant1\Temp1')) " & _
"ORDER BY Timestamp ASC"
' --- 4. Open OLE DB connection ------------------------------------
Set oConn = CreateObject("ADODB.Connection")
oConn.ConnectionString = sConn
oConn.CursorLocation = 3 ' adUseClient
oConn.Open
Set oCmd = CreateObject("ADODB.Command")
Set oCmd.ActiveConnection = oConn
oCmd.CommandText = sSQL
oCmd.CommandTimeout = 30
Set oRS = oCmd.Execute
' --- 5. Build CSV header ------------------------------------------
sCSV = "LocalTime;WinCCTime;RealValue;Quality;Flags" & vbCrLf
' --- 6. Iterate rows and convert time stamps -----------------------
Do While Not oRS.EOF
iQuality = CInt(oRS("Quality"))
sLine = FormatDateTime(DateAdd("s", CDbl(oRS("Timestamp")), _
#1970-01-01#), vbGeneralDate) & ";" & _
CStr(oRS("Timestamp")) & ";" & _
CStr(oRS("RealValue")) & ";" & _
Hex(iQuality) & ";" & _
Hex(CInt(oRS("Flags"))) & vbCrLf
sCSV = sCSV & sLine
oRS.MoveNext
Loop
' --- 7. Write file ------------------------------------------------
Set fso = CreateObject("Scripting.FileSystemObject")
sFile = "C:\Reports\PV_Export_" & _
Replace(Replace(FormatDateTime(Now, vbGeneralDate), "/", "-"), ":", "-") & _
".csv"
Set oFile = fso.CreateTextFile(sFile, True, True) ' Unicode = True
oFile.Write sCSV
oFile.Close
' --- 8. Cleanup ----------------------------------------------------
oRS.Close
oConn.Close
Set oRS = Nothing
Set oConn = Nothing
Set oCmd = Nothing
Set oFile = Nothing
Set fso = Nothing
' Optional: write a status to an internal tag
HMIRuntime.Trace "CSV export written to " & sFile & vbCrLf & sCSV
End Sub
PVDATAMANAGER join is optional but recommended. Without it the query must use ValueID (an integer assigned at archive start). The TagName-to-ValueID translation is what fails most often when migrating a script between projects.Rolling 10-Minute Buffer Strategy
The button action above runs only on demand. If the requirement is to keep the last ten minutes hot in memory and write only when the user clicks, use a cyclic VBScript trigger plus an in-memory dictionary. The WinCC V7.5 manual documents the HMIRuntime.BaseTagName pattern for tag arrays; pair it with the Windows Scripting Dictionary object as a sliding window.
' Global declaration at project level (optional)
Dim gBuffer ' Dictionary: key = "Tag|UnixSec", value = Array(ts, val, q)
' Cyclic trigger fires every 60 000 ms
Sub UpdateBuffer(ByVal Item)
Dim dNow, dKey, aRow, i
Dim tags, sTag, oTag, dVal, lQ
If IsEmpty(gBuffer) Or gBuffer Is Nothing Then
Set gBuffer = CreateObject("Scripting.Dictionary")
End If
dNow = DateAdd("s", Now, #1970-01-01#)
tags = Array("Plant1\Temp1", "Plant1\Press1", "Plant1\Flow1")
For i = 0 To UBound(tags)
sTag = tags(i)
Set oTag = HMIRuntime.Tags(sTag)
oTag.Read
dVal = oTag.Value
lQ = oTag.Quality
dKey = sTag & "|" & CStr(dNow)
If Not gBuffer.Exists(dKey) Then
gBuffer.Add dKey, Array(dNow, dVal, lQ)
End If
Next
' Trim entries older than 10 minutes
Dim dCutoff, k
dCutoff = dNow - 600
Dim aKeys : aKeys = gBuffer.Keys
For i = 0 To UBound(aKeys)
If CLng(Split(aKeys(i), "|")(1)) < dCutoff Then
gBuffer.Remove aKeys(i)
End If
Next
End Sub
' OnClick: serialise the buffer
Sub ExportBuffer(ByVal Item)
Dim k, a, sCSV, fso, oFile, sFile
sCSV = "Tag;WinCCTime;RealValue;Quality" & vbCrLf
For Each k In gBuffer.Keys
a = gBuffer(k)
sCSV = sCSV & Split(k, "|")(0) & ";" & _
a(0) & ";" & a(1) & ";" & Hex(CInt(a(2))) & vbCrLf
Next
Set fso = CreateObject("Scripting.FileSystemObject")
sFile = "C:\Reports\Buffer_" & FormatDateTime(Now, vbGeneralDate) & ".csv"
Set oFile = fso.CreateTextFile(sFile, True, True)
oFile.Write sCSV
oFile.Close
End Sub
Variant: ANSI-C Script (WinCC V7 Classic)
For WinCC V7 pictures that prefer C scripting over VBScript, the same workflow is possible with DBPROVIDER functions declared in apdefap.h:
// C-Action on click
#include "apdefap.h"
void OnClick(char* lpszPictureName, char* lpszObjectName,
char* lpszPropertyName)
{
// Connection
dbProviderInit("WinCCOLEDBProvider.1", "CC_Process_22R", ".\\WinCC");
dbConnect();
// Query
double dEnd = GetSecondsSince1970();
double dStart = dEnd - 600.0;
char szSQL[1024];
sprintf(szSQL,
"SELECT Timestamp, RealValue, Quality "
"FROM TAG_PVArchive_0 "
"WHERE Timestamp BETWEEN %f AND %f "
" AND ValueID IN (SELECT ValueID FROM PVDATAMANAGER "
" WHERE TagName IN ('Plant1\\Temp1'))",
dStart, dEnd);
// Open
dbOpen(szSQL);
// Iterate with dbGetField...
FILE* fp = fopen("C:\\Reports\\CExport.csv", "w");
fprintf(fp, "WinCCTime;RealValue;Quality\n");
while (dbGetRecord() == DB_OK) {
fprintf(fp, "%f;%f;%d\n",
dbGetFieldAsDouble("Timestamp"),
dbGetFieldAsDouble("RealValue"),
dbGetFieldAsInt("Quality"));
}
fclose(fp);
dbClose();
dbDisconnect();
}
dbProviderInit functions are unresolved and the picture fails to compile.RT Professional (TIA Portal V16-V20) Method
In WinCC Runtime Professional, user archives are queried with the same OLE DB pattern. The official Siemens documentation for this workflow is "Query for User Archives (RT Professional)":
Query for User Archives (RT Professional) – TIA Portal V20 documentation
For Process Value Archives in RT Professional, query the table TAG_<ArchiveName>_0 directly via the WinCC OLE DB Provider. The connection string is identical:
Dim sConn
sConn = "Provider=WinCCOLEDBProvider.1;" & _
"Catalog=CC_<RTProjectName>_R;" & _
"Data Source=.\WinCC"
To access user archives, swap the table prefix from TAG_ to UA#:
sSQL = "SELECT * FROM UA#ProductionLog ORDER BY ID ASC"
Architecture Overview
Verification Procedure
- Open WinCC Explorer → "Tag Logging" → "Archives". Verify that the archive referenced in the script exists and that the tag is checked under "Selected".
- Activate WinCC Runtime (RT) on the engineering station or on the target server.
- Open the picture containing the export button. Confirm that the button is enabled and that the OnClick event is bound to the VBScript (not to a C action if you pasted VBScript).
- Click the button. Open the WinCC "Diagnostics" tool (WinCC Explorer → Tools → "ApDiag"). Confirm that no SQL error or access violation is logged.
- Open the destination folder and check that the CSV file exists, has the expected size, and contains the column header plus at least ten data rows.
- Open the CSV in Microsoft Excel (data import → semicolon separator). Confirm that the "LocalTime" column is a recognisable date and that "RealValue" is numeric.
- Run the equivalent query directly in SQL Server Management Studio with the same catalog name to confirm that the WinCC OLE DB Provider returns identical rows:
SELECT TOP 50 Timestamp, RealValue, Quality, Flags
FROM CC_Process_22R.dbo.TAG_PVArchive_0
ORDER BY Timestamp DESC;
Troubleshooting Matrix
| Symptom | Likely Cause | Remediation |
|---|---|---|
| "Provider cannot be found" error 0x800A0E7A | WinCC OLE DB Provider not registered (script runs outside runtime) | Install WinCC runtime on the machine executing the script; do not run from WinCC Editor |
| Recordset empty despite tag values present | Querying TAG_<Archive>_1 after rotation |
Query TAG_<Archive>_0 (compressed long-term table) |
| Time stamp shows as large integer (e.g., 1 700 000 000) | Missing conversion from WinCC seconds to VB Date | Apply DateAdd("s", Timestamp, #1970-01-01#) before export |
| CSV cells contain scientific notation for large values | Default Excel cell format | Write ="value" or set Text format in CSV header row |
| Access denied to C:\Reports\ | WinCC runtime service account lacks write permission | Grant Authenticated Users write permission or run RT as a domain user with rights |
| Script hangs on first run | Database initialisation on cold start of WinCCOLEDBProvider
|
Pre-warm the provider in a cyclic action fired once per hour |
| Quality column always 0xC0 even on bad values | Reading ValueID of a non-archived tag | Confirm tag is configured in "Tag Logging → Selected" |
| CSV contains only one row regardless of time window | Using WHERE with local time string instead of WinCC float |
Convert time window to float with DateAdd("s", Now, #1970-01-01#)
|
| "Cannot open database requested in login" | SQL Server login lacks db_owner
|
Run sp_addrolemember 'db_owner', 'WinCCUser' in the catalog |
Field-Proven Caveats
-
Tag aliases in faceplates: When the tag is referenced through a faceplate interface, the TagName in PVDATAMANAGER includes the picture name. Strip the prefix with
REPLACEor join through the active picture context. - Time zone: WinCC stores time stamps in UTC-relative seconds since 1970-01-01. The local conversion in the script applies the OS time zone of the runtime server, not the engineering station. For multi-site deployments, document the offset explicitly.
-
Compression granularity: The compressed table returns one row per archive cycle (1 minute, 5 minutes, 1 hour depending on configuration). Do not expect every original sample if you query
_0rather than_1. - SQL Server 2005 deprecation: SQL Server 2005 is out of mainstream support. Modern installations of WinCC V7.4 and later pair with SQL Server 2014, 2016, or 2019. The OLE DB connection string is identical but the SQL Server Browser service must be running for named instances.
- 32-bit vs 64-bit provider: On a 64-bit Windows Server, the WinCC OLE DB Provider is 32-bit. The VBScript runtime inside WinCC is therefore also 32-bit; do not use a 64-bit-only ADO version.
-
Filename collisions: Two clicks within one second overwrite the file silently. Use
Replace(FormatDateTime(Now, vbGeneralDate), ":", "-")plus milliseconds if multiple operators are likely to click concurrently. - Performance: A 10-minute window of three tags is sub-second. A 24-hour window of 200 tags at 1-second resolution can take several seconds; in this case schedule the export to a background thread and post a completion notification back to the HMI.
Standards and Documentation References
The WinCC V7 manual set ("WinCC/Information System V7.5", chapter "ANSI-C and VBScript for actions", "Process Value Archive" and "WinCC OLE DB Provider") is the canonical reference for this workflow. For RT Professional, the TIA Portal online help under "WinCC RT Professional → Access to archive data via WinCC OLE DB Provider" documents the same provider.
FAQ
How do I query multiple tags at once from a WinCC Process Value Archive?
Use the PVDATAMANAGER table to resolve each tag to its ValueID and then select rows where ValueID IN (SELECT ValueID FROM PVDATAMANAGER WHERE TagName IN ('Tag1','Tag2')). This avoids the brittle pattern of hard-coding integers.
What is the difference between TAG_Archive_0 and TAG_Archive_1?
_0 contains the compressed long-term values (typically one row per archive cycle, calculated via min/max/average), while _1 contains the raw short-term values. For reports older than the raw-archive retention, only _0 will return data.
Why does my CSV show timestamps as large floating-point numbers such as 1 700 000 042.123?
WinCC stores seconds since 1970-01-01 00:00:00 UTC. To convert to a readable date in VBScript use FormatDateTime(DateAdd("s", CDbl(oRS("Timestamp")), #1970-01-01#), vbGeneralDate) before writing the row.
Can I export to .xlsx instead of .csv from a WinCC button?
Yes, by creating an Excel.Application COM object, opening a workbook, and writing cells with .Cells(i,1).Value = ..., but this requires Excel installed on the runtime server, which is discouraged on production SCADA hosts. CSV is the field-proven choice for 24/7 SCADA deployments.
Which SQL Server permissions does the WinCC runtime user need for OLE DB queries?
The user running the WinCC runtime service needs db_owner on the runtime catalog CC_<ProjectName>_<Suffix>R. On SQL Server 2005, grant it with sp_addrolemember 'db_owner', '<User>' while connected to that catalog. Without this, opening the OLE DB connection fails with error 0x80004005.