跳到主要内容

Excel 扩展

excel 扩展通过封装 i18npool library 提供按 Excel 格式规则格式化数字的函数,并支持读写 Excel(.xlsx)文件。请注意不支持 .xls 文件。

提示:此前,Excel 文件读写由 spatial 扩展处理,它通过依赖“顺带”支持了 XLSX,但该能力未来可能从 spatial 中移除。相比之下,excel 扩展更高效且对导入/导出流程控制更细。如果 excel 扩展无法满足你的场景,可尝试 spatial 扩展。可参考 Excel ImportExcel Export 页面,但请注意这些特性未来也可能被弃用。

安装与加载

excel 扩展首次使用时会从官方扩展仓库自动按需加载。 若要手动安装并加载,请执行:

INSTALL excel;
LOAD excel;

Excel 标量函数

函数说明
excel_text(number, format_string)format_string 规则格式化给定 number
text(number, format_string)excel_text 的别名

示例

SELECT excel_text(1_234_567.897, 'h:mm AM/PM') AS timestamp;
timestamp
9:31 PM
SELECT excel_text(1_234_567.897, 'h AM/PM') AS timestamp;
timestamp
9 PM

读取 XLSX 文件

读取 .xlsx 文件最简单的方式就是直接对其 SELECT,例如:

SELECT *
FROM 'test.xlsx';
ab
1.02.0
3.04.0

如果需要设置更多选项来控制导入过程,可使用 read_xlsx 函数。支持以下命名参数。

选项类型默认值说明
headerBOOLEANautomatically inferred是否将首行视为结果列名。
sheetVARCHARautomatically inferred要读取的 xlsx 工作表名称。默认读取第一个工作表。
all_varcharBOOLEANfalse是否将所有单元格都读取为 VARCHAR
ignore_errorsBOOLEANfalse是否忽略错误,并将无法转换为推断列类型的单元格静默替换为 NULL
rangeVARCHARautomatically inferred要读取的单元格范围(电子表格表示法)。例如 A1:B2 读取 A1 到 B2。若未指定,则会推断为:从第一行连续非空单元格开始,到覆盖相同列范围的第一行空行结束的矩形区域。
stop_at_emptyBOOLEANautomatically inferred遇到空行时是否停止读取。若显式提供 range,默认 false;否则默认 true
empty_as_varcharBOOLEANfalse自动推断列类型时,是否将空单元格视为 VARCHAR 而不是 DOUBLE
SELECT *
FROM read_xlsx('test.xlsx', header = true);
ab
1.02.0
3.04.0

此外,也可使用带 XLSX 格式选项的 COPY 语句将 Excel 文件导入现有表。此时会使用目标表列类型来约束 Excel 单元格类型转换。

CREATE TABLE test (a DOUBLE, b DOUBLE);
COPY test FROM 'test.xlsx' WITH (FORMAT xlsx, HEADER);
SELECT * FROM test;

类型与范围推断

由于 Excel 本质上只在单元格中存储数字或字符串,且不强制同一列单元格类型一致,excel 扩展在导入工作表时需要进行一定“推断”来决定列类型。虽然绝大多数列会被推断为 DOUBLEVARCHAR,但有以下注意点:

  • 在可能时,会根据单元格应用的 format 推断 TIMESTAMPTIMEDATEBOOLEAN
  • 包含 TRUEFALSE 的文本单元格会被推断为 BOOLEAN
  • 空单元格默认视为 DOUBLE;若 empty_as_varchar 设为 true,则视为 VARCHAR

all_varchar 设为 true,上述规则均不生效,所有单元格都按 VARCHAR 读取。

当未显式指定类型时(例如使用 read_xlsx 而不是 COPY TO ... FROM '⟨file⟩.xlsx'), 结果列类型会根据工作表第一条“数据行”推断,即:

  • 若未显式给出 range
    • 若检测到表头或通过 header 强制表头,则取表头后的第一行
    • 若未检测到或未强制表头,则取工作表第一行非空行
  • 若显式给出 range
    • 若第一行存在表头或通过 header 强制表头,则取 range 第二行
    • 若无表头,则取 range 第一行

如果第一条“数据行”不能代表整张表(例如包含空单元格),可能会导致问题。此时可用 ignore_errorsempty_as_varchar 规避。

但当使用 COPY TO ... FROM '⟨file⟩.xlsx' 语法时,不会进行类型推断,结果列类型由目标表列类型决定。所有单元格仅通过从 DOUBLEVARCHAR 到目标列类型的 cast 转换。

写入 XLSX 文件

可使用 COPY 语句并将格式指定为 XLSX 来写入 .xlsx 文件。支持以下附加参数。

选项类型默认值说明
headerBOOLEANfalse是否将列名写为工作表第一行
sheetVARCHARSheet1要写入的 xlsx 工作表名称
sheet_row_limitINTEGER1048576单个工作表最大行数。超出该限制会抛出错误。

警告:许多工具单个工作表最多只支持 1,048,576 行,因此提高 sheet_row_limit 可能导致结果文件无法被其他软件读取。

这些参数在 COPY 语句中作为 FORMAT 后的选项传入,例如:

CREATE TABLE test AS
SELECT *
FROM (VALUES (1, 2), (3, 4)) AS t(a, b);
COPY test TO 'test.xlsx' WITH (FORMAT xlsx, HEADER true);

类型转换

由于 XLSX 文件本质上只支持存储数字或字符串(对应 VARCHARDOUBLE),写入 XLSX 时会应用以下类型转换规则。

  • 数值类型写入 XLSX 时会 cast 为 DOUBLE
  • 时间类型(TIMESTAMPDATETIME 等)会转换为 Excel “序列值”:日期为自 1900-01-01 起的天数,时间为一天中的分数;随后应用“数字格式”,以便在 Excel 中显示为日期/时间。
  • TIMESTAMP_TZTIME_TZ 分别 cast 为 UTC TIMESTAMPTIME,时区信息会丢失。
  • BOOLEAN 会转换为 10,并应用“数字格式”,使其在 Excel 中显示为 TRUEFALSE
  • 其余类型都会 cast 为 VARCHAR 后写入为文本单元格。