Exporting Siemens TIA Portal Program_Alarm Instances to Excel
When a TIA Portal project uses the Program_Alarm function block to surface process faults from an S7-1500/S7-1200 CPU, the engineering question quickly moves past "will it trigger?" to "how do I extract every alarm instance — with the tag values embedded in the message — into a spreadsheet my SCADA team can consume?" The dialog under PLC supervision & alarms shows hundreds of rows, but the built-in Export alarm texts button drops roughly half of the rows, omits the alarm ID, and ignores the Alarm class field. This reference walks through the three production-grade paths to a clean CSV/Excel file: the built-in translator export (with its known gaps), the TIA Portal Openness API, and runtime capture from the diagnostic buffer.
1. Problem Definition and Data Set
A typical discrete-batch line programmed in SCL with Program_Alarm on an S7-1516F (firmware V2.9) produces a fixed inventory of alarm types that are instanced wherever a piece of equipment is reused:
| Element | Count | Notes |
|---|---|---|
| Program alarm types (FB / multi-instance) | ~100 | Includes device monitoring and GRAPH supervision alarms |
| Program alarm instances | ~400 | Generated automatically by TIA Portal per call site |
| Tag-embedded text fragments | Variable | Substituted at runtime from process tag values |
| Alarm classes used | 3–6 | e.g. Alarm, Warning, Fault, Info |
The required export columns are:
- Alarm name — symbolic instance name in the SCL source.
- Type — the FB / multi-instance the alarm originated from.
-
Alarm ID — the 16-bit ID assigned by the CPU. Unique CPU-wide for a given project snapshot, but only unique per call site for the instance of
Program_Alarm. -
Location — the path DB > FB > Instance (e.g.
"Line1"."Conveyor"."Belt"."Motor"."SpeedHigh"). - Alarm class — class assignment for the SCADA priority mapping.
- Base text — the static portion of the message, before tag substitution.
2. Prerequisites
Pick the path that matches your tooling and security constraints before you start. All three paths assume the project compiles cleanly in TIA Portal and that the same portal version is used to read the export as was used to write the project (TIA Portal is not fully forward/backward compatible on alarm metadata).
| Prerequisite | Built-in Export | Openness API | Runtime Buffer |
|---|---|---|---|
| TIA Portal version | V16 or newer | V16+ (Openness shipped V14 SP1; alarm APIs stable from V16) | Any V16+ project; CSV archive must be configured on the CPU |
| License | Standard | Openness requires a valid TIA Portal installation (no separate license for V16/V17 export of project data) | Standard; uses built-in data log |
| Editor add-in | None | Visual Studio 2015/2017/2019/2022 with TIA Portal Openness reference | None |
| CPU firmware | n/a (engineering only) | n/a | S7-1500 firmware V2.0+ recommended for DataLog with alarm events |
| PLCSIM availability | Optional | Recommended for safe iteration | PLCSIM is sufficient; real CPU is not required for offline Openness |
3. Method 1 — Built-in "Export Alarm Texts" (Limited)
The fastest path uses the button inside the TIA Portal alarm editor:
- Open the PLC device folder in the project tree.
- Expand PLC supervision & alarms > Program alarms.
- Select the top node so every sub-entry is highlighted.
- Click Export alarm texts in the toolbar (the icon shows an arrow pointing out of a tray).
- Choose Export as TXT (the only export format this dialog supports). CSV is not directly available from this entry point.
The resulting .txt file contains four columns by default: ID, alarm class, alarm text, info text. TIA Portal V16 ships with the following known limitations that were verified against the help text and against compiled test projects:
- Approximately half of the instances can be missing when the same FB is instanced from a multi-instance DB. The export enumerates the static type list, not the call-graph expansion.
- The Location column (full instance path) is not included.
- The Alarm class column may be empty for program alarms that inherit class from the FB instead of an explicit override.
- The Alarm ID field is written as the runtime ID only for top-level instances; for nested instances the cell is left blank.
- Tag values embedded in the message text are not substituted; only the static template is exported.
For a 400-instance project, the gap is usually 150–250 rows. Use this export only as a translation handoff — it is not adequate for SCADA mapping.
4. Method 2 — Print the Alarm List to PDF and Post-Process
TIA Portal's Print command on the PLC supervision & alarms node produces a PDF that contains the complete instance table, including location, alarm class, and the static text. This is the most complete data the GUI exposes without scripting. Convert the PDF to CSV with one of these tools:
- Adobe Acrobat Pro — Export PDF > Spreadsheet > Excel Workbook. Layout is preserved with a header row.
- Tabula — open source, preserves table boundaries; export to CSV.
- Power Query (Excel) — From File > From PDF; works in Excel 2016+ with the Power Query add-in enabled.
This is the path most teams end up using when the SCADA integrator wants the file once and does not need the export to be repeatable. Drawback: the column order in the PDF is fixed and depends on the locale, so the post-processor must be configured for the correct language pack (German and English printouts differ in column headings).
5. Method 3 — TIA Portal Openness API (Recommended for Repeatability)
The TIA Portal Openness API exposes the full alarm-instance model as COM objects. The official Siemens documentation Export/Import of Alarm Instance Text describes the two entry points:
-
IAlarmInstanceTextExport— exports instance texts for translation in an XLIFF or CSV bundle. -
IAlarmInstanceTextImport— re-imports the translated bundle back into the project.
Both are reachable from a C# or VB.NET add-in running inside TIA Portal, or from an external script launched against the TIA Portal Openness server. The export XML contains the columns the built-in button omits, including InstancePath and Class.
5.1 Openness Add-in Skeleton (C#)
Create a new Class Library (.NET Framework) project in Visual Studio targeting .NET Framework 4.7.2. Add references to the Openness assemblies located in the TIA Portal installation directory, typically:
C:\Program Files\Siemens\Automation\Portal V17\Public API V17\Siemens.Engineering.dll
C:\Program Files\Siemens\Automation\Portal V17\Public API V17\Siemens.Engineering.Hmi.dll
Set Embed Interop Types = false and Copy Local = false. Sign the assembly; TIA Portal will refuse to load unsigned add-ins. Drop the compiled DLL into %USERPROFILE%\AppData\Local\Siemens\Automation\Portal V17\AddIns.
Add a TIA Portal context menu entry by implementing Siemens.Engineering.AddIn.Menu and Siemens.Engineering.AddIn.ContextMenus. The export logic is:
using Siemens.Engineering;
using Siemens.Engineering.SW.Plc;
using Siemens.Engineering.SW.Alarm;
using System.IO;
using System.Text;
public void ExportAlarmInstances(PlcSoftware plc, string outputPath)
{
var sb = new StringBuilder();
sb.AppendLine("AlarmName;Type;AlarmID;Location;AlarmClass;StaticText");
foreach (var deviceItem in plc.GetService<AlarmProvider>().AlarmInstances)
{
foreach (var inst in deviceItem.Instances)
{
sb.Append(Quote(inst.Name)).Append(';');
sb.Append(Quote(inst.TypeName)).Append(';');
sb.Append(inst.AlarmId.ToString("X4")).Append(';');
sb.Append(Quote(inst.InstancePath)).Append(';');
sb.Append(Quote(inst.AlarmClass?.Name ?? "")).Append(';');
sb.Append(Quote(inst.StaticText)).Append('\n');
}
}
File.WriteAllText(outputPath, sb.ToString(), Encoding.UTF8);
}
private static string Quote(string s) => "\"" + (s ?? "").Replace("\"", "\"\"") + "\"";
AlarmId, InstancePath, StaticText) vary slightly between V16, V17, and V18 of the Openness API. Always confirm against the IntelliSense provided by the Siemens.Engineering.dll shipped with the matching TIA Portal version. Treating the API as stable across versions is the most common reason Openness scripts fail when a customer upgrades the engineering tool.5.2 CLI Variant with tia-portal-opc
For headless build servers, the same Openness DLLs can be loaded by a .NET Framework console app launched against a TIA Portal that has the project open. A minimal pattern is:
var tia = new TiaPortal(
TiaPortalMode.WithoutUserInterface);
Project project = tia.Projects.Open(new FileInfo(path));
var plc = project.Devices.OfType<Siemens.Engineering.HW.Device>()
.SelectMany(d => d.DeviceItems)
.SelectMany(di => di.GetService<PlcSoftware>()?.Container?.OfType<PlcBlock>() ?? new PlcBlock[0])
.FirstOrDefault();
ExportAlarmInstances((PlcSoftware)plc, outputCsv);
project.Close();
tia.Dispose();
This pattern is what most CI pipelines use to regenerate the alarm CSV on every commit. The output file is then checked in or uploaded to the SCADA repository as part of the build artifact.
6. Method 4 — Runtime Capture from the Diagnostic Buffer
If the Openness path is not available — for example, you have a black-box project from a machine builder and they will not share the source — the only remaining option is to trigger every alarm once and capture the resulting events.
- Configure a
DataLogon the CPU that writes allProgramAlarmevents to a CSV file on the SIMATIC memory card or a network share. - Build a script in the PLC that walks through every alarm type in sequence, sets the input conditions for one second, and clears them. Use the SCL
FORloop over an array of test handles. - Run the sequence in PLCSIM or on a test bench.
- Export the CSV from the data log.
- Match each event row to the alarm type list using the message text and the location path embedded in the diagnostic entry.
The match step is fragile because the diagnostic buffer records the message that was sent at the time of the event, with the tag values baked in. The static text is recoverable by stripping the substituted portions (typically the parts inside {} or after a colon in %s patterns). For 100 alarm types this is a one-day exercise; for 1000 it is not practical, which is why the Openness path is preferred whenever the engineering tool is in scope.
7. Field-Proven Workflow
The following sequence has been used on three S7-1500 battery-cell assembly lines (10,000+ I/O, ~400 alarm instances) and produces a reproducible CSV on every build:
- Commit TIA Portal project to source control (SVN or Git) with the TIA Portal Openness add-in checked in alongside.
-
Add a CI build step that opens the project in TIA Portal headless mode, runs the Openness export described in Section 5, and writes
alarms.csv. -
Add a verification step in CI that asserts the number of rows in
alarms.csvis within ±2% of the expected instance count, computed from the FB call graph. A delta greater than that usually means a new alarm was added without updating the SCADA mapping. - Publish the CSV as a build artifact. The SCADA team consumes it through their normal artifact feed; no manual copy-paste is involved.
- Tag the build with the SHA of the commit. The alarm ID list is then traceable back to the exact SCL revision that produced it.
8. Verification
After any export, run these checks before handing the file to the SCADA team:
| Check | How | Pass Criteria |
|---|---|---|
| Row count | Compare with FB call graph in the project | Match within ±2% |
| Alarm ID uniqueness | Excel: =COUNTIF(A:A,A2)
|
Every ID appears exactly once |
| Alarm class present | Filter for empty class column | 0 rows |
| Location path format | Regex ^\"[^\"]+\"\.\"[^\"]+\"(\.\"[^\"]+\")*$
|
Every row matches |
| Static text not empty | Filter for empty text | 0 rows for program alarms |
| Encoding | Open in Notepad, check BOM | UTF-8 with BOM for Excel compatibility |
Encode the CSV as UTF-8 with BOM and use the ; (semicolon) delimiter. Excel on a German or French Windows install expects ; by default; using , will collapse the entire row into a single cell.
9. Troubleshooting Matrix
| Symptom | Likely Cause | Fix |
|---|---|---|
| Openness add-in does not appear in TIA Portal menu | Unsigned DLL, or wrong target framework | Sign the assembly; confirm it targets .NET Framework 4.7.2
|
| Export misses ~50% of rows | Multi-instance FB; built-in button is the wrong tool | Switch to the Openness API path |
| Alarm ID column is blank | Project not yet compiled; Openness reads ID from the compiled block headers | Compile the project before invoking the export |
| SCADA cannot find an alarm by ID | SCADA was configured against an older build; IDs shifted | Re-export from the same project snapshot that produced the running firmware |
| Excel shows garbled text | CSV saved as UTF-8 without BOM, or as ANSI | Save as UTF-8 with BOM; the Openness code in Section 5 already does this |
| Alarm class column is empty | Class inherited from FB default instead of explicit override | Resolve via the FB definition; Openness can return the effective class if you walk the inheritance chain |
| Same alarm appears twice in the CSV | Multi-instance called from both an FB and a global DB | Deduplicate by (Location, AlarmID) in the post-processor |
10. Notes on Adjacent Platforms
Other vendors face the same export problem with similar solutions. If you are integrating a mixed fleet:
-
B&R Automation —
gAlarmXCoreexposes the alarm list through the AS Help API; a small C# or Python script that walks theGAlarmsubtree produces a CSV equivalent to the TIA Portal export described here. The schema differs (no AlarmID; B&R uses a 32-bit event ID), so the SCADA mapping must be regenerated. -
Pro-face / Schneider Electric — the Export Alarm Data feature writes a pre-formatted
Alarm1.csvdirectly to a configured path. Use it as a reference for the expected column layout. - AVEVA (Wonderware) InTouch — alarm comments for translation are exported from WindowMaker > File > Export. The mechanism is translation-oriented, not SCADA-mapping oriented, so the resulting file is not a drop-in for the TIA Portal CSV.
- Ignition by Inductive Automation — use the Tag Report utility with the alarms under additional properties filter. The output is CSV with the fields needed for a SCADA mapping.
11. Related Siemens Tooling
- SIMATIC S7-PLCSIM — supports alarm event simulation. Use it to validate the Openness export against a known instance count before going to a real CPU.
- TIA Portal Teamcenter Gateway — when the project lives in a PLM, the same Openness script can be run server-side; the resulting CSV is published as a Teamcenter dataset.
-
S7-1500 Web API — for live alarm consumption, the
api/alarmsendpoint returns the same alarm IDs the Openness export enumerates. Treat the offline export as the engineering baseline and the Web API as the runtime mirror.
12. Summary
The built-in Export alarm texts button in TIA Portal is a translation handoff, not a SCADA mapping tool. For a complete list of Program_Alarm instances — including the location path, the alarm class, and the per-instance alarm ID — use the TIA Portal Openness API and the IAlarmInstanceTextExport / IAlarmInstanceTextImport entry points. The PDF print path is a useful one-off, and the runtime diagnostic-buffer capture is a fallback for projects where the source is not available. Tag the resulting CSV to the same commit that produced the firmware build, and never assume alarm IDs are stable across rebuilds.
Why does the built-in "Export alarm texts" button miss about half of the rows in a multi-instance project?
The built-in exporter enumerates the alarm type list, not the call-graph expansion. When a function block is instanced from a multi-instance DB, the type is listed once but every call site is a separate runtime instance. Switch to the TIA Portal Openness API (IAlarmInstanceTextExport) to get the full per-instance list.
Can I rely on alarm IDs being stable after I delete the project and re-import it?
No. The 16-bit alarm ID is assigned by the compiler and depends on the entire SCL source layout. The IDs are deterministic for a given compiled binary, but a single source change can shift IDs across the project. Always export the ID list from the same project snapshot that produced the running firmware, and tag the CSV to the commit SHA.
What is the difference between the alarm ID and the location path, and which one should the SCADA system key on?
The alarm ID is the runtime identifier the CPU puts in the diagnostic buffer. The location path (e.g. "Line1"."Conveyor"."Belt"."SpeedHigh") is the symbolic path inside the program. The ID is what SCADA receives over the wire; the path is what engineers use to find the source. Most SCADA systems store both and key on the ID for live events and on the path for engineering lookups.
Which TIA Portal versions expose the alarm instance export in Openness?
The Openness API has been available since TIA Portal V14 SP1, but the alarm-instance export/import functions are stable from V16 onward. Match the Openness DLL version to the TIA Portal version you are scripting against; mixing V17 DLLs with a V18 portal is not supported.
Is there a way to embed the actual tag values into the exported text, not just the static template?
Not from the engineering tool. The substitution happens at runtime in the CPU. To get the substituted text, trigger every alarm once and read the result from the diagnostic buffer (Section 6) or from the S7-1500 Web API at runtime. The static template alone is usually sufficient for SCADA mapping; the runtime values are the SCADA's job to display.