Skip to content

Commit

Permalink
[FIX] xlsx: convert #REF at export to xlsx
Browse files Browse the repository at this point in the history
Reference errors in excel are #REF!, not #REF.

closes #5019

Task: 4207052
Signed-off-by: Lucas Lefèvre (lul) <[email protected]>
  • Loading branch information
hokolomopo authored and LucasLefevre committed Oct 28, 2024
1 parent 15e5883 commit a56536c
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
17 changes: 13 additions & 4 deletions src/xlsx/functions/cells.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
import { functionRegistry } from "../../functions";
import { formatValue, isNumber } from "../../helpers";
import { mdyDateRegexp, parseDateTime, timeRegexp, ymdDateRegexp } from "../../helpers/dates";
import { ExcelCellData, Format } from "../../types";
import { CellValue, ExcelCellData, Format } from "../../types";
import { CellErrorType } from "../../types/errors";
import { XMLAttributes, XMLString } from "../../types/xlsx";
import { FORCE_DEFAULT_ARGS_FUNCTIONS, NON_RETROCOMPATIBLE_FUNCTIONS } from "../constants";
import { getCellType, pushElement } from "../helpers/content_helpers";
Expand All @@ -34,13 +35,14 @@ export function addFormula(cell: ExcelCellData):
.every((tk) => functions[tk.value.toUpperCase()].isExported);

const type = getCellType(cell.value);
const exportedValue = adaptFormulaValueToExcel(cell.value);
if (isExported) {
const XlsxFormula = adaptFormulaToExcel(formula);
node = escapeXml/*xml*/ `
<f>
${XlsxFormula}
</f>
${escapeXml/*xml*/ `<v>${cell.value}</v>`}
${escapeXml/*xml*/ `<v>${exportedValue}</v>`}
`;
attrs.push(["t", type]);
return { attrs, node };
Expand All @@ -49,10 +51,10 @@ export function addFormula(cell: ExcelCellData):
// nothing* ,we don't export it.
// * non-falsy value are relevant and so are 0 and FALSE, which only leaves
// the empty string.
if (cell.value === "") return undefined;
if (exportedValue === "") return undefined;

attrs.push(["t", type]);
node = escapeXml/*xml*/ `<v>${cell.value}</v>`;
node = escapeXml/*xml*/ `<v>${exportedValue}</v>`;
return { attrs, node };
}
}
Expand Down Expand Up @@ -95,9 +97,16 @@ export function adaptFormulaToExcel(formulaText: string): string {
ast = addMissingRequiredArgs(ast);
return ast;
});
ast = convertAstNodes(ast, "REFERENCE", (ast) => {
return ast.value === CellErrorType.InvalidReference ? { ...ast, value: "#REF!" } : ast;
});
return ast ? astToFormula(ast) : formulaText;
}

function adaptFormulaValueToExcel(formulaValue: CellValue): CellValue {
return formulaValue === CellErrorType.InvalidReference ? "#REF!" : formulaValue;
}

/**
* Some Excel function need required args that might not be mandatory in o-spreadsheet.
* This adds those missing args.
Expand Down
10 changes: 10 additions & 0 deletions tests/__snapshots__/xlsx_export.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10456,6 +10456,16 @@ Object {
</v>
</c>
</row>
<row r=\\"41\\" ht=\\"17.25\\" customHeight=\\"1\\" hidden=\\"0\\">
<c r=\\"A41\\" s=\\"3\\" t=\\"str\\">
<f>
#REF!+5
</f>
<v>
#REF!
</v>
</c>
</row>
</sheetData>
</worksheet>",
"contentType": "sheet",
Expand Down
1 change: 1 addition & 0 deletions tests/xlsx_export.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const simpleData = {
A38: { content: `='<Sheet2>'!B2` },
A39: { content: `=A39` },
A40: { content: `=(1+2)/3` },
A41: { content: "=#REF + 5" },
K3: { border: 5 },
K4: { border: 4 },
K5: { border: 4 },
Expand Down

0 comments on commit a56536c

Please sign in to comment.