6.5 KiB
OnlyOffice xlsx 渲染自查 + 行高 409.5 上限真相
用途:交付前用 Maggie 实际看的引擎(OnlyOffice,非 LibreOffice)把汇总表 xlsx 渲染成 PDF/图片做视觉自查;并厘清"长内容行高调不上去"的根因,避免重复踩坑浪费时间。 来源:2026-06-17 万达行高验证 + 世茂重做渲染自查。
一、x2t 渲染 xlsx → PDF(用 OnlyOffice 引擎,保真度最高)
OnlyOffice 文档转换器 x2t 在容器 nextcloud-onlyoffice-1 内,是 Maggie 在线编辑/查看时的同款引擎。比 libreoffice --headless --convert-to pdf 更能反映她看到的真实效果。
format code:513 = PDF。
完整配方(已验证可用):
# 1. 容器内建可写目录(默认root建后chmod 777,让ds用户能写pdf输出)
docker exec nextcloud-onlyoffice-1 bash -c 'rm -rf /tmp/sx; mkdir -p /tmp/sx; chmod 777 /tmp/sx'
# 2. 主机预先写好转换配置 xml(关键:不要在容器内用 > 重定向,会因权限失败),cp进去
# /tmp/s_convert.xml 内容:
# <?xml version="1.0" encoding="utf-8"?>
# <TaskQueueDataConvert xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
# <m_sFileFrom>/tmp/sx/s.xlsx</m_sFileFrom>
# <m_sFileTo>/tmp/sx/s.pdf</m_sFileTo>
# <m_nFormatTo>513</m_nFormatTo>
# <m_bIsNoBase64>true</m_bIsNoBase64>
# </TaskQueueDataConvert>
docker cp /path/to/target.xlsx nextcloud-onlyoffice-1:/tmp/sx/s.xlsx
docker cp /tmp/s_convert.xml nextcloud-onlyoffice-1:/tmp/sx/s.xml
docker exec nextcloud-onlyoffice-1 bash -c 'chmod 666 /tmp/sx/s.xlsx /tmp/sx/s.xml'
# 3. 以 ds 用户身份跑 x2t(x2t 本身就是 ds 进程,必须 -u ds)
X2T=/var/www/onlyoffice/documentserver/server/FileConverter/bin/x2t
docker exec -u ds nextcloud-onlyoffice-1 bash -c \
"LD_LIBRARY_PATH=/var/www/onlyoffice/documentserver/server/FileConverter/bin $X2T /tmp/sx/s.xml 2>&1; echo x2t=\$?"
# 4. 取回 + 转图片自查
docker cp nextcloud-onlyoffice-1:/tmp/sx/s.pdf /tmp/out.pdf
pdftoppm -png -r 100 /tmp/out.pdf /tmp/out_img/s
⚠️ 权限坑(踩过3次才通)
x2t以 ds 用户运行,ds 的 HOME(/var/www/onlyoffice/documentserver)不可写。- ds 能写
/tmp和/var/lib/onlyoffice/documentserver/App_Data。 - 致命点:若用 root 建
/tmp/xxx目录,ds 写不进 →Permission denied+x2t=126/2。修复=建目录后chmod 777。 - 第二个坑:在容器内用
cat > s.xml <<EOF重定向写 xml 也会因 ds 权限失败。正确做法:主机写好 xml,docker cp 进去,不在容器内重定向。 - 成功标志:
x2t=0且/tmp/sx/s.pdf由ds ds所有、size>0。
截断检测用文本提取,不靠肉眼
渲染图片若无 vision 工具看不了内容时,用 pdftotext 抽全文,grep 各板块末尾独特锚点句是否都在(在=数据完整无截断)。比看图更可靠。
⚠️ pdftotext 会按列宽把长句折行,直接 grep 完整句会假阴性——先
tr -d '\n' | tr -d ' '把整页拍平再 grep(见主 SKILL Pitfall 1b 末条)。
⚠️ LibreOffice headless 渲超高行 xlsx 会卡死/被 SIGKILL → 直接走 x2t,别耗重试(2026-06-22 悦拾光实证)
交付前想出 PDF 自查时,别先试 libreoffice --headless --convert-to pdf——当 xlsx 含超高行 + 海量文本单元格(如 K列法律风险 800字、行高 600–700pt)时,LibreOffice headless 转换阶段会卡死,前台 timeout 到点被 -15、加 -env:UserInstallation 独立 profile 重试仍 -9(SIGKILL)。诊断特征:libreoffice --version 秒回正常、free -h 内存充足(11G+ 可用),唯独 --convert-to 这一步挂——证明不是环境/内存问题,是 LibreOffice 对「超高行+超长单元格」headless 排版的已知缺陷。
- 别浪费在 LibreOffice 上反复试(本次连耗 4 次 -9/-15 才转向):内存够、版本正常却
--convert-to挂,立即判定为超高行触发的 LO 缺陷,直接切到本文上半「x2t 渲染」配方。x2t 是 Maggie 实际看文件的引擎、对超高行无此问题,本就该优先用它,不该先绕 LibreOffice。 - 主 SKILL 已有铁律「LibreOffice 与 OnlyOffice 不同源、最终验收用 x2t」——本条补充其故障模式:LO 不只是「页数不准」,遇超高行会直接转换失败,更没有当 fallback 的价值。
- 清残留:转换挂掉常留 soffice 僵尸进程,重试前
pkill -9 -f soffice; pkill -9 -f oosplash。
⚠️ 程序化截断自检:用 skill 自带脚本,别每次手写行高估算(2026-06-22 悦拾光教训)
交付前判断「K列长文会不会被行高截断」,直接跑 scripts/xlsx-rowheight-analyze.py <文件.xlsx>(只读,按列宽折行估每行所需高度、标出「当前行高 < 建议行高」的行),不要在 execute_code 里临时手写一版行高估算函数——本次就因手写估算严重偏低(K列 800字实际需 43 行≈665pt,手写版只给了 21 行≈321pt),自检时才发现差一倍,白绕一圈。脚本已沉淀正确的 CJK 折行口径(中文按2宽、按 \n 切段逐段折行、向上取整),照用即可。设完行高用同口径复检 可显行数 ≥ 需求行数 全绿再渲染。
二、行高 409.5 pt 上限真相(别再浪费时间调高)
长内容单元格"行高调不上去"的根因已查清:
| 层 | 行为 |
|---|---|
| xlsx 文件格式 | 允许 >409.5pt(openpyxl 写 900 读回 900) |
| OnlyOffice x2t 批量引擎 | 接受 900pt,round-trip 不 clamp |
| OnlyOffice 网页版编辑器 | 存盘时 clamp 到 ~409.5pt ← 这是 Maggie 编辑保存后高行变矮的真因 |
- 实测:给行设 760pt 交付,Maggie 在 OnlyOffice 网页版打开编辑保存后,被压回 409.6pt。不是 xlsx 上限,是网页编辑器 clamp。
- Maggie 的决定(2026-06-17):"行距搞不定就算了,就按照目前的最高行距就好。" → 统一用 409.6pt,不再折腾调更高。
- 实务影响:单格约容纳 18–20 个折行;超长内容(如 K 列 700+ 字、第三部分 800+ 字)在网页在线编辑视图可滚动看全、数据层完整,只有导 PDF 给客户打印时才需另调版式(拆单元格/缩字号)。平时 409.6 即可,与万达定稿一致。
- 若某份确需更高且不经网页编辑器存盘(直接文件层交付),x2t 引擎会认 900pt——但 Maggie 已拍板用 409.6,除非她另有指示,不要自作主张调高。