目錄 / Table of Contents

LibreOffice 互通性矩陣

本文件記錄 OdfKit 與 LibreOffice 26.x 的實機 headless 互通驗收範圍。 矩陣以 OdfKit.Tests/LibreOfficeInteropTests.cs 與 eng/Test-LibreOfficeInterop.ps1 為準。

執行方式

# 有 LibreOffice 26.x 時執行互通測試;找不到則略過(exit 0)
pwsh eng/Test-LibreOfficeInterop.ps1

# CI 或本機強制要求 LibreOffice
pwsh eng/Test-LibreOfficeInterop.ps1 -RequireLibreOffice

# 指定 portable 安裝路徑
$env:ODFKIT_SOFFICE_PATH = "D:\Tools\LibreOffice\program\soffice.com"
pwsh eng/Test-LibreOfficeInterop.ps1

LibreOfficeInteropTests 預設不會由一般 dotnet test 自動執行真實 LibreOffice; 專用腳本會在測試程序期間設定 ODFKIT_RUN_LIBREOFFICE_INTEROP=1,以免 unfiltered 回歸在安裝 LibreOffice 的機器上被外部 headless 轉檔拖慢。

環境變數(擇一):

變數 用途
ODFKIT_SOFFICE_PATH soffice 可執行檔或安裝目錄(優先)
LIBREOFFICE_PATH 同上,相容別名

需求:

  • LibreOffice 26.x(soffice --version 輸出含 LibreOffice 26.)
  • 排除 MockSoffice 測試替身

矩陣

測試 來源格式 OdfKit 建立內容 LibreOffice 轉換 驗收方式 狀態
LibreOfficeHeadlessLoadsGeneratedDocuments ODT 標題、段落、互通標記 txt 轉出文字含 OdfKit-LibreOffice-26-Interop-Marker ✅
同上 ODS 嵌入圖表(條形圖、標題、圖例) xlsx 轉出 XLSX 非空 ✅
同上 ODP 進場動畫(fade-in) fodp 轉出 XML 含 ooo-entrance-fade-in ✅
同上 ODG 文字方塊互通標記 fodg 轉出 XML 含 OdfKit-LibreOffice-26-Interop-Marker ✅
LibreOfficeHeadlessLoadsTrackedChangesOdt ODT text:tracked-changes 段落與表格 txt / odt 標記保留;可 accept 修訂 ✅
LibreOfficeHeadlessLoadsTrackedChangesOds ODS table:tracked-changes 公式變更 ods 標記與修訂節點保留 ✅
LibreOfficeHeadlessLoadsTemplateVariantDocuments OTT 母片頁面、互通標記 txt 轉出文字含 OdfKit-LibreOffice-Template-Interop-Marker ✅
同上 OTS 工作表互通標記 fods 轉出 Flat XML 含互通標記 ✅
同上 OTP 標題 placeholder、文字方塊互通標記 fodp 轉出 Flat XML 含互通標記 ✅
同上 OTG 文字方塊互通標記 fodg 轉出 Flat XML 含互通標記 ✅
LibreOfficeHeadlessLoadsNativeFlatXmlDocuments FODT(原生產生,非由 ZIP 轉換) 標題、段落、互通標記 txt 轉出文字含 OdfKit-LibreOffice-NativeFlat-Interop-Marker ✅
同上 FODS(原生產生) 工作表互通標記 xlsx 轉出 XLSX 非空 ✅
同上 FODP(原生產生) 文字方塊互通標記 odp 轉出 ODP 含互通標記 ✅
同上 FODG(原生產生) 文字方塊互通標記 png 轉出 PNG 非空 ✅
LibreOfficeHeadlessLoadsMasterDocument ODM 段落、子文件參照、互通標記 txt / odm LibreOffice 識別為 Writer master document(writerglobal8);轉出文字含互通標記;往返後子文件參照保留 ✅
LibreOfficeHeadlessLoadsWebTemplateDocument OTH 標題、段落、互通標記 txt / odt LibreOffice 識別為 Writer/Web document(writerweb8_writer);轉出文字含互通標記;轉出 ODT 內容保留 ✅
DatabaseSchemaPackageUsesLibreOfficeCompatibleMimeType ODB 資料表、查詢、表單封裝 (封裝層級,無 CLI 轉換) mimetype/manifest media-type 與真實 LibreOffice 自建 ODB 完全一致;另以 UNO API desktop.loadComponentFromURL 人工驗證可成功載入 ✅
LibreOfficeHeadlessExecutesManagedDocumentMacros ODT 1.0~1.4 Basic 與 Python 文件巨集 UNO script provider 每個版本的兩個巨集各自寫出標記檔,並核對完整內容;Windows Portable 26.2.4.2 實測 ✅
LibreOfficeUnoOpenPgpRealKeyBidirectionalRoundTrip OpenPGP ODT 臨時 GnuPG RSA 金鑰、加密本文 UNO 解密、修改、重新儲存 核對本文、LibreOffice 新增標記、wholesome OpenPGP manifest,再由 OdfKit 解密 ✅
LibreOfficeHeadlessPivotTableRoundTripsOdsAndPdf ODS 1.4 DataPilot 日期月份分組、列百分比、列欄總計、outline 版面、drill-down ods / pdf 往返後由 OdfKit 讀回 Pivot 定義;PDF 非空 ✅
LibreOfficeKeepsWhitespaceAndListNumberingOfOdfKitText ODT 連續空格、定位字元、換行;AddListWithStyle 的 a) 與 (I) 編號 txt 空白原樣保留;清單顯示 a)、b)、(I)(修正前顯示成 1) ✅
LibreOfficeRecognizesPageNumberAndPageCountFields ODT 頁尾的頁碼與總頁數欄位 docx 頁尾還原為 PAGE 與 NUMPAGES(修正前總頁數也變成 PAGE) ✅
LibreOfficeReadsOdfKitConvertedXlsxWithDatesMergesAndSparseCells XLSX → ODS 日期、合併儲存格、前導空白、遠端位址的儲存格 xlsx 以 ClosedXML 讀回:日期不位移、合併範圍與空白保留、遠端儲存格在原位置 ✅
LibreOfficeOpensOdfKitConvertedDocxWithListsNotesBreaksAndFooter DOCX → ODT 清單、註腳、分頁符號、頁尾欄位、表格儲存格內的清單 txt / pdf / docx 專案符號與巢狀編號、註腳引用與內文、PDF 恰為兩頁、頁尾欄位與儲存格清單保留 ✅
LibreOfficeOpensOdfKitConvertedDocxWithSectionsAndHyperlinkFields DOCX → ODT 直向與橫向兩個章節各有頁首、HYPERLINK 複雜欄位 pdf / docx PDF 兩頁且同時含直向與橫向頁面;匯出的 DOCX 含兩個章節的頁首文字,超連結目標保留在關係檔 ✅
LibreOfficeOpensOdfKitConvertedDocxWithTocBookmarksColumnsAndPageNumbering DOCX → ODT 目錄欄位、標題書籤、連續雙欄章節、起始頁碼 txt / docx 目錄與各章節內文都在文字裡;匯出的 DOCX 還原出 TOC 欄位、_Toc1 書籤、w:cols w:num="2" 與 w:pgNumType w:start="5" ✅
LibreOfficeAuthoredOdtKeepsAllTextInEveryExportFormat LibreOffice ODT → DOCX/HTML/Markdown/RTF/PDF/重新儲存 含清單(有序、無序、巢狀)、表格(標題列與合併)、超連結、換行與圖片的真實 LibreOffice ODT txt / fodg(PDF 匯入)/ Open XML SDK 各格式的文字都完整;DOCX 通過 Open XML SDK 驗證;重新儲存的 ODT 能被 LibreOffice 開啟 ✅
OdfKitLoadsLibreOfficeSpreadsheetCompletelyAndKeepsItOnSave LibreOffice 儲存的 ODS 儲存格帶有宣告在根元素的 calcext: 前綴、表格超過 8 KB (OdfKit 載入、修改、儲存) DOM 載入後資料完整,修改後儲存再載入仍完整(修正前整張工作表被讀成空表) ✅
OdfKitKeepsSpaceBetweenSpansOfLibreOfficeWrittenOdt LibreOffice 儲存的 ODT 兩個 text:span 之間的單一空格 (OdfKit 載入、儲存) 載入與儲存後 </text:span> 與 <text:span 的空格仍在 ✅

Apache OpenOffice 獨立驗收

ApacheOpenOfficeInteropTests 不再掛在 LibreOfficeInteropTests partial 型別下。測試使用 獨立的 ODFKIT_OPENOFFICE_PATH,並核對 Windows 檔案版本描述與公司必須是 Apache OpenOffice/Apache Software Foundation,不得誤用 LibreOffice。實機範圍包含 ODT/ODS/ODP/ODG 核心文件往返,以及進階 DataPilot ODS 往返與 PDF 匯出。

Windows 版 Apache OpenOffice 不提供可靠的 LibreOffice --convert-to CLI;測試因此啟動 限定 loopback 的 soffice headless listener,再使用 AOO 安裝包隨附的官方 Python/UNO runtime 開啟、另存與匯出。PYTHONPATH 只設定於 bridge 子程序,不污染 runner 全域環境。 未明確要求時,沒有安裝 AOO 會略過;-RequireOpenOffice 會設定 fail-closed 模式,找不到 官方 runtime、UNO 連線失敗或路徑偽冒時皆失敗。 GitHub Actions 的手動 workflow 釘選 Apache OpenOffice 4.1.17,下載後依 Apache 官方 SHA-256 驗證。CI 使用 MSI administrative image 取得隔離的可攜執行樹,不修改 runner 的全機 Office 安裝;確認 soffice.exe 的公司為 Apache Software Foundation 後,再執行 net8.0 與 net10.0。

pwsh eng/Test-ApacheOpenOfficeInterop.ps1 `
  -SofficePath "C:\Program Files (x86)\OpenOffice 4\program\soffice.exe" `
  -RequireOpenOffice

已知上游限制(非 OdfKit 缺陷)

以 LibreOffice 26.2.4.2 驗證時另外確認兩項與 OdfKit 無關的行為,避免誤判為 OdfKit 缺陷:

  • LibreOffice 的 HTML 匯入會寫出 style:border-line-width-bottom="0cm 0.004cm 0.002cm";官方 ODF schema 的 positiveLength 要求嚴格為正,0cm 不符合,OdfKit 的 schema 驗證器因此正確地回報不符。
  • LibreOffice 的 txt 匯出遇到巢狀表格時,會把表格之後的段落重複輸出;以 LibreOffice 重新儲存的 ODT 結構正確(該段落只出現一次),因此判斷為匯出濾鏡的行為。

獨立(非嵌入 ODS/ODT/ODP)的 ODC/OTC/FODC 圖表文件,實測確認 LibreOffice 26.2.1 不接受 為可直接開啟的主文件:

格式 實測結果
.odc soffice --headless --convert-to txt 回報 source file could not be loaded
.otc 同上,回報 source file could not be loaded
.fodc 未回報錯誤,但被誤判為「Writer document」,僅原樣回顯來源 XML,並非真正剖析為圖表——不構成有效互通

ODF Chart 設計上即為僅可嵌入 ODS/ODT/ODP 內的子文件類型,並非獨立可開啟的主文件格式。 改以封裝結構與 schema 層級的精確驗證取代真機驗證(見 LibreOfficeInteropTests.OdfChartDocumentPackageStructureMatchesOdf14Schema),並以既有 「圖表嵌入 ODS 後由 LibreOffice 開啟」驗收(LibreOfficeHeadlessLoadsGeneratedDocuments 對 含圖表 ODS 的 xlsx 轉換)佐證嵌入式圖表的真實互通性。

獨立 OTF/FDF 公式範本與 Flat 變體同樣不被 LibreOffice 26.2.1 接受為可直接開啟的主文件:

格式 實測結果
.odf ✅ 真機支援——LibreOffice 識別為「Math document」,使用 math8 篩選器;MathML 內容(含 mrow 群組)往返保留
.otf ❌ soffice --headless --convert-to odf 回報 source file could not be loaded
.fdf ❌ 未回報錯誤,但被誤判為「Calc document」,以 calc_png_Export 篩選器產生與公式內容完全無關的輸出

ODF Formula 是唯一一個獨立 ZIP 主格式(.odf)確實有真機支援的次要格式(不同於 Chart/Image), 但其 Template/Flat 變體仍與 Chart/Image 的變體一樣不受支援。見 LibreOfficeInteropTests.LibreOfficeHeadlessLoadsFormulaDocument(.odf 真機驗收)與 OdfFormulaVariantDocumentPackageStructureMatchesOdf14Schema(.otf/.fdf 封裝結構驗證)。

獨立 ODI/OTI/FODI 影像文件同樣不被 LibreOffice 26.2.1 與 Microsoft Office 365 接受為可直接 開啟的主文件:

格式 實測結果
.odi ❌ soffice --headless --convert-to png 回報 source file could not be loaded
.oti ❌ 同上,回報 source file could not be loaded
.fodi ❌ 未回報錯誤,但被誤判為「Writer document」,以 writer_png_Export 篩選器產生與影像內容完全無關的輸出

.fodi 的誤判模式與 .fodc(誤判為 Writer document)、.fdf(誤判為 Calc document)一致—— 這修正了既有 ImageDocumentPackageStructureMatchesOdf14Schema 註解中原先聲稱「ODI/OTI/ FODI 一律回報 source file could not be loaded」的不準確描述(該描述對 ODI/OTI 成立,但對 FODI 並不成立)。改以封裝結構與 schema 層級的精確驗證取代真機驗證(該測試已擴充涵蓋 ODI/OTI/FODI 三者)。

ODB 資料庫文件的失效模式比 Chart/Image 更隱晦——並非乾淨的「could not be loaded」錯誤:

轉換目標 實測結果
odb(自身) ❌ 明確回報 no export filter,非零結束碼失敗
txt/ods/xlsx/csv ⚠️ 結束碼 0(看似成功),但輸出檔案經位元組層級檢查確認僅為來源 .odb 的逐位元組原樣複製,並未真正轉換——比清楚的錯誤訊息更具誤導性

這修正了既有 DatabaseSchemaPackageUsesLibreOfficeCompatibleMimeType 註解中原先聲稱「對既有 .odb 檔案執行 --convert-to 一律回報 source file could not be loaded」的不準確描述。改以封裝 層級 mimetype/manifest 驗證為主要自動化測試手段,並以已完成的 LibreOffice UNO API (desktop.loadComponentFromURL)人工驗證佐證真實載入能力。

非目標(Wave 3 尚未涵蓋)

  • 像素級視覺 diff(見 ooxml-visual-golden-matrix.md)
  • Microsoft Word / Excel 開啟驗收
  • 動畫播放、圖表樣式等編輯器行為驗證;進階 DataPilot 已涵蓋 OdfKit 物化、 LibreOffice 往返與 Apache OpenOffice 專用驗收入口
  • 所有 24 種 extension 的封裝層級/互通驗收已於 Batch 1-6(2026-06-23)涵蓋完畢 (四主格式 template/flat 變體、.odm/.oth、Chart 全族、Formula 全族、Image 全族、 .odb 皆已驗證並記錄真實 LibreOffice 行為,包含已確認的上游限制);剩餘僅為本節其餘 列出的非目標項目(像素級視覺 diff、Office 開啟驗收、編輯器行為驗證)

相關測試

類別 說明
LibreOfficeInteropTests 本矩陣的實機 headless 測試
ApacheOpenOfficeInteropTests Apache OpenOffice 四種核心格式與 DataPilot 實機 headless 測試
LibreOfficeScriptingInteropTests 使用隔離 profile 實際執行 Basic/Python 文件巨集
TrackedChangesInteropTests 追蹤修訂語意(非必須 LO)
LoExtInteropTests loext:decorative 載入映射
LibreOfficeRenderer*Tests Extensions.Rendering 可替換 backend