使用 LibreOffice 的 'scalc' 从命令行将制表符分隔的文本转换为 Excel

Posted

技术标签:

【中文标题】使用 LibreOffice 的 \'scalc\' 从命令行将制表符分隔的文本转换为 Excel【英文标题】:Using LibreOffice's 'scalc' to convert tab-delimited text to Excel from the command line使用 LibreOffice 的 'scalc' 从命令行将制表符分隔的文本转换为 Excel 【发布时间】:2020-09-26 01:37:39 【问题描述】:

我有一个以 LF 结尾、制表符分隔的输入文件,我希望使用 scalc --headless 将其转换为 Excel 格式(例如,OOXML .xlsx)。

我知道其他选项,例如 pyuno,甚至还有一些预先编写的脚本,例如 this one,但我认为没有理由为了完成我认为 scalc 可以完成的事情而使用 Python使用内置的命令行选项。

这是我尝试过但不起作用的方法:

scalc --headless --convert-to xlsx input.tsv
scalc --headless --infilter=tsv --convert-to xlsx input.tsv
scalc --headless --infilter=tsv:Text --convert-to xlsx input.tsv
scalc --headless --infilter=Text:tsv --convert-to xlsx input.tsv  # --> Error: no export filter

最后两个完全是猜测,因为除了scalc --help 的输出中的两个示例之外,没有关于--infilter 选项的真实文档。

最后一个产生了错误,但在所有其他情况下,制表符不会被识别为字段分隔符,生成的 Excel 电子表格只是在第一列中将所有数据连接在一起。

参考文献

https://help.libreoffice.org/latest/en-US/text/shared/guide/start_parameters.html 特别是“General arguments”部分,其中显示了两个示例:
--infilter="Calc Office Open XML"
--infilter="Text (encoded):UTF8,LF,Liberation Mono,en-US"
我假设分别表示从 .xlsx 到 Calc 的转换,以及从纯文本到 Writer 的转换

【问题讨论】:

现在,我什至不会为此烦恼 LibreOffice,因为转换器选项缺乏简洁、现成的文档(例如手册页或)。相反,我在 openpyxl 和 tabulate 库周围使用了我自己的非常薄的 Python 包装器,虽然速度不够快,但对于大多数一次性 Excel 到制表符分隔的转换(我的典型用例)来说已经足够了。 【参考方案1】:

虽然令人失望的是没有记录,但我还是能够从几个不同的来源拼凑出这个可行的解决方案:

scalc --headless --infilter="Text - txt - csv (StarCalc):9" \
      --convert-to xlsx input.tsv

“9”是水平制表符的小数 ASCII control code。我使用python -c 'print(ord("\t"))' 找到了这个,尽管man ascii 也可以。

详细here,有许多逗号分隔的选项可以传递给这个过滤器:

╔══════════════╤══════════╤═══════════╤═════════════╤══════════════════╤═════════════════════╗
║ option (pos) │ sep. (1) │ quote (2) │ charset (3) │ 1st line (4)     │ cell format (5)     ║
╠══════════════╪══════════╪═══════════╪═════════════╪══════════════════╪═════════════════════╣
║ defaults (?) │ 44 (,)   │ 34 (")    │ 0 (system)  │ 1                │ null ("standard")   ║
╟──────────────┼──────────┼───────────┼─────────────┼──────────────────┼─────────────────────╢
║ example      │ 9 (tab)  │ 39 (')    │ 76 (UTF-8)  │ 2 (skip 1st row) │ 1/9 (skip 1st col.) ║
╚══════════════╧══════════╧═══════════╧═════════════╧══════════════════╧═════════════════════╝

所以,例如:

scalc --headless --infilter="Text - txt - csv (StarCalc):9,39,76,2,1/9" \
      --convert-to xlsx input.tsv

将使用单引号作为文本分隔符和 UTF-8 编码的制表符分隔输入文件转换为 Excel .xlsx 文件,跳过第一行和第一列。

如上所述,输入记录分隔符和引号字符是 ASCII 序数。字符集的代码可以查找here,但0(系统默认)、1(Windows-1252)、12(ISO-8859-1)和76(UTF- 8) 对讲英语的人来说很有趣。

逗号分隔的选项字符串中的第 5 位“单元格格式”指定特定列的格式,并由正斜杠 (col/fmt/col/fmt) 分隔。这在here有详细解释,但简要说明:

1   Standard
2   Text
3   MM/DD/YY
4   DD/MM/YY
5   YY/MM/DD
6   - (unused?)
7   - ("     ")
8   - ("     ")
9   ignore field (do not import)
10  US-English
    (',' as 1000s sep, '.' as decimal, regardless of locale)

在那之后的过滤选项字符串中甚至还有更多个值,这些值与导入/导出对话框中的各种选项有关,例如“引用字段为文本”。再次参考上面链接的相同OpenOffice wiki article 以获得对这些的解释,因为我在这里已经筋疲力尽了。

来源

这个Linux Journal article 使用pyuno,这让我知道使用Text - txt - csv (StarCalc) 作为过滤器名称 我通过在 LibreOffice 源代码树中误入 this directory 来证实这一点,其中定义了所有过滤器 https://wiki.openoffice.org/wiki/Documentation/DevGuide/Spreadsheets/Filter_Options 具体来说,this section 用于 CSV 过滤器 标记为“从 OpenOffice 4.1.x 开始不再是最新的”,但当前足够仍然可以解决我的问题 这篇文章让我想到尝试将制表符的 ASCII 序数作为--infilter 字符串的“过滤器选项”部分的第一个字符 我应该使用冒号作为分隔符是我在 2014 年从 this commit 推断出来的,它将两个 --infilter 示例添加到 soffice --help 的输出中

【讨论】:

以上是关于使用 LibreOffice 的 'scalc' 从命令行将制表符分隔的文本转换为 Excel的主要内容,如果未能解决你的问题,请参考以下文章

使用命令行使用 Libre Office 将 xls 转换为 dbf

Scalc SBT 编译失败

使用 OpenOffice sCalc - 如何将 IF 函数与 REGEX 捕获一起使用,如果为真则打印捕获到单元格

怎么把libreoffice改成正常

使用 python 访问 LibreOffice 的比较文档

使用 libreoffice 从 HTML 转换时嵌入图像