# Exporting a run

> The portable copies and the generated PDF of a run: what each verb needs, how the files are named, and exactly what a CSV, an XLSX, a GLAB and a PDF contain.

The strip above the open run carries the portable copies first, then the generated
documents ([The run record](histories-record#the-strip)). The four verbs below take the
**Export/import histories** permission, and all four are reads of the run file: they stay
available while the runtime is stopped and while a unit records, and none of them writes
anything into the run.

The strip carries a fifth verb, **New label**, which is neither an export nor a read: it
emits a label into the run and is recorded there as evidence of it, so it takes **Run
procedures** instead of the export permission and is described with the documents it
belongs to ([Labels and reports](histories-documents)).

| Verb | Produces | Available for | Lands |
| --- | --- | --- | --- |
| Export CSV | The raw datalog as text. | Any run, including one still recording. | A browser download, on the station's own window as well ("Exported CSV · file"). |
| Export XLSX | An Excel workbook with the run identity, the metadata and the typed datalog. | Any run, including one still recording; a run that has recorded nothing yet answers "The run has no header snapshot yet. Try again in a moment." | A browser download ("Exported XLSX · file"). |
| Export GLAB | The whole run as one portable `.glab` file another station can import. | Completed, Aborted or Failed runs only. | A browser download ("Exported GLAB · file (size)"). |
| Generate PDF | A fresh report PDF composed from the whole run with the layout the picker selects. | Any run that has finished recording. | The reports folder of the data root, then opened. |

A mid-run CSV or XLSX export is a consistent partial copy: the frozen header is written
when the run starts, so the export carries the full column set and the rows recorded so
far, read through the live recording rather than a second connection to the file. Every
date and time in an export follows the format configured in
[Settings](settings-localization), and each file declares the reference its stamps are
read in: "UTC" or "UTC±hh:mm", the station's offset at export time.

## File names {#file-names}

CSV, XLSX, GLAB and PDF share one base name per run: the start instant in the station's
date and time format with the separators made file-safe, then the model, the unit and the
procedure names ("02-09-2026 14-05-30 - Climatic chamber - Unit 1 - Soak test"), each part
shortened to 48 characters and stripped of characters Windows refuses. The base is reserved
durably, so repeated exports of one run keep the same name across restarts, and only a
different run that would land on the same name receives a short suffix from its identity.
A report emitted by an action adds the group's name after the base; a PDF generated here
keeps the plain base. Every file is completed under a temporary name and published only
when complete, so a cancelled export never leaves a partial file with the product
extension.

## CSV {#csv}

One **Timestamp** column, headed "Timestamp (UTC-03:00)" with the time reference, then,
per recorded channel in the frozen column order, a value column headed by the channel name
with its engineering unit in brackets ("Temperature [°C]") and a quality column beside it
("Temperature [°C] Quality") reading **Good** or **Unavailable**. The value column keeps
whatever the datalog stored (blank when nothing was), booleans read `true`/`false`, a
date-typed channel reads in the station's format, and a value containing the separator, a
quote or a line break is quoted. A text cell beginning with `=`, `+`, `-` or `@` is prefixed
with an apostrophe so a spreadsheet reads it as text and not as a formula: the channel names
in the header and a string channel's readings, which come from the equipment. Numbers are
never prefixed, so a negative reading stays a number.

The file follows the station's decimal-separator preference: with point decimals the list
separator is `,`; with comma decimals it is `;`, so the file opens cleanly in a
spreadsheet of that locale. Numbers are written without a thousands separator, at the
datalog's full stored precision. The text is UTF-8.

## XLSX {#xlsx}

The workbook opens with a **Run** sheet, two columns headed Field and Value:

| Field | Content |
| --- | --- |
| Run ID | The run's unique identity. |
| Run Name, Model, Model Revision, Unit, Procedure | The names frozen when the run recorded; a field the run has no value for is blank. |
| Started At, Finished At | The run's bounds. A run still recording reads **In progress** for Finished At. |
| Time Zone | The reference every instant in the workbook is read in. |
| State | The lifecycle state at export. |
| Result | The verdict, or **In progress** while the run is still recording. |
| Termination | None, or StopInterlock. |
| Interval (ms) | The recording interval. |
| Imported At, Imported From | Only on a copy imported from another installation: when it arrived here and the received file it came from. A run recorded here carries neither row. |
| Notes | The run's notes. |

A second header, Metadata and Value, follows with one row per metadata field recorded at
Start, in prompt order. One or more **Datalog** sheets follow, in the same column order as
the CSV, with the header row frozen, an autofilter on every sheet and no grid lines. A
datalog longer than Excel's 1,048,576-row sheet limit splits automatically into
**Datalog 2**, **Datalog 3**, and so on, each with its own header.

Values are written as typed cells: integers and finite decimals as native numbers at the
datalog's full stored precision, booleans as native TRUE/FALSE. Excel itself works with at
most 15 significant digits, so digits beyond that are not shown there, though the file
carries them. A non-finite reading, a date-typed channel and the timestamps are text; a
reading whose quality is **Unavailable** leaves its value cell empty, with the quality
column saying so. A run that would need more than Excel's 16,384 columns, or a text cell
over its 32,767-character limit, is refused with the reason instead of producing a
truncated workbook.

## GLAB {#glab}

The `.glab` file is a consistent, page-level copy of the run's own SQLite file, taken
online: no archive wrapper, no manifest, no derived documents and no published PDF. It
carries everything the run file carries: the frozen snapshot, the rows, the metadata, the
recipe writes, the criteria, the occurrences, the comments, the annotations, the
productivity records, the label artifacts with their frozen bytes and the report
registrations with any copy they kept. It uses the same base name as the other exports and
is only published once completely written. Another station takes it back in through
[Importing runs](histories-import).

## PDF {#pdf}

**Generate PDF** composes the report with the layout the picker beside it selects.
"(procedure's report)" is the layout named by the procedure's first completion report
command in emission order today (its first start command when it emits none at
Completion); a procedure that is gone or emits no report, and a layout that was deleted,
fall back to the all-sections default, so a regeneration outlives the configuration. Any
other layout of the library can be chosen instead, because the run file is self-sufficient.
The PDF is published in the reports folder under the run's plain base name, replacing the
previous hand render, and registers nothing on the run.

On the station's own window the finished PDF opens in the system's PDF viewer, falling
back to a browser download when that fails ("Could not open the report. Downloading it
instead."); in a browser, local or remote, it opens in a new tab. What the pages contain is
[Report layouts](process-reports#what-the-pdf-prints). The report already registered for a
run is reissued instead from [Labels and reports](histories-documents), which never
composes it again.
