# 导出一次运行记录

> 一次运行记录的可携带副本和生成出来的 PDF：每个动作需要什么、文件怎么命名，以及 CSV、XLSX、GLAB 和 PDF 到底各自包含什么。

打开的运行记录上方那一条，先摆可携带的副本，再摆生成出来的文档（见[运行档案](histories-record#the-strip)）。下面这四个动作需要**导出/导入历史**权限，而且四个都是对运行记录文件的读取：运行时停止期间和某个单元正在记录期间它们照常可用，四个都不往运行记录里写任何东西。

这一条上还有第五个动作，**新建标签**，它既不是导出也不是读取：它往运行记录里发出一张标签，并把这件事作为证据记在那里，因此它需要的是**运行流程**权限而不是导出权限，说明写在它所属的那些文档那一页（见[标签与报告](histories-documents)）。

| 动作 | 产出什么 | 对什么可用 | 落到哪里 |
| --- | --- | --- | --- |
| 导出 CSV | 以文本形式导出的原始数据记录。 | 任何运行记录，包括仍在记录的。 | 浏览器下载，在工作站自己的窗口上也一样（“已导出 CSV · 文件”）。 |
| 导出 XLSX | 一个 Excel 工作簿，含运行记录的标识、元数据和带类型的数据记录。 | 任何运行记录，包括仍在记录的；什么都还没记录的运行记录会答“这次运行记录还没有表头快照。请稍后再试。” | 浏览器下载（“已导出 XLSX · 文件”）。 |
| 导出 GLAB | 把整条运行记录导成一个可携带的 `.glab` 文件，另一台工作站可以导入它。 | 只有已完成、已中止或失败的运行记录。 | 浏览器下载（“已导出 GLAB · 文件（大小）”）。 |
| 生成 PDF | 用选择框选中的版式，从整条运行记录排出一份新的报告 PDF。 | 任何已经结束记录的运行记录。 | 数据根目录下的报告文件夹，随后打开。 |

运行中途导出的 CSV 或 XLSX 是一份自洽的部分副本：冻结的表头在运行开始时就写好了，因此导出带着完整的列集合和到目前为止记录下来的那些行，而且是通过正在进行的记录读出来的，不是另开一条到文件的连接。导出里的每一个日期和时间都遵循[设置](settings-localization)里配置的格式，每一个文件也都声明它的时间戳是按哪个基准读的：“UTC”或者“UTC±hh:mm”，也就是导出时刻工作站的时差。

## 文件名 {#file-names}

CSV、XLSX、GLAB 和 PDF 对同一条运行记录共用一个基础名称：按工作站的日期和时间格式写出的开始时刻（分隔符换成文件名里安全的字符），然后是模型、单元和流程的名称（“02-09-2026 14-05-30 - 气候试验箱 - 单元 1 - 保温试验”），每一段都截到 48 个字符，并去掉 Windows 不接受的字符。这个基础名称是持久占用的，因此同一条运行记录反复导出，即使重启也仍是同一个名字，只有会落到同一个名字上的另一条运行记录，才会从它的标识里取一个短后缀。由动作发出的报告会在基础名称后面加上分组名称；在这里生成的 PDF 用的是普通的基础名称。每一个文件都先用临时名称写完，写完了才发布，因此被取消的导出绝不会留下一个带成品扩展名的半截文件。

## CSV {#csv}

一列 **Timestamp**，表头写着带时间基准的 “Timestamp (UTC-03:00)”，然后按冻结下来的列顺序，每一个记录的通道有一列数值，表头是这次运行为这一列冻结下来的名称（单元上生效的别名，没有别名时则是通道名称）加方括号里的工程单位（“温度 [°C]”），旁边还有一列质量（“温度 [°C] Quality”），内容是 **Good** 或 **Unavailable**。这个表头就是这次运行的图表和报告给同一列起的名字。数值那一列原样保留数据记录存下来的东西（什么都没存时为空），布尔量写 `true`/`false`，日期类型的通道按工作站的格式写，含有分隔符、引号或换行的值会加引号。以 `=`、`+`、`-` 或 `@` 开头的文本单元格前面会加一个撇号，好让电子表格把它当文本而不是公式来读：表头里的列名称，以及来自现场设备的字符串通道的读数，都是这样处理的。数字永远不加前缀，因此负读数仍然是数字。

文件遵循工作站的小数分隔符偏好：小数点用点号时，列表分隔符是 `,`；小数点用逗号时，列表分隔符是 `;`，这样文件在该地区设置的电子表格里就能干净地打开。数字不写千位分隔符，按数据记录存下来的完整精度写。文本是 UTF-8。

## XLSX {#xlsx}

工作簿开头是一张 **Run** 工作表，两列，表头是 Field 和 Value：

| 字段 | 内容 |
| --- | --- |
| Run ID | 这次运行记录的唯一标识。 |
| Run Name、Model、Model Revision、Unit、Procedure | 记录当时冻结下来的那些名称；运行记录没有值的字段留空。 |
| Started At、Finished At | 这次运行的起止。仍在记录的运行记录，Finished At 写 **In progress**。 |
| Time Zone | 工作簿里每一个时刻所依据的基准。 |
| State | 导出时刻的生命周期状态。 |
| Result | 结论（OK、NOK、Indeterminate 或 None）；运行记录仍在记录时写 **In progress**。 |
| Termination | None，或者 StopInterlock。 |
| Interval (ms) | 记录间隔。 |
| Imported At、Imported From | 只有从另一套安装导入进来的副本才有：它是什么时候到这里来的，以及它来自哪个收到的文件。在这里记录的运行记录两行都没有。 |
| Notes | 这次运行记录的附注。 |

接下来是第二个表头 Metadata 和 Value，开始时记下的每一个元数据字段一行，按提示顺序排列。随后是一张或多张 **Datalog** 工作表，列顺序和通道表头都和 CSV 一样，表头行冻结，每张表都带自动筛选，不画网格线。数据记录超过 Excel 每张表 1,048,576 行的上限时，会自动拆成 **Datalog 2**、**Datalog 3**，依此类推，每一张都有自己的表头。

值按类型写进单元格：整数和有限小数写成原生数字，精度是数据记录存下来的完整精度，布尔量写成原生的 TRUE/FALSE。Excel 自己最多只处理 15 位有效数字，因此超出的位数在那里不显示，尽管文件里带着它们。非有限的读数、日期类型的通道和那些时间戳都是文本；质量为 **Unavailable** 的读数，数值单元格留空，由质量那一列说明。需要超过 Excel 16,384 列的运行记录，或者超过它 32,767 个字符上限的文本单元格，会连同原因一起被拒绝，而不是产出一个被截断的工作簿。

## GLAB {#glab}

`.glab` 文件是运行记录自己那个 SQLite 文件的一份自洽的、按页复制的在线副本：没有压缩包外壳，没有清单，没有派生出来的文档，也没有已发布的 PDF。运行记录文件里有什么，它就带什么：冻结的快照、那些行、元数据、配方写入、判据、事件条目、备注、标注、产量记录、带着冻结字节的标签产物，以及带着所留副本的报告登记。它用的基础名称和别的导出一样，而且只有完整写完才发布。另一台工作站通过[导入运行记录](histories-import)把它收回去。

## PDF {#pdf}

**生成 PDF** 用旁边选择框选中的版式排出报告。“（流程自带的报告）”指的是按今天的发出顺序排在最前的那条完成报告命令所指定的版式（流程在完成时不发出报告时，则是最前的那条开始命令）；流程已经不在或者不发出报告，以及版式已被删除，都会退回到包含全部小节的默认版式，因此重新生成的能力比配置活得更久。库里任何别的版式也可以选，因为运行记录文件是自足的。PDF 用运行记录普通的基础名称发布到报告文件夹里，覆盖上一次手工排出的那一份，而且不在运行记录上登记任何东西。

在工作站自己的窗口上，排好的 PDF 会在系统的 PDF 查看器里打开，打不开时退回到浏览器下载（“无法打开这份报告。改为下载它。”）；在浏览器里，无论本地还是远程，它都在新标签页里打开。页面上有什么内容，见[报告版式](process-reports#what-the-pdf-prints)。已经为一条运行记录登记过的报告，则改由[标签与报告](histories-documents)重出，那里绝不会重新排版。
