From 297841eed423c0e2b5414491e4e2e14f2a4cf0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Rahir=20=28rar=29?= Date: Fri, 19 Apr 2024 10:38:41 +0200 Subject: [PATCH] [IMP] XLSX: Faulty default styles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to some mismatch between the style in the default exported construct and the default values computed for a cell style, we were creating useless style entries at export. By setting a style index on a worksheet cell entry, our import code would then apply this style to the cell even though that same cell, when exported, had no style whatsoever. Furthermore, we did not process Excel default color properly. In Xlsx file, the color is sometimes set specifically to "FF000000" in the style sheet. However, that color (black) is not applied as a user-defined color in Excel (i.e. it's importance is lower than the color applied by a table[^1]). Instead, a user-defined "black" will be referred to via a theme property[^2]. Since we did not detect this "default color" pattern, we would consider the attribute `rgb=FF000000` as a user-defined color an ultimately set it in the plugin structure at import. This revision detects the "default color" situation and discards the given color to let the library (and specifically the CellPlugin as that issue affects the cell font color in particular) use its own default behaviour. [^1]: To test this out: - Go to Excel and create a sheet on which you put a table. - Apply a style such that the text turns white - On the cells with white text, manually apply an italic format - Import the xlsx file inside o-spreadsheet ==> the text turned black in o-spreadsheet [^2]: This situation seems to only concern that specific color and might encompass a broader scope but I haven't been able to find proper documentation about this. closes odoo/o-spreadsheet#3799 Signed-off-by: Rémi Rahir (rar) --- src/xlsx/conversion/color_conversion.ts | 8 + src/xlsx/extraction/base_extractor.ts | 4 +- src/xlsx/functions/worksheet.ts | 5 +- src/xlsx/helpers/content_helpers.ts | 2 +- src/xlsx/helpers/xml_helpers.ts | 4 +- .../__snapshots__/xlsx_export.test.ts.snap | 2402 ++++++++--------- 6 files changed, 1087 insertions(+), 1338 deletions(-) diff --git a/src/xlsx/conversion/color_conversion.ts b/src/xlsx/conversion/color_conversion.ts index ea3420b40c..b5e8ab4160 100644 --- a/src/xlsx/conversion/color_conversion.ts +++ b/src/xlsx/conversion/color_conversion.ts @@ -86,3 +86,11 @@ export function hexaToInt(hex: Color) { } return parseInt(hex.replace("#", ""), 16); } + +/** + * When defining style (fontColor, borderColor for instance) + * Excel will specify rgb="FF000000" + * In that case, We should not consider this value as user-defined but + * rather like an instruction: "Use your system default" + */ +export const DEFAULT_SYSTEM_COLOR = "FF000000"; diff --git a/src/xlsx/extraction/base_extractor.ts b/src/xlsx/extraction/base_extractor.ts index 02b2284cc6..fe036b3216 100644 --- a/src/xlsx/extraction/base_extractor.ts +++ b/src/xlsx/extraction/base_extractor.ts @@ -8,6 +8,7 @@ import { XLSXTheme, XMLFile, } from "../../types/xlsx"; +import { DEFAULT_SYSTEM_COLOR } from "../conversion"; import { fixXlsxUnicode } from "../helpers/misc"; import { XLSXImportWarningManager } from "../helpers/xlsx_parser_error_manager"; import { escapeQueryNameSpaces } from "../helpers/xml_helpers"; @@ -327,9 +328,10 @@ export class XlsxBaseExtractor { rgb = this.getThemeColor(themeIndex, theme.clrScheme); } else { rgb = this.extractAttr(colorElement, "rgb")?.asString(); + rgb = rgb === DEFAULT_SYSTEM_COLOR ? undefined : rgb; } const color = { - rgb, + rgb: rgb || defaultColor, auto: this.extractAttr(colorElement, "auto")?.asBool(), indexed: this.extractAttr(colorElement, "indexed")?.asNum(), tint: this.extractAttr(colorElement, "tint")?.asNum(), diff --git a/src/xlsx/functions/worksheet.ts b/src/xlsx/functions/worksheet.ts index 4c2e31ad05..6cdfaa0a21 100644 --- a/src/xlsx/functions/worksheet.ts +++ b/src/xlsx/functions/worksheet.ts @@ -86,7 +86,10 @@ export function addRows( // style const id = normalizeStyle(construct, extractStyle(cell, data)); - attributes.push(["s", id]); + // don't add style if default + if (id) { + attributes.push(["s", id]); + } let additionalAttrs: XMLAttributes = []; let cellNode = escapeXml``; diff --git a/src/xlsx/helpers/content_helpers.ts b/src/xlsx/helpers/content_helpers.ts index 74ffe3c274..99891283bc 100644 --- a/src/xlsx/helpers/content_helpers.ts +++ b/src/xlsx/helpers/content_helpers.ts @@ -96,7 +96,7 @@ export function extractStyle(cell: ExcelCellData, data: WorkbookData): Extracted vertical: style.verticalAlign ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign] : undefined, - wrapText: style.wrapping === "wrap", + wrapText: style.wrapping === "wrap" || undefined, }, }; diff --git a/src/xlsx/helpers/xml_helpers.ts b/src/xlsx/helpers/xml_helpers.ts index 6a83c0a7b7..c87e47014f 100644 --- a/src/xlsx/helpers/xml_helpers.ts +++ b/src/xlsx/helpers/xml_helpers.ts @@ -93,7 +93,7 @@ export function getDefaultXLSXStructure(data: ExcelWorkbookData): XLSXStructure fillId: 0, numFmtId: 0, borderId: 0, - alignment: { vertical: "bottom" }, + alignment: {}, }, ], fonts: [ @@ -101,7 +101,7 @@ export function getDefaultXLSXStructure(data: ExcelWorkbookData): XLSXStructure size: DEFAULT_FONT_SIZE, family: 2, color: { rgb: "000000" }, - name: "Calibri", + name: "Arial", }, ], fills: [{ reservedAttribute: "none" }, { reservedAttribute: "gray125" }], diff --git a/tests/xlsx/__snapshots__/xlsx_export.test.ts.snap b/tests/xlsx/__snapshots__/xlsx_export.test.ts.snap index 4107781dfa..7786eebc04 100644 --- a/tests/xlsx/__snapshots__/xlsx_export.test.ts.snap +++ b/tests/xlsx/__snapshots__/xlsx_export.test.ts.snap @@ -382,80 +382,80 @@ exports[`Test XLSX export Charts Chart legend is set to none position 1`] = ` - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -471,12 +471,7 @@ exports[`Test XLSX export Charts Chart legend is set to none position 1`] = ` "content": " - - - - - - + @@ -505,11 +500,8 @@ exports[`Test XLSX export Charts Chart legend is set to none position 1`] = ` - - - - - + + @@ -978,80 +970,80 @@ exports[`Test XLSX export Charts Export chart overflowing outside the sheet 1`] - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -1067,12 +1059,7 @@ exports[`Test XLSX export Charts Export chart overflowing outside the sheet 1`] "content": " - - - - - - + @@ -1101,11 +1088,8 @@ exports[`Test XLSX export Charts Export chart overflowing outside the sheet 1`] - - - - - + + @@ -1574,80 +1558,80 @@ exports[`Test XLSX export Charts chart dataset without title 1`] = ` - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -1663,12 +1647,7 @@ exports[`Test XLSX export Charts chart dataset without title 1`] = ` "content": " - - - - - - + @@ -1697,11 +1676,8 @@ exports[`Test XLSX export Charts chart dataset without title 1`] = ` - - - - - + + @@ -3026,80 +3002,80 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -3156,12 +3132,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun "content": " - - - - - - + @@ -3190,11 +3161,8 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - - - - - + + @@ -3689,80 +3657,80 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -4154,12 +4122,7 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` "content": " - - - - - - + @@ -4188,11 +4151,8 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - - - - - + + @@ -5024,80 +4984,80 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -5113,12 +5073,7 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` "content": " - - - - - - + @@ -5147,11 +5102,8 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - - - - - + + @@ -5455,7 +5407,7 @@ exports[`Test XLSX export Charts pie chart with only title dataset 1`] = ` - + @@ -5481,9 +5433,7 @@ exports[`Test XLSX export Charts pie chart with only title dataset 1`] = ` - - - + @@ -5898,80 +5848,80 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ 'Sheet1!B1:B4' - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -5987,12 +5937,7 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ 'Sheet1!B1:B4' "content": " - - - - - - + @@ -6021,11 +5966,8 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ 'Sheet1!B1:B4' - - - - - + + @@ -6508,80 +6450,80 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ 'Sheet1!B1:B4', - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -6597,12 +6539,7 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ 'Sheet1!B1:B4', "content": " - - - - - - + @@ -6631,11 +6568,8 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ 'Sheet1!B1:B4', - - - - - + + @@ -7087,80 +7021,80 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ 'Sheet1!B1:B4 - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -7176,12 +7110,7 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ 'Sheet1!B1:B4 "content": " - - - - - - + @@ -7210,11 +7139,8 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ 'Sheet1!B1:B4 - - - - - + + @@ -7709,80 +7635,80 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ 'Sheet1!B1:B4 - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -7798,12 +7724,7 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ 'Sheet1!B1:B4 "content": " - - - - - - + @@ -7832,11 +7753,8 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ 'Sheet1!B1:B4 - - - - - + + @@ -8281,80 +8199,80 @@ exports[`Test XLSX export Charts simple line chart with dataset [ 'Sheet1!B1:B4' - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -8370,12 +8288,7 @@ exports[`Test XLSX export Charts simple line chart with dataset [ 'Sheet1!B1:B4' "content": " - - - - - - + @@ -8404,11 +8317,8 @@ exports[`Test XLSX export Charts simple line chart with dataset [ 'Sheet1!B1:B4' - - - - - + + @@ -8894,80 +8804,80 @@ exports[`Test XLSX export Charts simple line chart with dataset [ 'Sheet1!B1:B4' - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -8983,12 +8893,7 @@ exports[`Test XLSX export Charts simple line chart with dataset [ 'Sheet1!B1:B4' "content": " - - - - - - + @@ -9017,11 +8922,8 @@ exports[`Test XLSX export Charts simple line chart with dataset [ 'Sheet1!B1:B4' - - - - - + + @@ -9383,80 +9285,80 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ 'Sheet1!B1:B4' - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -9472,12 +9374,7 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ 'Sheet1!B1:B4' "content": " - - - - - - + @@ -9506,11 +9403,8 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ 'Sheet1!B1:B4' - - - - - + + @@ -9946,80 +9840,80 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ 'Sheet1!B1:B4', - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -10035,12 +9929,7 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ 'Sheet1!B1:B4', "content": " - - - - - - + @@ -10069,11 +9958,8 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ 'Sheet1!B1:B4', - - - - - + + @@ -10516,80 +10402,80 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ 'Sheet1!B1: - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -10605,12 +10491,7 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ 'Sheet1!B1: "content": " - - - - - - + @@ -10639,11 +10520,8 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ 'Sheet1!B1: - - - - - + + @@ -11125,80 +11003,80 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ 'Sheet1!B1: - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -11214,12 +11092,7 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ 'Sheet1!B1: "content": " - - - - - - + @@ -11248,11 +11121,8 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ 'Sheet1!B1: - - - - - + + @@ -11735,80 +11605,80 @@ exports[`Test XLSX export Charts stacked bar chart 1`] = ` - + 0 - + 1 - + 2 - + 10 - + 20 - + 3 - + 11 - + 19 - + 4 - + 12 - + 18 - + 5 - + 13 - + 17 @@ -11824,12 +11694,7 @@ exports[`Test XLSX export Charts stacked bar chart 1`] = ` "content": " - - - - - - + @@ -11858,11 +11723,8 @@ exports[`Test XLSX export Charts stacked bar chart 1`] = ` - - - - - + + @@ -12039,53 +11901,53 @@ exports[`Test XLSX export Export data filters Export data filters snapshot 1`] = - + 0 - + 1 - + 2 - + 78 @@ -12103,12 +11965,7 @@ exports[`Test XLSX export Export data filters Export data filters snapshot 1`] = "content": " - - - - - - + @@ -12137,11 +11994,8 @@ exports[`Test XLSX export Export data filters Export data filters snapshot 1`] = - - - - - + + @@ -12259,60 +12113,60 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Conditional f - + 1 - + 0 - + 42 - + 13 - + 1 - + 20 - + 0 - + 5 - + 0 - + 3 @@ -12488,12 +12342,7 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Conditional f "content": " - - - - - - + @@ -12522,11 +12371,8 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Conditional f - - - - - + + @@ -12642,7 +12488,7 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Conditional f - + @@ -12668,9 +12514,7 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Conditional f - - - + @@ -12791,7 +12635,7 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Merges 1`] = - + @@ -12817,9 +12661,7 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Merges 1`] = - - - + @@ -12934,267 +12776,267 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Simple model 1 - + 2 - + - + 3 - + - + - + - + 4 - + 5 - + - + - + - + 6 - + - + - + - + 7 - + - + - + - + 8 - + - + - + - + 9 - + - + 10 - + - + - + - + 11 - + - + 12 - + - + - + - + 13 - + 14 - + - + 15 - + - + 16 - + - + 0.43 - + 10 - + 10.123 - + 17 - + 18 - + 19 - + 20 - + 21 - + 22 - + 23 - + 24 - + 25 - + 26 - + "this is a quote: """ - + '<Sheet2>'!B2 - + A39 @@ -13204,7 +13046,7 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Simple model - + (1+2)/3 @@ -13252,7 +13094,7 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Simple model - + 42 @@ -13267,11 +13109,11 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Simple model "content": " - + - + @@ -13285,11 +13127,6 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Simple model - - - - - @@ -13496,39 +13333,36 @@ exports[`Test XLSX export Generic sheets (style, hidden, size, cf) Simple model - - - - + + + - + + + + - - - - - - - + + - + - + - - - - - - - - - + + + + + + + + + @@ -13781,7 +13615,7 @@ exports[`Test XLSX export Header grouping export Nested grouped headers 1`] = ` - + @@ -13807,9 +13641,7 @@ exports[`Test XLSX export Header grouping export Nested grouped headers 1`] = ` - - - + @@ -13939,7 +13771,7 @@ exports[`Test XLSX export Header grouping export Nested grouped headers 2`] = ` - + @@ -13965,9 +13797,7 @@ exports[`Test XLSX export Header grouping export Nested grouped headers 2`] = ` - - - + @@ -14091,7 +13921,7 @@ exports[`Test XLSX export Header grouping export Simple grouped headers 1`] = ` - + @@ -14117,9 +13947,7 @@ exports[`Test XLSX export Header grouping export Simple grouped headers 1`] = ` - - - + @@ -14235,7 +14063,7 @@ exports[`Test XLSX export Header grouping export Simple grouped headers 2`] = ` - + @@ -14261,9 +14089,7 @@ exports[`Test XLSX export Header grouping export Simple grouped headers 2`] = ` - - - + @@ -14441,7 +14267,7 @@ exports[`Test XLSX export Images image larger than the sheet 1`] = ` - + @@ -14467,9 +14293,7 @@ exports[`Test XLSX export Images image larger than the sheet 1`] = ` - - - + @@ -14662,7 +14486,7 @@ exports[`Test XLSX export Images image overflowing outside the sheet 1`] = ` - + @@ -14688,9 +14512,7 @@ exports[`Test XLSX export Images image overflowing outside the sheet 1`] = ` - - - + @@ -14988,7 +14810,7 @@ exports[`Test XLSX export Images images in different sheets 1`] = ` - + @@ -15014,9 +14836,7 @@ exports[`Test XLSX export Images images in different sheets 1`] = ` - - - + @@ -15282,7 +15102,7 @@ exports[`Test XLSX export Images multiple images in the same sheet 1`] = ` - + @@ -15308,9 +15128,7 @@ exports[`Test XLSX export Images multiple images in the same sheet 1`] = ` - - - + @@ -15504,7 +15322,7 @@ exports[`Test XLSX export Images simple image 1`] = ` - + @@ -15530,9 +15348,7 @@ exports[`Test XLSX export Images simple image 1`] = ` - - - + @@ -15709,7 +15525,7 @@ exports[`Test XLSX export Sheet with frozen panes 1`] = ` - + @@ -15735,9 +15551,7 @@ exports[`Test XLSX export Sheet with frozen panes 1`] = ` - - - + @@ -15897,7 +15711,7 @@ exports[`Test XLSX export Sheet with hide gridlines 1`] = ` - + @@ -15923,9 +15737,7 @@ exports[`Test XLSX export Sheet with hide gridlines 1`] = ` - - - + @@ -16085,7 +15897,7 @@ exports[`Test XLSX export Workbook with hidden sheet 1`] = ` - + @@ -16111,9 +15923,7 @@ exports[`Test XLSX export Workbook with hidden sheet 1`] = ` - - - + @@ -16219,1512 +16029,1512 @@ exports[`Test XLSX export formulas All exportable formulas 1`] = ` - + 0 - + 1 - + 2 - + 3 - + 4 - + 5 - + 0.1 - + ABS(-5.5) - + 6 - + 26 - + 1204.7 - + 25618 - + 5 - + 0.2 - + ACOS(1) - + 7 - + 13 - + 500.9 - + 23000 - + 7 - + 0.4 - + ACOSH(2) - + 8 - + 26 - + 252.4 - + 110120.5 - + 3 - + 0.5 - + _xlfn.ACOT(1) - + _xlfn.ACOT(_xlfn.ACOT(1)) - + 9 - + 42 - + 4701.3 - + 50024 - + 4 - + 0.6 - + _xlfn.ACOTH(2) - + 10 - + 9 - + 12.1 - + 2 - + 1000 - + 11 - + AND(TRUE,TRUE) - + 12 - + 27 - + 4000 - + 189576 - + 2 - + 1 - + ASIN(0.5) - + 13 - + 30 - + 12052 - + 256018 - + 1 - + 0 - + ASINH(2) - + 14 - + 37 - + 4890.1 - + 5000 - + 30 - + ATAN(1) - + ATAN2(-1,0) - + 15 - + ATANH(0.7) - + 1 - + 2 - + 3 - + 4 - + 5 - + AVEDEV(I2:I9) - + 8 - + 16 - + 17 - + 18 - + 19 - + AVERAGE(H2:H9) - + AVERAGEA(G2:H9) - + AVERAGEIF(J2:J9,">150000") - + AVERAGEIFS(I2:I9,H2:H9,">=30",K2:K9,"<10") - + CEILING(20.4,1) - + _xlfn.CEILING.MATH(-5.5,1,0) - + _xlfn.CEILING.PRECISE(230,100) - + CHAR(74) - + COLUMN(C4) - + COLUMNS(A5:D12) - + _xlfn.CONCAT(1,23) - + CONCATENATE("BUT, ","MICHEL") - + COS(PI()/3) - + COSH(2) - + _xlfn.COT(PI()/6) - + _xlfn.COTH(0.5) - + COUNT(1,"a","5","2021-03-14") - + COUNTA(1,"a","5","2021-03-14") - + COUNTBLANK("","1",3,FALSE) - + COUNTIF(H2:H9,">30") - + COUNTIFS(H2:H9,">25",K2:K9,"<4") - + COVAR(H2:H9,K2:K9) - + _xlfn.COVARIANCE.P(K2:K9,H2:H9) - + _xlfn.COVARIANCE.P(I2:I9,J2:J9) - + _xlfn.CSC(PI()/4) - + _xlfn.CSCH(PI()/3) - + DATE(2020,5,25) - + DATEVALUE("1969-08-15") - + DAVERAGE(G1:K9,"Tot. Score",J12:J13) - + DAY("2020-03-17") - + _xlfn.DAYS("2022-03-17","2021-03-17") - + DCOUNT(G1:K9,"Name",H12:H13) - + DCOUNTA(G1:K9,"Name",H12:H13) - + _xlfn.DECIMAL(20,16) - + DEGREES(PI()/4) - + DGET(G1:K9,"Hours Played",G12:G13) - + DMAX(G1:K9,"Tot. Score",I12:I13) - + DMIN(G1:K9,"Tot. Score",H12:H13) - + DPRODUCT(G1:K9,"Age",K12:K13) - + DSTDEV(G1:K9,"Age",H12:H13) - + DSTDEVP(G1:K9,"Age",H12:H13) - + DSUM(G1:K9,"Age",I12:I13) - + DVAR(G1:K9,"Hours Played",H12:H13) - + DVARP(G1:K9,"Hours Played",H12:H13) - + EDATE("1969-07-22",-2) - + EOMONTH("2020-07-21",1) - + EXACT("AbsSdf%","AbsSdf%") - + EXP(4) - + FIND("A","qbdahbaazo A") - + FLOOR(5.5,2) - + _xlfn.FLOOR.MATH(-5.55,2,1) - + _xlfn.FLOOR.PRECISE(199,100) - + HLOOKUP("Tot. Score",H1:K9,4,FALSE) - + HOUR("02:14:56") - + IF(TRUE,"TABOURET","JAMBON") - + IFERROR(0/0,"no diving by zero.") - + _xlfn.IFS($H2>$H3,"first player is older",$H3>$H2,"second player is older") - + ISERROR(0/0) - + ISEVEN(3) - + ISLOGICAL("TRUE") - + ISNONTEXT(TRUE) - + ISNUMBER(1231.5) - + ISO.CEILING(-7.89) - + ISODD(4) - + _xlfn.ISOWEEKNUM("2016-01-03") - + ISTEXT("123") - + LARGE(H2:H9,3) - + LEFT("Mich",4) - + LEN("anticonstitutionnellement") - + ROUND(LN(2),5) - + LOOKUP(42,H2:J9) - + LOWER("オAドB") - + MATCH(42,H2:H9,0) - + MAX(N1:N8) - + MAXA(N1:N8) - + _xlfn.MAXIFS(H2:H9,K2:K9,"<20",K2:K9,"<>4") - + MEDIAN(-1,6,7,234,163845) - + MIN(N1:N8) - + MINA(N1:N8) - + _xlfn.MINIFS(J2:J9,H2:H9,">20") - + MINUTE(0.126) - + MOD(42,12) - + MONTH("1954-05-02") - + NETWORKDAYS("2013-01-01","2013-02-01") - + NETWORKDAYS.INTL("2013-01-01","2013-02-01","0000111") - + NOT(FALSE) - + NOW() - + ODD(4) - + OR("true",FALSE) - + PERCENTILE(N1:N5,1) - + _xlfn.PERCENTILE.EXC(N1:N5,0.5) - + _xlfn.PERCENTILE.INC(N1:N5,0) - + PI() - + POWER(42,2) - + PRODUCT(1,2,3) - + QUARTILE(N1:N5,0) - + _xlfn.QUARTILE.EXC(N1:N5,1) - + _xlfn.QUARTILE.INC(N1:N5,4) - + RAND() - + RANDBETWEEN(1.1,2) - + REPLACE("ABZ",2,1,"Y") - + RIGHT("kikou",2) - + ROUND(49.9,1) - + ROUNDDOWN(42,-1) - + ROUNDUP(-1.6,0) - + ROW(A234) - + ROWS(B3:C40) - + SEARCH("C","ABCD") - + _xlfn.SEC(PI()/3) - + _xlfn.SECH(1) - + SECOND("00:21:42") - + SIN(PI()/6) - + SINH(1) - + SMALL(H2:H9,3) - + SQRT(4) - + STDEV(-2,0,2) - + _xlfn.STDEV.P(2,4) - + _xlfn.STDEV.S(2,4,6) - + STDEVA(TRUE,3,5) - + STDEVP(2,5,8) - + STDEVPA(TRUE,4,7) - + SUBSTITUTE("SAP is best","SAP","Odoo") - + SUM(1,2,3,4,5) - + SUMIF(K2:K9,"<100") - + SUMIFS(H2:H9,K2:K9,"<100") - + TAN(PI()/4) - + TANH(1) - + _xlfn.TEXTJOIN("-",TRUE,"","1","A","%") - + TIME(9,11,31) - + TIMEVALUE("18:00:00") - + TODAY() - + TRIM(" Jean Ticonstitutionnalise ") - + TRUNC(42.42,1) - + UPPER("grrrr !") - + VAR(K1:K5) - + _xlfn.VAR.P(K1:K5) - + _xlfn.VAR.S(2,5,8) - + VARA(K1:K5) - + VARP(K1:K5) - + VARPA(K1:K5) - + VLOOKUP("NotACheater",G1:K9,3,FALSE) - + WEEKDAY("2021-06-12") - + WEEKNUM("2021-06-29") - + WORKDAY("2021-03-15",6) - + WORKDAY.INTL("2021-03-15",6,"0111111") - + _xlfn.XOR(FALSE,TRUE,FALSE,FALSE) - + YEAR("2012-03-12") - + DELTA(1,1) - + NA() - + ISNA(A162) - + ISERR(A162) - + HYPERLINK("https://www.odoo.com","Odoo") - + ADDRESS(27,53,4,FALSE,"sheet!") - + DATEDIF("2002-01-01","2002-01-02","D") - + RANDARRAY(2,2) - + - + - + @@ -17736,12 +17546,7 @@ exports[`Test XLSX export formulas All exportable formulas 1`] = ` "content": " - - - - - - + @@ -17770,11 +17575,8 @@ exports[`Test XLSX export formulas All exportable formulas 1`] = ` - - - - - + + @@ -17978,525 +17780,525 @@ exports[`Test XLSX export formulas All non-exportable formulas 1`] = ` - + 0 - + 4 - + 1 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + 66 - + 2 - + 1 - + 1 - + 1 - + 2 - + 1 - + 18 - + 84 - + 1 - + 27 - + 3 - + 0.04 - + 42 - + 2.5 - + 213 - + 0 - + 1000 - + SUM(A3:Z3) - + SUM(A3:A100) - + 2 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -18509,12 +18311,7 @@ exports[`Test XLSX export formulas All non-exportable formulas 1`] = ` - - - - - - + @@ -18543,12 +18340,9 @@ exports[`Test XLSX export formulas All non-exportable formulas 1`] = ` - - - - - - + + + @@ -18709,7 +18503,7 @@ exports[`Test XLSX export formulas Multi-Sheet export async functions without cr - + 5 @@ -18724,12 +18518,7 @@ exports[`Test XLSX export formulas Multi-Sheet export async functions without cr "content": " - - - - - - + @@ -18758,11 +18547,8 @@ exports[`Test XLSX export formulas Multi-Sheet export async functions without cr - - - - - + + @@ -18869,7 +18655,7 @@ exports[`Test XLSX export formulas Multi-Sheet export functions with cross refer - + SUM(Sheet2!A1) @@ -18917,7 +18703,7 @@ exports[`Test XLSX export formulas Multi-Sheet export functions with cross refer - + 5 @@ -18932,12 +18718,7 @@ exports[`Test XLSX export formulas Multi-Sheet export functions with cross refer "content": " - - - - - - + @@ -18966,11 +18747,8 @@ exports[`Test XLSX export formulas Multi-Sheet export functions with cross refer - - - - - + + @@ -19077,1512 +18855,1512 @@ exports[`Test XLSX export formulas Multi-Sheets exportable functions 1`] = ` - + 0 - + 1 - + 2 - + 3 - + 4 - + 5 - + 0.1 - + ABS(-5.5) - + 6 - + 26 - + 1204.7 - + 25618 - + 5 - + 0.2 - + ACOS(1) - + 7 - + 13 - + 500.9 - + 23000 - + 7 - + 0.4 - + ACOSH(2) - + 8 - + 26 - + 252.4 - + 110120.5 - + 3 - + 0.5 - + _xlfn.ACOT(1) - + _xlfn.ACOT(_xlfn.ACOT(1)) - + 9 - + 42 - + 4701.3 - + 50024 - + 4 - + 0.6 - + _xlfn.ACOTH(2) - + 10 - + 9 - + 12.1 - + 2 - + 1000 - + 11 - + AND(TRUE,TRUE) - + 12 - + 27 - + 4000 - + 189576 - + 2 - + 1 - + ASIN(0.5) - + 13 - + 30 - + 12052 - + 256018 - + 1 - + 0 - + ASINH(2) - + 14 - + 37 - + 4890.1 - + 5000 - + 30 - + ATAN(1) - + ATAN2(-1,0) - + 15 - + ATANH(0.7) - + 1 - + 2 - + 3 - + 4 - + 5 - + AVEDEV(I2:I9) - + 8 - + 16 - + 17 - + 18 - + 19 - + AVERAGE(H2:H9) - + AVERAGEA(G2:H9) - + AVERAGEIF(J2:J9,">150000") - + AVERAGEIFS(I2:I9,H2:H9,">=30",K2:K9,"<10") - + CEILING(20.4,1) - + _xlfn.CEILING.MATH(-5.5,1,0) - + _xlfn.CEILING.PRECISE(230,100) - + CHAR(74) - + COLUMN(C4) - + COLUMNS(A5:D12) - + _xlfn.CONCAT(1,23) - + CONCATENATE("BUT, ","MICHEL") - + COS(PI()/3) - + COSH(2) - + _xlfn.COT(PI()/6) - + _xlfn.COTH(0.5) - + COUNT(1,"a","5","2021-03-14") - + COUNTA(1,"a","5","2021-03-14") - + COUNTBLANK("","1",3,FALSE) - + COUNTIF(H2:H9,">30") - + COUNTIFS(H2:H9,">25",K2:K9,"<4") - + COVAR(H2:H9,K2:K9) - + _xlfn.COVARIANCE.P(K2:K9,H2:H9) - + _xlfn.COVARIANCE.P(I2:I9,J2:J9) - + _xlfn.CSC(PI()/4) - + _xlfn.CSCH(PI()/3) - + DATE(2020,5,25) - + DATEVALUE("1969-08-15") - + DAVERAGE(G1:K9,"Tot. Score",J12:J13) - + DAY("2020-03-17") - + _xlfn.DAYS("2022-03-17","2021-03-17") - + DCOUNT(G1:K9,"Name",H12:H13) - + DCOUNTA(G1:K9,"Name",H12:H13) - + _xlfn.DECIMAL(20,16) - + DEGREES(PI()/4) - + DGET(G1:K9,"Hours Played",G12:G13) - + DMAX(G1:K9,"Tot. Score",I12:I13) - + DMIN(G1:K9,"Tot. Score",H12:H13) - + DPRODUCT(G1:K9,"Age",K12:K13) - + DSTDEV(G1:K9,"Age",H12:H13) - + DSTDEVP(G1:K9,"Age",H12:H13) - + DSUM(G1:K9,"Age",I12:I13) - + DVAR(G1:K9,"Hours Played",H12:H13) - + DVARP(G1:K9,"Hours Played",H12:H13) - + EDATE("1969-07-22",-2) - + EOMONTH("2020-07-21",1) - + EXACT("AbsSdf%","AbsSdf%") - + EXP(4) - + FIND("A","qbdahbaazo A") - + FLOOR(5.5,2) - + _xlfn.FLOOR.MATH(-5.55,2,1) - + _xlfn.FLOOR.PRECISE(199,100) - + HLOOKUP("Tot. Score",H1:K9,4,FALSE) - + HOUR("02:14:56") - + IF(TRUE,"TABOURET","JAMBON") - + IFERROR(0/0,"no diving by zero.") - + _xlfn.IFS($H2>$H3,"first player is older",$H3>$H2,"second player is older") - + ISERROR(0/0) - + ISEVEN(3) - + ISLOGICAL("TRUE") - + ISNONTEXT(TRUE) - + ISNUMBER(1231.5) - + ISO.CEILING(-7.89) - + ISODD(4) - + _xlfn.ISOWEEKNUM("2016-01-03") - + ISTEXT("123") - + LARGE(H2:H9,3) - + LEFT("Mich",4) - + LEN("anticonstitutionnellement") - + ROUND(LN(2),5) - + LOOKUP(42,H2:J9) - + LOWER("オAドB") - + MATCH(42,H2:H9,0) - + MAX(N1:N8) - + MAXA(N1:N8) - + _xlfn.MAXIFS(H2:H9,K2:K9,"<20",K2:K9,"<>4") - + MEDIAN(-1,6,7,234,163845) - + MIN(N1:N8) - + MINA(N1:N8) - + _xlfn.MINIFS(J2:J9,H2:H9,">20") - + MINUTE(0.126) - + MOD(42,12) - + MONTH("1954-05-02") - + NETWORKDAYS("2013-01-01","2013-02-01") - + NETWORKDAYS.INTL("2013-01-01","2013-02-01","0000111") - + NOT(FALSE) - + NOW() - + ODD(4) - + OR("true",FALSE) - + PERCENTILE(N1:N5,1) - + _xlfn.PERCENTILE.EXC(N1:N5,0.5) - + _xlfn.PERCENTILE.INC(N1:N5,0) - + PI() - + POWER(42,2) - + PRODUCT(1,2,3) - + QUARTILE(N1:N5,0) - + _xlfn.QUARTILE.EXC(N1:N5,1) - + _xlfn.QUARTILE.INC(N1:N5,4) - + RAND() - + RANDBETWEEN(1.1,2) - + REPLACE("ABZ",2,1,"Y") - + RIGHT("kikou",2) - + ROUND(49.9,1) - + ROUNDDOWN(42,-1) - + ROUNDUP(-1.6,0) - + ROW(A234) - + ROWS(B3:C40) - + SEARCH("C","ABCD") - + _xlfn.SEC(PI()/3) - + _xlfn.SECH(1) - + SECOND("00:21:42") - + SIN(PI()/6) - + SINH(1) - + SMALL(H2:H9,3) - + SQRT(4) - + STDEV(-2,0,2) - + _xlfn.STDEV.P(2,4) - + _xlfn.STDEV.S(2,4,6) - + STDEVA(TRUE,3,5) - + STDEVP(2,5,8) - + STDEVPA(TRUE,4,7) - + SUBSTITUTE("SAP is best","SAP","Odoo") - + SUM(1,2,3,4,5) - + SUMIF(K2:K9,"<100") - + SUMIFS(H2:H9,K2:K9,"<100") - + TAN(PI()/4) - + TANH(1) - + _xlfn.TEXTJOIN("-",TRUE,"","1","A","%") - + TIME(9,11,31) - + TIMEVALUE("18:00:00") - + TODAY() - + TRIM(" Jean Ticonstitutionnalise ") - + TRUNC(42.42,1) - + UPPER("grrrr !") - + VAR(K1:K5) - + _xlfn.VAR.P(K1:K5) - + _xlfn.VAR.S(2,5,8) - + VARA(K1:K5) - + VARP(K1:K5) - + VARPA(K1:K5) - + VLOOKUP("NotACheater",G1:K9,3,FALSE) - + WEEKDAY("2021-06-12") - + WEEKNUM("2021-06-29") - + WORKDAY("2021-03-15",6) - + WORKDAY.INTL("2021-03-15",6,"0111111") - + _xlfn.XOR(FALSE,TRUE,FALSE,FALSE) - + YEAR("2012-03-12") - + DELTA(1,1) - + NA() - + ISNA(A162) - + ISERR(A162) - + HYPERLINK("https://www.odoo.com","Odoo") - + ADDRESS(27,53,4,FALSE,"sheet!") - + DATEDIF("2002-01-01","2002-01-02","D") - + RANDARRAY(2,2) - + - + - + @@ -20627,7 +20405,7 @@ exports[`Test XLSX export formulas Multi-Sheets exportable functions 1`] = ` - + 20 @@ -20642,12 +20420,7 @@ exports[`Test XLSX export formulas Multi-Sheets exportable functions 1`] = ` "content": " - - - - - - + @@ -20676,11 +20449,8 @@ exports[`Test XLSX export formulas Multi-Sheets exportable functions 1`] = ` - - - - - + + @@ -20891,14 +20661,14 @@ exports[`Test XLSX export formulas Non exportable formulas are exported even wit - + 0 - + 0 @@ -20913,12 +20683,7 @@ exports[`Test XLSX export formulas Non exportable formulas are exported even wit "content": " - - - - - - + @@ -20947,11 +20712,8 @@ exports[`Test XLSX export formulas Non exportable formulas are exported even wit - - - - - + + @@ -21055,35 +20817,35 @@ exports[`Test XLSX export link cells 1`] = ` - + 0 - + 0 - + 1 - + 2 - + 1 @@ -21105,12 +20867,7 @@ exports[`Test XLSX export link cells 1`] = ` "content": " - - - - - - + @@ -21139,11 +20896,8 @@ exports[`Test XLSX export link cells 1`] = ` - - - - - + + @@ -21590,7 +21344,7 @@ exports[`Test XLSX export multiple elements are exported in the correct order 1` - + 0 @@ -21619,12 +21373,7 @@ exports[`Test XLSX export multiple elements are exported in the correct order 1` "content": " - - - - - - + @@ -21653,11 +21402,8 @@ exports[`Test XLSX export multiple elements are exported in the correct order 1` - - - - - + + @@ -24242,7 +23988,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -24268,9 +24014,7 @@ exports[`Test XLSX export references with headers should be converted to referen - - - + @@ -24370,22 +24114,22 @@ exports[`Test XLSX export references with headers should be converted to referen - + SUM(B3:B5) - + - + - + @@ -24411,12 +24155,7 @@ exports[`Test XLSX export references with headers should be converted to referen "content": " - - - - - - + @@ -24445,11 +24184,8 @@ exports[`Test XLSX export references with headers should be converted to referen - - - - - + +