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