Adding Logo and Borders to Excel Reports in WinCC Flexible 2008

David Krause17 min read
SiemensTutorial / How-toWinCC
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

Adding Logo and Borders to Excel Reports in WinCC Flexible 2008 SP2 Runtime

WinCC Flexible 2008 SP2 Runtime does not expose a built-in, dialog-driven way to embed a corporate logo or to apply cell borders inside the formatted output of an Excel report. The standard report object writes tag values, alarm archives, and process values into a defined layout, but the visual treatment of the report — header graphics, lines, frames, and corporate identity elements — must be carried in by the template. The supported and field-proven approach is to author a fully formatted Excel template (.xlt or .xls) that already contains the company logo, header text, cell borders, fonts, and number formats, and to use a VBScript function in the WinCC Flexible project to copy this template, populate it from runtime tags, and save the result under a runtime-generated filename. This article documents that workflow end-to-end with code, parameter tables, and the diagnostic checks that commissioning engineers typically need.

Scope. This procedure targets the Windows-based WinCC Flexible 2008 SP2 Runtime (PC RT) where Excel automation via CreateObject("Excel.Application") is supported. WinCE-based Panel RTs do not host Excel and cannot use this approach. For current-generation TIA Portal projects use the WinCC Unified Excel Reporting add-in workflow instead.

1. Architecture: How Excel Reporting Works in WinCC Flexible 2008

WinCC Flexible 2008 SP2 ships two native report objects that can target Excel as a print/export target:

  • Report (alarm / process value log) — drawn from the configured alarm archive or process value archive and rendered through a layout. Excel export is available when the layout is configured with a spreadsheet target.
  • Recipe report — produces a single-line-per-ingredient tabular view of a recipe set; it is the closest native analog of a "batch sheet" and is the layout the source conversation modified.

Both objects are bound to a layout file stored on the runtime filesystem. Layout files in WinCC Flexible are proprietary and do not give access to the chart-frame, picture-insertion, or border properties the customer requested. The widely deployed and Siemens-supported workaround is to drive Excel directly from a VBScript triggered by a button, a scheduled task, or a value-change on a tag. The script becomes the layout.

The runtime model is therefore:

HMI Tag (Batch_ID, PVs...) VBScript Function On scheduled/event Excel COM CreateObject("Excel.Application") Template.xlt (logo + borders) Runtime file Report_<BatchID>.xls

When the script fires, the template is opened, the placeholder cells are written with live tag values, and a new workbook is written to the report destination. The original template is never modified, so every batch report inherits the customer's branding and frame automatically.

2. Prerequisites

  1. Microsoft Excel installed on the RT PC. A 32-bit Excel installation is recommended when the WinCC Flexible RT is 32-bit; mixing 32/64-bit Office with 32/64-bit RT will not work because VBScript binds to the first matching registered class id.
  2. WinCC Flexible 2008 SP2 (or SP3/SP4) engineering software with a project compiled for the PC RT target.
  3. VBScript editor access on the RT, enabled in Project > Settings > Runtime Settings > Services. The default is enabled; verify before commissioning.
  4. Write permission for the runtime user account on the directory that will hold the template and the generated reports. On a multi-user RT, the path should be on a local fixed disk or a UNC path the RT service can reach; mapped network drives lose their mapping when the RT runs as a service.
  5. Template authoring workstation with Excel 2003/2007/2010. The template should be saved as Excel 97-2003 Workbook (.xls) if any RT PC still has Office 2003, or as Excel Template (.xlt) when forcing the file to be treated as a template on open.
Excel security. From Excel 2007 onward, the Trust access to the VBA project object model flag must be enabled on the RT PC or the script will fail with error 1004. Set it under File > Options > Trust Center > Trust Center Settings > Macro Settings. For automation that only writes values to cells (no VBA macro execution in the file), the default macro-disable level is acceptable as long as the workbook is opened and not run.

3. Step 1 — Author the Excel Template with Logo and Borders

Open a new workbook in Excel and lay out the report as it should look at runtime. The convention is to designate specific cells as data cells and to leave every other cell fully formatted. The script only writes to the data cells.

3.1 Cell layout convention

Range Type Content (template) Written by script?
A1:F1 Merged header Company name + tagline, Calibri 16pt bold No
A2:F2 Image anchor Company logo (.png/.bmp/.jpg) inserted via Insert > Picture No
A4:F4 Section header "Batch Production Report", bordered No
A5 Label "Batch ID" No
B5 Data cell (empty, format: text) Yes — SmartTags("Batch_ID")
A6 Label "Operator" No
B6 Data cell (empty, format: text) Yes — SmartTags("Operator")
A7 Label "Start time" No
B7 Data cell (empty, format: yyyy-mm-dd hh:nn:ss) Yes — SmartTags("Batch_Start")
A8 Label "End time" No
B8 Data cell (empty, format: yyyy-mm-dd hh:nn:ss) Yes — SmartTags("Batch_End")
A10:F25 Measurement table Header row + empty rows, full borders Yes — loop writes row by row

3.2 Applying cell borders

Select the report range (e.g. A4:F25) and apply borders from the ribbon. The Microsoft Excel support article on cell borders documents the user-interface path and the underlying constants used by the Excel object model. The same constants are reused by the script in step 4.

VBScript constant Decimal Border edge
xlDiagonalDown 5 Diagonal from top-left to bottom-right
xlDiagonalUp 6 Diagonal from bottom-left to top-right
xlEdgeBottom 9 Bottom edge of the range
xlEdgeLeft 7 Left edge of the range
xlEdgeRight 10 Right edge of the range
xlEdgeTop 8 Top edge of the range
xlInsideHorizontal 12 Horizontal lines between rows
xlInsideVertical 11 Vertical lines between columns

Recommended pattern for a corporate frame is to set xlEdgeTop, xlEdgeBottom, xlEdgeLeft, xlEdgeRight to Thin / Continuous / Automatic, and the inside lines to Hairline / Continuous / Automatic. This combination is readable on print and survives a highlighter pass from a quality auditor.

3.3 Inserting the company logo

Place the cursor in cell A2 (or any cell that will hold the image) and use Insert > Pictures > This Device. Anchor the picture To Cell, untick Move with cells only if you want the image pinned to its row during sorting — for a report it should be anchored to the cell. Acceptable formats are PNG, JPG, BMP, GIF, and TIFF; PNG at 150-300 DPI gives the best print quality without bloating the file. A logo of 200×60 pixels at 96 DPI fits a typical header band and keeps the workbook under 100 kB.

Template size. Avoid embedding photos or other high-resolution images. Each generated report inherits the image stream, so a 2 MB photo multiplied by 200 batches/day is 400 MB/day of disk churn.

3.4 Save the template

Save the workbook as report_template.xlt into the runtime-visible path, typically:

  • Local RT folder: C:\Program Files\Siemens\Automation\WinCC Flexible 2008 RT\Reports\report_template.xlt
  • Or an operator-facing path: D:\Reports\report_template.xlt

Use Save As > Excel Template (.xlt) to flag the file as a template. Excel will then open it as a copy in memory, leaving the original untouched. If you save as .xls instead, the script must explicitly use SaveAs to write a new file, which is the approach the source conversation adopted.

4. Step 2 — Configure the Runtime Storage Path

The runtime needs read access to the template and write access to the report destination. In the engineering project, declare both paths as paths so they can be edited at the panel without re-compiling:

  1. Open Project > Paths.
  2. Add REPORT_TEMPLATE pointing to the .xlt location.
  3. Add REPORT_DESTINATION pointing to the output directory (e.g. D:\Reports\Archive\).

These are not filesystem variables — they are project constants surfaced under Runtime > Project Settings > Paths on the target. Keep them lowercase on the filesystem; Excel does not care, but case-sensitive backup tools do.

5. Step 3 — Write the VBScript Function

The function below opens the template, writes the tag values into the placeholder cells, applies a thicker border around the measurement block, embeds a logo if the template does not already have one, and saves the result. It is the same skeleton that ships in customer projects derived from the source conversation, extended with explicit object cleanup, error handling, and configurable paths.

'--------------------------------------------------------------
' WinCC Flexible 2008 SP2 RT — Excel Report Generator
' Trigger: scheduled task, button press, or value-change on
'          tag "Generate_Report_Trigger"
'--------------------------------------------------------------
Option Explicit

Const xlContinuous      = 1
Const xlAutomatic       = -4105
Const xlThin            = 2
Const xlMedium          = -4138
Const xlEdgeTop         = 8
Const xlEdgeBottom      = 9
Const xlEdgeLeft        = 7
Const xlEdgeRight       = 10
Const xlInsideHorizontal= 12
Const xlInsideVertical  = 11
Const msoTrue           = -1
Const msoFalse          = 0

Sub Generate_Batch_Report()
    Dim objExcel, objWkb, objWks, objFSO, objFolder
    Dim sTemplate, sDestDir, sBatchID, sOutFile, sErr
    Dim iRow, iCol

    On Error GoTo EH

    '--- 1. Resolve paths from project constants ---
    sTemplate = SmartTags("REPORT_TEMPLATE")
    sDestDir  = SmartTags("REPORT_DESTINATION")
    sBatchID  = SmartTags("Batch_ID")

    '--- 2. Validate inputs ---
    If Len(sTemplate) = 0 Or Len(sDestDir) = 0 Or Len(sBatchID) = 0 Then
        SmartTags("Report_Status") = "E: missing path or batch id"
        Exit Sub
    End If

    '--- 3. Ensure destination directory exists ---
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    If Not objFSO.FolderExists(sDestDir) Then objFSO.CreateFolder sDestDir

    '--- 4. Launch Excel invisibly ---
    Set objExcel = CreateObject("Excel.Application")
    objExcel.Visible        = False
    objExcel.DisplayAlerts  = False
    objExcel.ScreenUpdating = False

    '--- 5. Open the template (logo + borders pre-applied) ---
    Set objWkb = objExcel.Workbooks.Open(sTemplate, , True)  ' ReadOnly=True keeps template intact
    Set objWks = objWkb.Sheets(1)

    '--- 6. Optional: dynamically insert a logo if template lacks one ---
    If objWks.Shapes.Count = 0 Then
        objWks.Shapes.AddPicture _
            Replace(sTemplate, "report_template.xlt", "company_logo.png"), _
            msoTrue, msoTrue, 10, 10, 200, 60
    End If

    '--- 7. Write tag values to placeholder cells ---
    With objWks
        .Range("B5").Value = sBatchID
        .Range("B6").Value = SmartTags("Operator")
        .Range("B7").Value = SmartTags("Batch_Start")
        .Range("B8").Value = SmartTags("Batch_End")

        ' Measurement block A10:F25 — write 16 rows from array tag
        For iRow = 0 To 15
            .Cells(11 + iRow, 1).Value = iRow + 1
            .Cells(11 + iRow, 2).Value = SmartTags("Meas_Name_"  & (iRow + 1))
            .Cells(11 + iRow, 3).Value = SmartTags("Meas_Value_" & (iRow + 1))
            .Cells(11 + iRow, 4).Value = SmartTags("Meas_Unit_"  & (iRow + 1))
            .Cells(11 + iRow, 5).Value = SmartTags("LSL_"        & (iRow + 1))
            .Cells(11 + iRow, 6).Value = SmartTags("USL_"        & (iRow + 1))
        Next iRow
    End With

    '--- 8. Re-assert borders on the measurement block in case
    '        the template author left them off ---
    With objWks.Range("A10:F26").Borders
        .Item(xlEdgeTop).LineStyle  = xlContinuous : .Item(xlEdgeTop).Weight  = xlMedium
        .Item(xlEdgeBottom).LineStyle=xlContinuous : .Item(xlEdgeBottom).Weight=xlMedium
        .Item(xlEdgeLeft).LineStyle = xlContinuous : .Item(xlEdgeLeft).Weight = xlMedium
        .Item(xlEdgeRight).LineStyle= xlContinuous : .Item(xlEdgeRight).Weight= xlMedium
        .Item(xlInsideHorizontal).LineStyle = xlContinuous
        .Item(xlInsideVertical).LineStyle   = xlContinuous
    End With

    '--- 9. Save under runtime-generated filename ---
    sOutFile = sDestDir & "Report_" & sBatchID & "_" & _
               FormatDateTime(Now, 2) & "_" & _
               FormatDateTime(Now, 4) & ".xls"
    sOutFile = Replace(sOutFile, "/", "-")    ' Excel does not like / in sheet names
    objWkb.SaveAs sOutFile, -4143            ' xlWorkbookNormal

    SmartTags("Report_Status")   = "OK: " & sOutFile
    SmartTags("Report_FilePath") = sOutFile

    '--- 10. Clean up ---
    objWkb.Close False
    objExcel.Quit
    Set objWks = Nothing : Set objWkb = Nothing : Set objExcel = Nothing
    Set objFSO = Nothing
    Exit Sub

EH:
    sErr = "E" & Err.Number & " " & Err.Description
    SmartTags("Report_Status") = sErr
    If Not objWkb Is Nothing Then objWkb.Close False
    If Not objExcel Is Nothing Then objExcel.Quit
    Set objWks = Nothing : Set objWkb = Nothing : Set objExcel = Nothing
    Set objFSO = Nothing
End Sub

5.1 Code notes

  • Workbooks.Open(sTemplate, , True) opens the file in read-only mode so the original template is not modified. The subsequent SaveAs writes a new workbook to the destination.
  • objExcel.DisplayAlerts = False suppresses the "Keep current format?" prompt that Excel shows when saving an .xls from a newer Excel version. Set this to True during commissioning to see the dialogs and identify the format being written.
  • Border constants are defined at the top of the module. xlContinuous = 1 is the only line style used for solid corporate frames; the Microsoft Excel cell borders reference documents the full set.
  • The FormatDateTime(Now, 2) returns yyyy/mm/dd on most locales; replace the date formatter with a fixed format string if your plant enforces a particular naming convention.

6. Step 4 — Bind the Script to a Trigger

There are three trigger patterns in WinCC Flexible 2008 that engineers typically choose between:

Trigger Where configured Use case Limitation
Scheduled task (cyclic / once) Project > Schedules End-of-shift report, daily summary Drift between trigger time and PC clock
Tag change Tag properties > Events End of batch (Batch_ID transitions to a new value) Edge detection required
Button click Button properties > Events > Press Operator-driven ad-hoc report Operator must be on the right screen

For batch reporting the recommended binding is tag change on a Boolean or integer trigger tag. Configure the tag with an event that calls Generate_Batch_Report on a rising edge only. A common implementation writes a one-shot pulse from the PLC (0 → 1 → 0) and uses the rising edge to fire the report. This avoids duplicate reports when the runtime reads the same value twice.

7. Border and Logo Reference Tables

The following tables consolidate the Excel object-model constants the script uses. They are the same constants a user would set in the Excel UI; the script reaches them programmatically.

7.1 LineStyle constants

Constant Value Appearance
xlContinuous 1 Solid line
xlDash -4115 Dashed
xlDashDot 4 Dash-dot
xlDashDotDot 5 Dash-dot-dot
xlDot -4118 Dotted
xlDouble -4119 Double line
xlLineStyleNone -4142 No line

7.2 Weight constants

Constant Value Use
xlHairline 1 Inside grid lines
xlThin 2 Standard frame
xlMedium -4138 Section frame, headline band
xlThick 4 Outer frame on a corporate template

7.3 Shapes.AddPicture parameters

Parameter Type Meaning
Filename String Absolute path to the image file
LinkToFile Boolean msoTrue = linked, msoFalse = embedded (use msoFalse for portable reports)
SaveWithDocument Boolean msoTrue = save image inside the workbook
Left, Top Single Position in points (1 point = 1/72 inch)
Width, Height Single Display size in points
Embedded vs linked. Always set LinkToFile = msoFalse in a report that may be moved to a different folder or sent to a customer. A linked picture shows a red X the moment the original image is no longer reachable from the report's path.

8. Error Handling and Diagnostics

The most common failure modes seen in field deployments are listed below with their hex/decimal error codes and the corrective action.

VBScript error Hex / dec Typical cause Fix
ActiveX component can't create object 0x800A01AD / -2146827859 Excel not installed, or wrong bitness (64-bit RT with 32-bit Office) Install matching Office bitness; verify with CreateObject("Excel.Application") in a small test
Method 'Open' of object 'Workbooks' failed 0x800A03EC / -2146827252 Template path not reachable by the RT service Use an absolute local path; UNC paths must be reachable from the service account
Method 'SaveAs' of object '_Workbook' failed 0x800A03EC / -2146827252 Destination directory read-only, or filename contains illegal characters Strip / : * ? " < > | from filenames; verify write permission
File format is not valid 0x800A03EC / -2146827252 Template is .xlsx and Office 2003 is on the RT Re-save template as .xls (Excel 97-2003)
Subscript out of range 0x800A0009 / 9 Sheets(1) called on a workbook with no sheets (template corrupted) Open template manually, save again, re-deploy
Permission denied 0x800A0046 / 70 Template opened by another user (read-only on the network) Place template on the local RT disk; never on a shared editor's workstation

Two operational rules eliminate most of the entries above:

  1. Always store the template on a local fixed disk of the RT, never on a network share. The RT service may not have a mapped drive letter.
  2. Always set the template as read-only at the filesystem level so a misbehaving script cannot corrupt it. The script opens it with ReadOnly:=True for the same reason.

9. Verification and Commissioning

A sign-off script for the QA team should include the following checks. Run them once during Site Acceptance Test (SAT) and again on any Excel/Office update.

  1. Template path resolution — From the RT, open a command prompt under the same service account and confirm dir "%REPORT_TEMPLATE%" lists report_template.xlt.
  2. First-run end-to-end — Trigger the report manually from the HMI button. Confirm the new file appears in the destination, contains the logo in the header, and shows borders on the measurement block.
  3. 100-run stress — Loop the trigger 100 times with synthetic data. Verify (a) all 100 files are written, (b) file sizes are within 10% of each other, (c) the template file is unchanged (compare SHA-256).
  4. Edge cases — Trigger a report with an empty Operator tag. Trigger one with a Batch_ID containing a slash. Verify that the script does not crash and that the output filename has illegal characters replaced.
  5. Print preview — Open one of the generated files, send to print preview, and verify the logo and borders render on a real printer or to PDF.
  6. Multi-user — If the RT supports concurrent operators, trigger two reports within one second. Verify both are written and that Excel does not raise a "file in use" error. If it does, the script must serialize the calls with a single global mutex tag.

10. Performance and Runtime Footprint

Each report open Excel.Application starts a new EXCEL.EXE process. The WinCC Flexible RT is forgiving of this for low-frequency reports (end of batch, end of shift), but it is not appropriate for tag-change-rate triggers on fast processes. Approximate numbers from the field:

Action Typical duration (PC, x86, HDD)
Excel.Application cold start 1.2 – 2.0 s
Open 50 kB template 0.3 – 0.5 s
Write 16 rows + format 0.1 – 0.2 s
SaveAs .xls 0.4 – 0.6 s
Quit and cleanup 0.2 – 0.4 s
Total per report 2.2 – 3.7 s

For reports triggered more often than once per minute, consider keeping a single Excel.Application instance alive and reusing it via a long-lived script object. WinCC Flexible 2008 SP2 does not expose an in-process Excel server, so this is a workaround that is brittle across RT restarts and is not recommended in production for the typical batch-reporting workload.

Excel process leak. If the script terminates abnormally (e.g. RT power loss) the EXCEL.EXE can remain in memory. Add a watchdog that kills EXCEL.EXE at the start of each Generate_Batch_Report call if it has been idle for more than N minutes. Set objExcel = Nothing alone is not sufficient on a hard RT abort.

11. Migration Path to WinCC Unified

Customers continuing to use WinCC Flexible 2008 SP2 should be aware that the platform is in the legacy / extended support phase and that the Excel-COM approach above is replaced in current TIA Portal projects by the WinCC Unified Reporting add-in for Excel. The new workflow:

  1. Install the WinCC Unified Reporting add-in in Excel on the engineering station.
  2. Open the add-in and connect it to the Unified runtime; tag values are exposed as a connected data model.
  3. Author the report as a regular Excel file — the Reporting add-in in Excel page documents the enablement steps in the Trust Center.
  4. Publish the report template to the runtime; reports are generated server-side, not via per-report Excel launches.

The data-cell philosophy (write tags into fixed cells of a styled template) is identical between the two platforms, which makes the migration mechanical: the template can be reused, only the binding mechanism changes.

12. Reference Material

FAQ

Why does the company logo disappear or show a red X in the generated report?

The logo is linked to the original image file (LinkToFile = msoTrue), and the generated file was moved to a path that can no longer reach the image. Re-author the template with LinkToFile = msoFalse and SaveWithDocument = msoTrue so the image is embedded inside the workbook and travels with the file.

The script returns "ActiveX component can't create object" (0x800A01AD). What bitness do I need?

Install the same bitness of Microsoft Office as the WinCC Flexible 2008 RT. A 32-bit RT requires 32-bit Office. Mixed bitness (64-bit Office, 32-bit RT) fails to register the class id and the CreateObject call returns error -2146827859.

Can I apply borders to a range without a template, directly from the script?

Yes. Use the Range.Borders collection with the constants xlEdgeTop, xlEdgeBottom, xlEdgeLeft, xlEdgeRight, xlInsideHorizontal, and xlInsideVertical, and set LineStyle = xlContinuous and Weight = xlThin or xlMedium. The reference table in section 7.1 lists every line style and the Microsoft Excel borders documentation covers the UI equivalents.

How do I prevent the template from being overwritten by a misbehaving script?

Open the template with Workbooks.Open(sTemplate, , True) so Excel opens it read-only, and set the filesystem permission on the .xlt to read-only for the RT service account. The script writes a new file via SaveAs, leaving the original template byte-identical (verifiable with SHA-256).

How many reports per minute can the WinCC Flexible 2008 SP2 RT generate this way?

Field measurements show 2.2 to 3.7 seconds per report including Excel cold start. The practical ceiling is roughly 15-20 reports per minute on a typical industrial PC. For higher rates, use a pooled Excel.Application instance (not recommended for long-running RT) or migrate to the WinCC Unified server-side reporting pipeline.

Back to blog