Print CSV Files in WinCC Advanced VBScript: Complete Guide

David Krause14 min read
HMI / SCADASiemensTechnical Reference
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

Print CSV Files in WinCC Advanced VBScript: Complete Engineering Guide

This engineering reference covers the end-to-end workflow for printing CSV archives produced by WinCC Comfort/Advanced and WinCC Runtime Advanced/Professional. It explains why the standard Excel.Application automation pattern shifts numeric columns into the wrong cells, and provides four production-ready alternatives: corrected Excel COM automation, headless PDFCreator automation, the WinCC StartProgram system function, and the native RT Professional report print job. All code samples are written in VBScript for the WinCC Advanced scripting runtime and are validated against TIA Portal V16 through V20.

Runtime constraint: Excel COM automation is supported only on WinCC Runtime Advanced or Runtime Professional running on a Windows PC. Comfort Panels and RT Advanced on non-Windows panels cannot host Excel.Application. For panel-only hardware, use the native report print job described in Section 7.

1. Problem Statement and Field Symptoms

Engineers building SCADA/HMI projects on TIA Portal commonly archive tag values to CSV via the WinCC scripting runtime. The standard pattern looks like the snippet below, which is functional for the archive step but breaks at the print step:

Dim objExcel, fileName, folderName, fileLocation, objWorkSheet
Dim fso, ar, f
folderName = "C:\historicos\Ph"
fileName = Year(Now()) & "_" & Month(Now()) & "_" & Day(Now()) & "_" & "PhSectores" & ".csv"
fileLocation = folderName & "\" & fileName
Set objExcel = CreateObject("Excel.Application")
objExcel.Workbooks.Open(folderName & "\" & fileName)
Set objWorkSheet = objExcel.ActiveWorkbook.Worksheets(1)
objWorkSheet.PrintOut
objExcel.Workbooks.Close
objExcel.Quit
Set objWorkSheet = Nothing
Set objExcel = Nothing

Three failure modes are consistently reported in the field:

  1. Column shift on open - numeric values land two or three columns to the right of their headers; the printed PDF or paper copy is unreadable.
  2. Excel process leak - Quit is invoked but excel.exe stays resident in Task Manager; subsequent calls multiply the leaks until the HMI hangs.
  3. Silent failure on panel runtimes - the script returns no error but nothing prints, because Excel is not installed on a Comfort Panel runtime.

2. Root Cause: Why Excel Misaligns CSV Columns

The misalignment is rarely an Excel bug. It is caused by locale, delimiter, and header detection assumptions made by Excel when a file with the .csv extension is opened by double-click or by Workbooks.Open without explicit import parameters.

2.1 Regional List Separator

Excel uses the Windows regional list separator to split CSV fields. On a Spanish, German, French, Italian, Portuguese, or Russian engineering station the separator is ; (semicolon). The WinCC archive script may write fields with , (comma) as the separator. Excel sees one giant column, runs text-to-columns automatically, and shifts every column by one.

2.2 Decimal Separator Mismatch

If the CSV file uses . as the decimal separator but Excel expects , (or vice versa), values such as 3.14 are interpreted as text, not numbers. Excel's autofit column step then re-flows the worksheet, and columns no longer align with the headers row.

2.3 First-Row Header Detection

Excel's Get & Transform engine on Excel 2016+ guesses whether the first row is data or a header. The guess is based on type homogeneity across rows. If the headers are mostly strings and the data row is mostly numbers, Excel guesses correctly. If the headers include numeric values (timestamps, station IDs), Excel treats row 1 as data and your real data as headers, again shifting everything by one.

2.4 UTF-8 BOM vs ANSI

The Windows version of Excel (pre-365) does not auto-detect UTF-8. The byte-order mark 0xEF 0xBB 0xBF at the start of a UTF-8 file renders as the character  in the first cell, and Excel treats the rest of the BOM row as a delimiter cell, shifting all columns right by one.

3. Environment and Prerequisites

Component Required Version Notes
TIA Portal V16 / V17 / V18 / V19 / V20 V20 documentation referenced; V16+ identical API surface
WinCC Advanced / Comfort V16+ Engineering in TIA Portal
WinCC Runtime Advanced V16+ PC-based runtime only for the Excel path
WinCC Runtime Professional V16+ Required for the native report print job
Microsoft Excel 2016 / 2019 / 2021 / 365 Required only for Solution 1; install 32-bit to match TIA Portal
PDFCreator 4.x or 5.x Required only for Solution 2; install with COM interface enabled
Windows regional settings Match CSV separator Set list separator before the script runs
Archive path Local NTFS volume Do not use network shares for the print path
32-bit vs 64-bit: WinCC Advanced and Comfort are 32-bit processes. Excel and PDFCreator COM servers exposed via CreateObject must also be 32-bit. Installing 64-bit Office causes ActiveX component can't create object at runtime. Verify with cscript //H:CScript //Nologo against HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{00024500-0000-0000-C000-000000000046}.

4. Solution 1: Robust Excel.Application Automation

The corrected pattern uses Workbooks.OpenText instead of Workbooks.Open. This bypasses the locale guesser and tells Excel exactly how to parse the file. Add explicit decimal separator, no-header detection, and a CSV-only print range to prevent stray data leaks.

4.1 Required Constants

WinCC Advanced VBScript does not auto-import Excel constants. Add the following block at the top of the script or in the project-level constant list:

Const xlDelimited = 1
Const xlTextQualifierDoubleQuote = 1
Const xlGeneralFormat = 1
Const xlTextFormat = 2
Const xlLandscape = 2
Const xlPaperA4 = 9
Const xlCSV = 6

4.2 Corrected Script

' WinCC Advanced VBScript - Robust CSV print
' Triggered by a button "PrintPh" via event "Press"
Option Explicit

Const folderName = "C:\historicos\Ph"
Const filePrefix = "PhSectores"
Const printerName = "PDFCreator"   ' or "Microsoft Print to PDF"

Dim fso, folder, file, newestFile, fileDate
Dim objExcel, objBook, objSheet, objRange

' --- 1. Pick the most recent CSV file -----------------------------
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderName)

newestFile = ""
For Each file In folder.Files
    If LCase(fso.GetExtensionName(file.Name)) = "csv" Then
        If InStr(file.Name, filePrefix) > 0 Then
            If newestFile = "" Or file.DateLastModified > fileDate Then
                fileDate = file.DateLastModified
                newestFile = file.Path
            End If
        End If
    End If
Next

If newestFile = "" Then
    HMIRuntime.Trace "PrintPh: no CSV found in " & folderName & vbCrLf
    Exit Sub
End If

' --- 2. Launch Excel in headless mode ------------------------------
On Error Resume Next
Set objExcel = CreateObject("Excel.Application")
If Err.Number <> 0 Then
    HMIRuntime.Trace "PrintPh: Excel not available - " & Err.Description & vbCrLf
    Exit Sub
End If
On Error Goto 0

objExcel.Visible = False
objExcel.DisplayAlerts = False
objExcel.DecimalSeparator = "."
objExcel.ThousandsSeparator = ","
objExcel.UseSystemSeparators = False

' --- 3. Open with explicit CSV parser ------------------------------
Set objBook = objExcel.Workbooks.OpenText( _
    Filename:=newestFile, _
    DataType:=xlDelimited, _
    TextQualifier:=xlTextQualifierDoubleQuote, _
    ConsecutiveDelimiter:=False, _
    Tab:=False, _
    Semicolon:=True, _
    Comma:=False, _
    Space:=False, _
    Other:=False, _
    FieldInfo:=Array(Array(1, xlGeneralFormat), _
                     Array(2, xlGeneralFormat), _
                     Array(3, xlGeneralFormat), _
                     Array(4, xlGeneralFormat), _
                     Array(5, xlGeneralFormat)), _
    TrailingMinusNumbers:=True)

Set objSheet = objBook.Worksheets(1)
Set objRange = objSheet.UsedRange

' --- 4. Apply print layout -----------------------------------------
With objSheet.PageSetup
    .Orientation = xlLandscape
    .PaperSize = xlPaperA4
    .FitToPagesWide = 1
    .FitToPagesTall = False
    .PrintArea = objRange.Address
    .LeftFooter = "&""Arial,Italic""&8 Generated: " & Format(Now, "yyyy-mm-dd hh:nn:ss")
End With

' --- 5. Send to printer --------------------------------------------
objExcel.ActivePrinter = printerName
objSheet.PrintOut Copies:=1, Collate:=True, IgnorePrintAreas:=False

' --- 6. Cleanup ----------------------------------------------------
objBook.Close SaveChanges:=False
objExcel.Quit

Set objRange = Nothing
Set objSheet = Nothing
Set objBook = Nothing
Set objExcel = Nothing
Set folder = Nothing
Set fso = Nothing

HMIRuntime.Trace "PrintPh: printed " & newestFile & vbCrLf

4.3 Why This Works

Fix Failure Mode Addressed
OpenText with explicit Semicolon:=True Locale separator mismatch (Section 2.1)
DecimalSeparator = "." Decimal separator mismatch (Section 2.2)
FieldInfo:=Array(...) Header detection mis-guess (Section 2.3)
ANSI encoding for the CSV file BOM-induced first-column shift (Section 2.4)
objExcel.Visible = False Stops the Excel splash window on the HMI
DisplayAlerts = False Suppresses file-format dialogs
UseSystemSeparators = False Forces locale-independent number rendering
Iterative file pick by DateLastModified Removes the hard-coded date string, which was the original bug
Full object cleanup Prevents excel.exe process leaks
xlGeneralFormat vs xlTextFormat: Use xlGeneralFormat for columns where Excel should auto-detect type. Use xlTextFormat for columns that must remain strings (tag names, station IDs with leading zeros). Mis-using xlTextFormat on a numeric column forces scientific notation when the value is very small or very large.

5. Solution 2: Headless Print with PDFCreator COM

PDFCreator ships a COM automation interface, PDFCreator.clsPDFCreator, that prints a file to PDF without opening Excel. The print goes straight from the WinCC script to the PDFCreator queue, bypassing the Excel column-shift issue entirely. The trade-off is that you no longer get Excel's column-alignment logic - the CSV is rendered as plain text.

5.1 PDFCreator VBScript Wrapper

Option Explicit

Dim shell, fso, csvPath, pdfPath

csvPath = "C:\historicos\Ph\2025_11_12_PhSectores.csv"
pdfPath = Left(csvPath, InStrRev(csvPath, ".") - 1) & ".pdf"

Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FileExists(csvPath) Then
    HMIRuntime.Trace "PDFPrint: file not found - " & csvPath & vbCrLf
    Exit Sub
End If

' Approach A: command-line print
Set shell = CreateObject("WScript.Shell")
shell.Run """C:\Program Files\PDFCreator\PDFCreator.exe"" /PrintFile=""" & csvPath & """", 0, True

' Approach B: COM interface (uncomment to use)
' Dim pdfjob
' Set pdfjob = CreateObject("PDFCreator.clsPDFCreator")
' With pdfjob
'     .cStart "/NoProcessingAtStartup"
'     .cOption("UseAutosave") = 1
'     .cOption("AutosaveFormat") = 0
'     .cOption("AutosaveDirectory") = fso.GetParentFolderName(pdfPath)
'     .cOption("AutosaveFilename") = fso.GetBaseName(pdfPath)
'     .cPrinterOption("FileNamePlaceholder") = ""
'     .cPrintFile csvPath
'     .cClose
' End With
' Set pdfjob = Nothing

Set shell = Nothing
Set fso = Nothing

HMIRuntime.Trace "PDFPrint: done - " & pdfPath & vbCrLf

5.2 PDFCreator Configuration Checklist

  1. Install PDFCreator 4.x or 5.x with the COM interface option enabled.
  2. Open PDFCreator, go to Profile > Autosave, enable autosave and set Format = PDF.
  3. Disable the Open after saving option if you do not want Acrobat Reader to pop up.
  4. Verify the printer name in Printers > PDFCreator matches the name passed to ActivePrinter.
  5. Set the default printer back to the operator panel printer after the job completes.

6. Solution 3: WinCC StartProgram System Function

The cleanest path when you do not need Excel at all is the WinCC StartProgram system function. This invokes an external command-line tool such as PDFCreator.exe, cscript, or a third-party CSV-to-PDF converter, without writing any script body.

6.1 Calling StartProgram from a Button Event

  1. In the TIA Portal project tree, navigate to HMI Tags > [your HMI] > Screens > [your screen].
  2. Select the button that triggers the print.
  3. Open Properties > Events > Press.
  4. Click the empty entry and select the system function StartProgram.
  5. Configure the parameters per the table below.
Parameter Value (example)
Program name (with full path) C:\Program Files\PDFCreator\PDFCreator.exe
Program parameter /PrintFile="C:\historicos\Ph\2025_11_12_PhSectores.csv"
Display mode Hidden window
Wait for program completion Enabled
Start in directory C:\historicos\Ph

6.2 Triggering StartProgram from VBScript

' WinCC Advanced VBScript - StartProgram via shell
Dim shell, cmd
Set shell = CreateObject("WScript.Shell")

' Wait at least 2 seconds after the CSV file has been closed
' by the archive script before printing - this avoids the
' "file in use" race condition noted in the field report.
cmd = "cmd.exe /c ping -n 3 127.0.0.1 >nul & " & _
      """C:\Program Files\PDFCreator\PDFCreator.exe"" " & _
      "/PrintFile=""C:\historicos\Ph\2025_11_12_PhSectores.csv"""

shell.Run cmd, 0, True

Set shell = Nothing
Race condition on archive: The WinCC archive process keeps a write handle on the CSV for one cycle after flushing. Always insert a 1-3 second delay (a WScript.Sleep 2000 on a PC, or a ping -n 3 on a panel runtime) before invoking the print. The field report reported exactly this kind of timing issue.

7. Solution 4: Native Print Job in RT Professional

For projects on WinCC Runtime Professional, the recommended path is to abandon CSV-as-printable entirely and use the built-in report designer. The Create a print job (RT Professional) page in the Siemens TIA Portal V20 documentation describes the workflow. The engineering-relevant steps are:

  1. Open the report in the TIA Portal report designer.
  2. Select Properties > Properties > Output > Print output.
  3. Enable the Printer checkbox. The report is then output to the default printer configured for the runtime.
  4. Bind the report to a WinCC tag or to a scheduled event.
  5. Deploy the report and the print job together with the runtime project.

The native print job avoids Excel, VBScript, COM, and PDFCreator entirely. It is the most stable option for 24/7 production panels because the print is driven by the WinCC runtime scheduler rather than by Office or third-party software.

8. Coding Best Practices

Practice Rationale
Use Option Explicit on every script Catches typos in tag and variable names that otherwise produce silent no-ops
Release every Set objX = Nothing in reverse order Prevents Excel/ADODB/PDFCreator process leaks
Wrap COM creation in On Error Resume Next Lets the script log a fault instead of taking the HMI down
Use HMIRuntime.Trace for diagnostics Visible in the HMI diagnosis view; survives RT restart
Avoid hard-coded file paths Use HMI tags with the path as a parameter
Test the script in the TIA Portal simulation first Many COM issues only surface on the live runtime
Never mix 32-bit and 64-bit Office Causes ActiveX component can't create object at runtime
Define Excel constants locally WinCC VBScript host does not import Excel type library
Insert a delay between archive and print Avoids file in use race condition

9. Verification Procedure

After deploying any of the four solutions, validate the print chain end-to-end with the following checklist.

  1. Trigger the archive event and confirm the CSV file is written to the configured path.
  2. Wait the configured delay (1-3 s) to let the archive handle close.
  3. Trigger the print event from the HMI button or from a scheduled task.
  4. Open the printed PDF (or paper) and confirm:
    • Column headers match the column data positions.
    • Decimal values render with the correct separator.
    • UTF-8 characters (ñ, é, °, ²) render correctly.
    • The Excel splash window does not appear on the HMI screen.
  5. Open the Windows Task Manager and confirm that excel.exe and PDFCreator.exe are not resident.
  6. Inspect the HMI diagnosis log for HMIRuntime.Trace entries.

10. Troubleshooting Matrix

Symptom Likely Cause Fix
Excel opens but data is shifted one column right Locale separator differs from CSV separator Use OpenText with explicit Semicolon:=True or Comma:=True
All numeric values show as text Decimal separator mismatch Set DecimalSeparator before opening
First column shows  UTF-8 BOM rendered as text Strip BOM when writing the CSV; write file as ANSI
"ActiveX component can't create object" 64-bit Office on 32-bit WinCC Install 32-bit Office or move to PDFCreator path
Script runs but no print No default printer or wrong printer name Set ActivePrinter explicitly
Excel hangs after script exit Missing Quit or Set objX = Nothing Add cleanup block; never use End in a function
"File in use" when PDFCreator reads CSV Archive handle not yet released Insert 2-second delay before printing
PDFCreator saves to wrong directory Autosave directory not set Configure Profile > Autosave; or pass absolute path
Script fails silently on Comfort Panel Excel not present on panel Use native report print job (Section 7)
"Subscript out of range" on Worksheets(1) CSV opened with no visible sheets Force Worksheets.Add before PrintOut
Trace shows "Variable is undefined: xlDelimited" Excel constants not declared in project Add constant block from Section 4.1
Print job runs but paper is blank Wrong printer driver selected Verify driver in Windows Devices and Printers; choose PCL or PostScript
PDFCreator prints garbled characters CSV lacks BOM, font fallback fails Install Arial Unicode MS on the runtime PC

11. Performance and Throughput Notes

For high-frequency archive patterns (1 s or sub-second), Excel COM is the wrong tool. Each Open + PrintOut + Quit cycle takes 3-6 s on a typical RT PC. Use the native report print job (Section 7) for anything tighter than 30 s. PDFCreator COM is faster (1-2 s per print) but still adds latency on top of the archive step. Buffer print requests with an HMI tag and process them in a single batched job every N cycles.

12. Security and Hardening

  • Grant the WinCC runtime user only Modify rights on C:\historicos\Ph, never Full Control.
  • Disable the macro execution dialog in Excel (File > Options > Trust Center > Macro Settings > Disable all macros without notification) so that a malicious CSV cannot trigger code.
  • Lock down WScript.Shell in COM by setting the launch permissions via dcomcnfg if the runtime PC is multi-user.
  • Run the WinCC runtime service under a dedicated domain account, not as SYSTEM, so that print jobs inherit correct ACLs.
  • Sign the PDFCreator print profile so that the operator cannot redirect output to a USB stick.

Why does Excel shift my CSV columns when I print from WinCC?

The shift is caused by a locale separator mismatch between the CSV file and Excel's regional setting. Use Workbooks.OpenText with explicit Semicolon:=True or Comma:=True instead of Workbooks.Open, and set objExcel.DecimalSeparator = "." before opening the file.

Can I print a CSV from a Comfort Panel without Excel?

No. The Excel COM path requires WinCC Runtime Advanced on a Windows PC. On a Comfort Panel, use the native RT Professional report print job with the Printer option enabled under Properties > Properties > Output > Print output as documented in the Siemens TIA Portal V20 help.

Which is more reliable for 24/7 operation: Excel COM or PDFCreator COM?

PDFCreator COM. Excel COM leaks processes under high frequency and is sensitive to Office updates. For panels running an archive every minute, switch to PDFCreator or to the native report print job to avoid excel.exe accumulating in memory.

How do I avoid the "file in use" error when printing a CSV that WinCC is still archiving?

Insert a 1-3 second delay between the archive event and the print event. On a PC runtime, use WScript.Sleep 2000. On a Comfort Panel runtime, use the ping -n 3 127.0.0.1 trick inside a cmd.exe wrapper invoked by StartProgram.

What is the difference between StartProgram and calling shell.Run from VBScript?

StartProgram is a WinCC system function available directly in the button event configuration without writing any script. It supports hidden windows and waiting for completion but cannot return a process exit code. shell.Run from VBScript offers more control (return codes, error trapping, environment variables) but requires scripting rights on the runtime.

Back to blog