From 93eb716fc355a296c22acf2253485cde05fed60e Mon Sep 17 00:00:00 2001 From: "Adrien Minne (adrm)" Date: Tue, 12 Nov 2024 09:29:51 +0100 Subject: [PATCH] [FIX] xlsx: preserve leading whitespace at export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a shared string has leading/trailing whitespace, it should have the attribute `xml:space="preserve"` otherwise the whitespace is trimmed in Excel. closes odoo/o-spreadsheet#5377 Task: 4044862 Signed-off-by: RĂ©mi Rahir (rar) Signed-off-by: Adrien Minne (adrm) --- src/xlsx/xlsx_writer.ts | 7 ++++++- tests/xlsx/xlsx_export.test.ts | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/xlsx/xlsx_writer.ts b/src/xlsx/xlsx_writer.ts index 095fddec49..132a5d2848 100644 --- a/src/xlsx/xlsx_writer.ts +++ b/src/xlsx/xlsx_writer.ts @@ -283,7 +283,12 @@ function createSharedStrings(strings: string[]): XLSXExportFile { ["uniqueCount", strings.length], ]; - const stringNodes = strings.map((string) => escapeXml/*xml*/ `${string}`); + const stringNodes = strings.map((string) => { + if (string.trim() !== string) { + return escapeXml/*xml*/ `${string}`; + } + return escapeXml/*xml*/ `${string}`; + }); const xml = escapeXml/*xml*/ ` diff --git a/tests/xlsx/xlsx_export.test.ts b/tests/xlsx/xlsx_export.test.ts index fd66b70d48..513dfee79e 100644 --- a/tests/xlsx/xlsx_export.test.ts +++ b/tests/xlsx/xlsx_export.test.ts @@ -765,6 +765,20 @@ describe("Test XLSX export", () => { expect(styles[1].querySelector("alignment")!.getAttribute("wrapText")).toBe("1"); }); + test("Leading and trailing whitespace in strings are preserved", async () => { + const model = new Model(); + setCellContent(model, "A1", " Multiline with\n leading and trailing spaces\n "); + + const exportedXlsx = await exportPrettifiedXlsx(model); + const sharedStrings = parseXML( + exportedXlsx.files.find((f) => f["contentType"] === "sharedStrings")!["content"] + ); + + const string = sharedStrings.querySelector("si t")!; + expect(string.getAttribute("xml:space")).toBe("preserve"); + expect(string.textContent).toBe(" Multiline with\n leading and trailing spaces\n "); + }); + describe("formulas", () => { beforeAll(() => { functionRegistry.add("NOW", {