Preserve QExcell cell notes in XLSX

This commit is contained in:
Курнат Андрей
2026-06-02 05:50:30 +03:00
parent 57cce9ea96
commit 22d2903f10
7 changed files with 300 additions and 24 deletions
+54
View File
@@ -4,6 +4,7 @@ import {
buildChartXml,
buildCellXml,
buildAutoFilterXml,
buildCommentsXml,
buildColumnWidthsXml,
buildHyperlinksXml,
buildMergeCellsXml,
@@ -28,6 +29,7 @@ import {
worksheetXmlToHiddenColumns,
worksheetXmlToHiddenRows,
worksheetXmlToHyperlinks,
worksheetCommentsXmlToComments,
worksheetXmlToMergedCells,
worksheetXmlToRowHeights,
worksheetXmlToShowGridLines,
@@ -145,6 +147,58 @@ describe("excellOffice OOXML helpers", () => {
expect(relationshipsXml).not.toContain('TargetMode="External"');
});
it("собирает и читает legacy comments XLSX для заметок ячеек", () => {
const commentsXml = buildCommentsXml({ B2: "Проверить сумму", A1: "Комментарий\nв две строки" });
const parsedComments = worksheetCommentsXmlToComments({
comments: {
commentList: {
comment: [
{ ref: "B2", text: { t: "Проверить сумму" } },
{ ref: "A1", text: { r: [{ t: "Комментарий" }, { t: "\nв две строки" }] } }
]
}
}
});
expect(commentsXml).toContain('<comment ref="A1" authorId="0"><text><t>Комментарий\nв две строки</t></text></comment>');
expect(commentsXml).toContain('<comment ref="B2" authorId="0"><text><t>Проверить сумму</t></text></comment>');
expect(parsedComments).toEqual({ A1: "Комментарий\nв две строки", B2: "Проверить сумму" });
});
it("сохраняет заметки ячеек XLSX в comments, VML и relationships", async () => {
const blob = await exportXlsxBlob({
id: "workbook",
title: "Comments.xlsx",
updatedAt: "2026-06-01T00:00:00.000Z",
activeSheet: "sheet-1",
sheets: [
{
id: "sheet-1",
name: "Sheet 1",
cells: { A1: "Итого" },
comments: { A1: "Проверено финансовым отделом" }
}
]
});
const zip = await JSZip.loadAsync(await blob.arrayBuffer());
const contentTypesXml = await zip.file("[Content_Types].xml")?.async("string");
const worksheetXml = await zip.file("xl/worksheets/sheet1.xml")?.async("string");
const relationshipsXml = await zip.file("xl/worksheets/_rels/sheet1.xml.rels")?.async("string");
const commentsXml = await zip.file("xl/comments1.xml")?.async("string");
const vmlXml = await zip.file("xl/drawings/vmlDrawing1.vml")?.async("string");
const imported = await importXlsxFile(new File([blob], "Comments.xlsx", { type: blob.type }));
expect(contentTypesXml).toContain("/xl/comments1.xml");
expect(contentTypesXml).toContain('Extension="vml"');
expect(worksheetXml).toContain('<legacyDrawing r:id="rId2"/>');
expect(relationshipsXml).toContain('Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"');
expect(relationshipsXml).toContain('Target="../comments1.xml"');
expect(relationshipsXml).toContain('Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"');
expect(commentsXml).toContain('<comment ref="A1" authorId="0">');
expect(vmlXml).toContain("<x:Row>0</x:Row><x:Column>0</x:Column>");
expect(imported.sheets[0].comments).toEqual({ A1: "Проверено финансовым отделом" });
});
it("сохраняет базовое форматирование ячеек XLSX в XML листа", () => {
const cellFormats = {
A1: { bold: true, fontSize: 14, fontFamily: "Arial", textColor: "0f5fae", fillColor: "fff2cc", horizontalAlign: "center" as const },