From c712b02990660b26c15d8a9f5dbb8830ad160e5b Mon Sep 17 00:00:00 2001 From: "Adrien Minne (adrm)" Date: Thu, 30 Mar 2023 15:14:35 +0000 Subject: [PATCH] [IMP] xlsx_import: support more date formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now try to parse and modify the xlsx date formats at import to get a format supported by o_spreadsheet. Odoo task 3222986 closes odoo/o-spreadsheet#2293 Signed-off-by: Lucas Lefèvre (lul) --- src/constants.ts | 2 +- src/xlsx/conversion/format_conversion.ts | 87 ++++ src/xlsx/conversion/style_conversion.ts | 52 +- .../__xlsx__/xlsx_demo_data/docProps/app.xml | 2 +- .../__xlsx__/xlsx_demo_data/docProps/core.xml | 2 +- .../__xlsx__/xlsx_demo_data/xl/calcChain.xml | 2 +- .../xlsx_demo_data/xl/sharedStrings.xml | 5 +- tests/__xlsx__/xlsx_demo_data/xl/styles.xml | 35 +- .../xlsx_demo_data/xl/tables/table1.xml | 18 +- tests/__xlsx__/xlsx_demo_data/xl/workbook.xml | 8 +- .../xl/worksheets/_rels/sheet4.xml.rels | 4 - .../xlsx_demo_data/xl/worksheets/sheet1.xml | 37 +- .../xlsx_demo_data/xl/worksheets/sheet2.xml | 46 +- .../xlsx_demo_data/xl/worksheets/sheet3.xml | 14 +- .../xlsx_demo_data/xl/worksheets/sheet4.xml | 394 +++++--------- .../xlsx_demo_data/xl/worksheets/sheet5.xml | 480 +++++++++--------- .../xlsx_demo_data/xl/worksheets/sheet6.xml | 123 +++-- .../xlsx_demo_data/xl/worksheets/sheet7.xml | 298 ++++------- .../xlsx_demo_data/xl/worksheets/sheet9.xml | 6 +- tests/xlsx_import.test.ts | 46 +- 20 files changed, 703 insertions(+), 958 deletions(-) create mode 100644 src/xlsx/conversion/format_conversion.ts delete mode 100644 tests/__xlsx__/xlsx_demo_data/xl/worksheets/_rels/sheet4.xml.rels diff --git a/src/constants.ts b/src/constants.ts index fb6cd967b6..de87fd1668 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -148,7 +148,7 @@ export const DEFAULT_BORDER_DESC: BorderDescr = ["thin", "#000"]; export const DEFAULT_FILTER_BORDER_DESC: BorderDescr = ["thin", FILTERS_COLOR]; // DateTimeRegex -export const DATETIME_FORMAT = /[ymd:]/; +export const DATETIME_FORMAT = /[ymdhs:]/; // Ranges export const INCORRECT_RANGE_STRING = CellErrorType.InvalidReference; diff --git a/src/xlsx/conversion/format_conversion.ts b/src/xlsx/conversion/format_conversion.ts new file mode 100644 index 0000000000..8a624f92f9 --- /dev/null +++ b/src/xlsx/conversion/format_conversion.ts @@ -0,0 +1,87 @@ +import { formatValue } from "../../helpers"; +import { XLSXNumFormat } from "../../types/xlsx"; +import { WarningTypes, XLSXImportWarningManager } from "../helpers/xlsx_parser_error_manager"; +import { XLSX_FORMATS_CONVERSION_MAP } from "./conversion_maps"; + +const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i; + +/** + * Convert excel format to o_spreadsheet format + * + * Excel format are defined in openXML §18.8.31 + */ +export function convertXlsxFormat( + numFmtId: number, + formats: XLSXNumFormat[], + warningManager: XLSXImportWarningManager +): string | undefined { + if (numFmtId === 0) { + return undefined; + } + // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30 + let format = + XLSX_FORMATS_CONVERSION_MAP[numFmtId] || formats.find((f) => f.id === numFmtId)?.format; + + if (format) { + try { + let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format + convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31) + convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks + + // Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format + const numberOfQuotes = convertedFormat.match(/"/g)?.length || 0; + const numberOfOpenBrackets = convertedFormat.match(/\[/g)?.length || 0; + if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) { + throw new Error("Multiple escaped blocks in format"); + } + convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]' + + convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore width of next char for align purposes. Not supported ATM + convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM + + convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces + + convertedFormat = convertedFormat.replace(/\\./g, (match) => match[1]); // unescape other characters + + if (isXlsxDateFormat(convertedFormat)) { + convertedFormat = convertDateFormat(convertedFormat); + } + + if (isFormatSupported(convertedFormat)) { + return convertedFormat; + } + } catch (e) {} + } + + warningManager.generateNotSupportedWarning( + WarningTypes.NumFmtIdNotSupported, + format || `nmFmtId ${numFmtId}` + ); + return undefined; +} + +function isFormatSupported(format: string): boolean { + try { + formatValue(0, format); + return true; + } catch (e) { + return false; + } +} + +function isXlsxDateFormat(format: string): boolean { + return format.match(XLSX_DATE_FORMAT_REGEX) !== null; +} + +function convertDateFormat(format: string): string { + // Some of these aren't defined neither in the OpenXML spec not the Xlsx extension of OpenXML, + // but can still occur and are supported by Excel/Google sheets + + format = format.toLowerCase(); + format = format.replace(/mmmmm/g, "mmm"); + format = format.replace(/am\/pm|a\/m/g, "a"); + format = format.replace(/hhhh/g, "hh"); + format = format.replace(/\bh\b/g, "hh"); + + return format; +} diff --git a/src/xlsx/conversion/style_conversion.ts b/src/xlsx/conversion/style_conversion.ts index b94e41f3c8..d1918faaf4 100644 --- a/src/xlsx/conversion/style_conversion.ts +++ b/src/xlsx/conversion/style_conversion.ts @@ -1,5 +1,4 @@ import { fontSizeMap } from "../../fonts"; -import { formatValue } from "../../helpers"; import { Border, BorderDescr, Style } from "../../types"; import { XLSXBorder, @@ -9,7 +8,6 @@ import { XLSXFont, XLSXHorizontalAlignment, XLSXImportData, - XLSXNumFormat, XLSXVerticalAlignment, } from "../../types/xlsx"; import { arrayToObject } from "../helpers/misc"; @@ -22,8 +20,8 @@ import { SUPPORTED_FILL_PATTERNS, SUPPORTED_FONTS, SUPPORTED_HORIZONTAL_ALIGNMENTS, - XLSX_FORMATS_CONVERSION_MAP, } from "./conversion_maps"; +import { convertXlsxFormat } from "./format_conversion"; interface StyleStruct { fontStyle?: XLSXFont; @@ -124,54 +122,6 @@ export function convertFormats( return arrayToObject(formats, 1); } -/** - * Convert excel format to o_spreadsheet format - * - * Excel format are defined in openXML §18.8.31 - */ -export function convertXlsxFormat( - numFmtId: number, - formats: XLSXNumFormat[], - warningManager: XLSXImportWarningManager -): string | undefined { - if (numFmtId === 0) { - return undefined; - } - // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30 - let format = - XLSX_FORMATS_CONVERSION_MAP[numFmtId] || formats.find((f) => f.id === numFmtId)?.format; - - if (format) { - try { - let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format - convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31) - convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks - - // Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format - const numberOfQuotes = convertedFormat.match(/"/g)?.length || 0; - const numberOfOpenBrackets = convertedFormat.match(/\[/g)?.length || 0; - if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) { - throw new Error("Multiple escaped blocks in format"); - } - convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]' - - convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore with of next char for align purposes. Not supported ATM - convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM - - convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces - - formatValue(0, convertedFormat); - return convertedFormat; - } catch (e) {} - } - - warningManager.generateNotSupportedWarning( - WarningTypes.NumFmtIdNotSupported, - format || `nmFmtId ${numFmtId}` - ); - return undefined; -} - /** * We currently only support only a set of font sizes, we cannot define new font sizes. * This function adapts an arbitrary font size to the closest supported font size. diff --git a/tests/__xlsx__/xlsx_demo_data/docProps/app.xml b/tests/__xlsx__/xlsx_demo_data/docProps/app.xml index 6de9966268..c3f76e3cda 100644 --- a/tests/__xlsx__/xlsx_demo_data/docProps/app.xml +++ b/tests/__xlsx__/xlsx_demo_data/docProps/app.xml @@ -9,7 +9,7 @@ Worksheets - 10 + 11 diff --git a/tests/__xlsx__/xlsx_demo_data/docProps/core.xml b/tests/__xlsx__/xlsx_demo_data/docProps/core.xml index 91cd0d506c..c5577ad9a4 100644 --- a/tests/__xlsx__/xlsx_demo_data/docProps/core.xml +++ b/tests/__xlsx__/xlsx_demo_data/docProps/core.xml @@ -2,5 +2,5 @@ Adrien 2022-02-10T15:47:12Z - 2022-10-11T11:39:36Z + 2023-03-28T12:16:40Z diff --git a/tests/__xlsx__/xlsx_demo_data/xl/calcChain.xml b/tests/__xlsx__/xlsx_demo_data/xl/calcChain.xml index 3e64084422..ea39ba4488 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/calcChain.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/calcChain.xml @@ -370,5 +370,5 @@ - + diff --git a/tests/__xlsx__/xlsx_demo_data/xl/sharedStrings.xml b/tests/__xlsx__/xlsx_demo_data/xl/sharedStrings.xml index b349fa7873..c6c7a16480 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/sharedStrings.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/sharedStrings.xml @@ -1,5 +1,5 @@ - + CF =42 @@ -1210,9 +1210,6 @@ #,##0[$ EUR €] - - d/m/yy - not supported: multiple escaped sequences diff --git a/tests/__xlsx__/xlsx_demo_data/xl/styles.xml b/tests/__xlsx__/xlsx_demo_data/xl/styles.xml index a7eb8fa17f..99cc5a7b71 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/styles.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/styles.xml @@ -1,11 +1,10 @@ - + - @@ -700,7 +699,7 @@ - + @@ -765,15 +764,10 @@ - - - - - @@ -795,7 +789,6 @@ - @@ -808,17 +801,12 @@ - - - - - @@ -848,10 +836,6 @@ - - - - @@ -867,21 +851,10 @@ - + - - - - - - - - - - - @@ -889,7 +862,6 @@ - @@ -902,7 +874,6 @@ - diff --git a/tests/__xlsx__/xlsx_demo_data/xl/tables/table1.xml b/tests/__xlsx__/xlsx_demo_data/xl/tables/table1.xml index 957f31d5f3..36f7b2ba55 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/tables/table1.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/tables/table1.xml @@ -1,5 +1,5 @@ - +
@@ -11,22 +11,22 @@ - - - - + + + + Table3[[#This Row],[Rank]]+Table3[[#This Row],[Age]] - + SUM(Table3[Rank]) - + SUM(Table3[[#All],[Rank]]) - + Table3[[#Totals],[Rank]] - + Table3[[#Headers],[Rank]] diff --git a/tests/__xlsx__/xlsx_demo_data/xl/workbook.xml b/tests/__xlsx__/xlsx_demo_data/xl/workbook.xml index 82eeff5aad..ef3f4a6dd0 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/workbook.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/workbook.xml @@ -1,15 +1,15 @@ - + - + - + - + diff --git a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/_rels/sheet4.xml.rels b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/_rels/sheet4.xml.rels deleted file mode 100644 index f252cca8e6..0000000000 --- a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/_rels/sheet4.xml.rels +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet1.xml b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet1.xml index a9026497c0..bc5e7b2c21 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet1.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet1.xml @@ -16,7 +16,7 @@ - + 0 @@ -25,7 +25,7 @@ - + 2 @@ -34,10 +34,10 @@ 5 - + 4 - + @@ -47,10 +47,10 @@ 8 - - + + - + 5 @@ -68,10 +68,10 @@ 9 - - + + - + @@ -81,10 +81,10 @@ 15 - - + + - + @@ -92,7 +92,7 @@ 22 - + @@ -100,7 +100,7 @@ 3 - + @@ -108,7 +108,7 @@ 30 - + @@ -129,7 +129,6 @@ 9 - @@ -160,7 +159,6 @@ C14 #CYCLE - @@ -182,7 +180,6 @@ 14 - @@ -409,7 +406,7 @@ - + 42 diff --git a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet2.xml b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet2.xml index 43ea3e4d7b..f9fd1add36 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet2.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet2.xml @@ -83,11 +83,11 @@ SUM(H2, I$2) 1230.7 - + SUM(H2, $I2) 1230.7 - + SUM(H2, $I$2) 1230.7 @@ -125,15 +125,15 @@ 0.4 - + SUM(H3, I$2) 1217.7 - + SUM(H3, $I3) 513.9 - + SUM(H3, $I$2) 1217.7 @@ -171,15 +171,15 @@ 0.5 - + 1230.7 - + 278.39999999999998 - + 1230.7 @@ -217,15 +217,15 @@ 0.6 - + 1246.7 - + 4743.3 - + 1246.7 @@ -263,15 +263,15 @@ 50 - + 1213.7 - + 21.1 - + 1213.7 @@ -309,7 +309,6 @@ 1 - @@ -344,8 +343,6 @@ 0 - - @@ -377,7 +374,6 @@ 30 - @@ -394,7 +390,6 @@ 1 - @@ -414,8 +409,6 @@ 59 - - @@ -447,7 +440,6 @@ 39 - @@ -479,7 +471,6 @@ 65 - @@ -496,7 +487,6 @@ 1 - @@ -1869,7 +1859,7 @@ NOW() - 44659.691878356483 + 45013.594915277776 IF(ISNUMBER(B100),1,0) @@ -2559,7 +2549,7 @@ TODAY() - 44659 + 45013 IF(ISNUMBER(B144),1,0) @@ -2841,12 +2831,12 @@ - + 1 - + 0 diff --git a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet3.xml b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet3.xml index 8fc7353d3e..296280f783 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet3.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet3.xml @@ -19,14 +19,14 @@ 355 - + 358 - + 359 - + 397 @@ -35,18 +35,18 @@ SUM(A1) 0 - - + + [1]Feuil1!$A$1 referenced string - + 357 - + 396 diff --git a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet4.xml b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet4.xml index 85632f8941..aba547e43f 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet4.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet4.xml @@ -1,487 +1,373 @@ - + - - + + - - - - - - - + + + - - + + 304 - + 305 - + 306 - - + + 308 - + 309 - + 392 - + - - + + 239 - + 379 - + 274 - + 226 - + 299 - + 312 - + 395 - + 10 - - + + 240 - - + 15 - + 226 - + 300 - + 381 - + 393 - + 10 - - + + 241 - + 262 - + 275 - + 226 - + 301 - + 382 - + 394 - + 10 - - + + 242 - + 276 - + 226 - + 302 - + 401 - + 10 - - + + 243 - + 263 - + 277 - + 226 - + 303 - + 398 - + 10 - - + + 244 - + 278 - + 226 - + 310 - + 400 - + 10 - - + + 245 - + 264 - + 279 - + 226 - + 311 - - - + 402 - + 10 - - - - - + + 246 - + 280 - + 226 - - - - + 403 - + 10 - - - - - + + 247 - + 265 - - - - - - - 404 - - - 10 - - - - - - + + 248 - + 307 - - - - - - - - - + - - + + 249 - + 266 - + 281 - + 226 - - - - - - - - - - + + 250 - + 16 - + 226 - - - - - - - - + + 251 - + 267 - + 275 - + 226 - - - - - - - - + + 252 - + 278 - + 226 - - - - - - - - - - + + 253 - + 268 - + 280 - + 226 - - - - - - - - - - + + 254 - - - - - - - - - - + + 255 - + 269 - - - - - - - - - - + + 256 - - - - - - - - - - + + 257 - + 270 - - - - - - - - - - + + 258 - - - - - - - - - - + + 259 - + 271 - + - - + + 261 - + - - + + 260 - + 272 - + - - - + + + 273 - - - + + + 380 - - - + + + 378 - + diff --git a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet5.xml b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet5.xml index dff6d53b01..b4d9bb51d6 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet5.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet5.xml @@ -1,6 +1,6 @@ - + @@ -12,25 +12,25 @@ - - + + 347 - + 228 - + 229 - + 318 - - - + + + - - + + 330 @@ -39,30 +39,30 @@ 1 - + 313 - + 5 3 - + 1 - - + + 340 - + 236 - + 233 - + 314 @@ -75,14 +75,14 @@ 1 - - + + 342 - + 230 - + 315 @@ -95,8 +95,8 @@ 1 - - + + 344 @@ -106,7 +106,7 @@ 0 - + 317 @@ -119,17 +119,17 @@ 1 - - + + 338 - + 235 - + 233 - + 316 @@ -142,20 +142,20 @@ 1 - - + + 337 - + 231 - + 232 - + 231 - + 238 @@ -168,28 +168,28 @@ 1 - - + + 341 - + 234 - + 233 - - + + 343 - + 230 - + - - + + 345 @@ -199,26 +199,24 @@ 0/0 #DIV/0! - + 319 - - - - - + + + - - + + 339 - + 233 - + 234 - + 320 @@ -230,22 +228,20 @@ 1 - - - - + + 346 - + TODAY() - 44659 + 45013 - + DATE(2010,10,2) 40453 - + 323 @@ -257,11 +253,9 @@ 1 - - - - + + 335 @@ -270,191 +264,191 @@ 5 - + 321 - + 5 - + 3 - + 1 - - + + 336 - + 232 - + 231 - + 231 - + 322 - + 5 - + 3 - + 1 - - + + 331 1 - + 282 - + 5 - + 3 - + 1 - - + + 352 - + 2 - + 1 - + 283 - + 5 - + 3 - + 1 - - + + 353 - + 0 - + 2 - + 284 - + 5 - + 3 - + 1 - + 348 - + 3 - + 0 - + 285 - + 5 - + 3 - + 1 - + 349 - + 2 - + 0 - + 287 - + 5 - + 3 - + 1 - + 350 - + 0 - + 2 - + 288 - + 5 - + 3 - + 1 - + 351 - + 2 - + 3 - + 289 @@ -471,120 +465,114 @@ - + 332 - + 2 - + 0 - + 290 - + 5 - + 4 - + 3 - + 2 - + 333 - + 1 - + 2 - + 291 - + 5 - + 4 - + 3 - + 2 - - - - + 292 - + 5 - + 4 - + 3 - + 2 - + 334 - + 5 - + 2 - + 293 - + 5 - + 4 - + 3 - + 2 - - - - + 294 - + 5 - + 4 - + 3 - + 2 @@ -592,26 +580,25 @@ - + 237 - + 2 - - + 295 - + 5 - + 4 - + 3 - + 2 @@ -619,19 +606,19 @@ - + 296 - + 5 - + 4 - + 3 - + 2 @@ -639,19 +626,19 @@ - + 297 - + 5 - + 4 - + 3 - + 2 @@ -659,19 +646,19 @@ - + 298 - + 5 - + 4 - + 3 - + 2 @@ -679,173 +666,170 @@ - + 324 - + 5 - + 3 - + 1 - + 286 - + 5 - + 3 - + 1 - + 325 - + 5 - + 3 - + 1 - + 326 - + 5 - + 3 - + 1 - + 327 - + 5 - + 3 - + 1 - + 328 - + 5 - + 3 - + 1 - + 329 - + 5 - + 3 - + 1 - - - - + - + LEFT(B3,LEN("rule"))="rule" - + LEN(TRIM(B4))=0 - + ISERROR(B5) - + NOT(ISERROR(SEARCH("rule",B6))) - + RIGHT(B8,LEN("rule"))="rule" - + LEN(TRIM(B9))>0 - + NOT(ISERROR(B10)) - + ISERROR(SEARCH("rule",B11)) - + FLOOR(B12,1)=TODAY() - + ODD(B15) - + 2 - + 2 - + 2 @@ -1011,10 +995,10 @@ - + - + @@ -1031,10 +1015,10 @@ - + - + @@ -1131,33 +1115,33 @@ - + 2 - + 2 - + 2 - + 2 - + 2 4 - + 2 4 diff --git a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet6.xml b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet6.xml index 3d2e95bc71..e1efcad0fa 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet6.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet6.xml @@ -2,7 +2,7 @@ - + @@ -50,96 +50,96 @@ - + 41 - + 26 - + 5 - + Table3[[#This Row],[Rank]]+Table3[[#This Row],[Age]] 31 - + SUM(Table3[Rank]) 12 - + SUM(Table3[[#All],[Rank]]) 24 - + Table3[[#Totals],[Rank]] 12 - + Table3[[#Headers],[Rank]] Rank - + 43 - + 13 - + 7 - + Table3[[#This Row],[Rank]]+Table3[[#This Row],[Age]] 20 - + SUM(Table3[Rank]) 12 - + SUM(Table3[[#All],[Rank]]) 24 - + Table3[[#Totals],[Rank]] 12 - + Table3[[#Headers],[Rank]] Rank - + 361 - + SUBTOTAL(109,Table3[Age]) 39 - + SUBTOTAL(109,Table3[Rank]) 12 - + SUBTOTAL(109,Table3[Rank+Age =E4+D4]) 51 - + SUBTOTAL(109,Table3[Data =SUM(E4:E5)]) 24 - + SUBTOTAL(109,Table3[All =SUM(E3:E6)]) 48 - + SUBTOTAL(109,Table3[Totals =E6]) 24 - + SUBTOTAL(109,Table3[Headers =E3]) 0 @@ -183,139 +183,134 @@ - + 372 - + 1 - + 2 - - + 3 - + 4 - + 373 - + 1 - + 2 - - + 3 - + 4 - + 375 - + 1 - + 2 - - + 3 - + 4 - + 376 - + 1 - + 2 - - + 3 - + 4 - + 374 - + 1 - + 2 - - + 3 - + 4 - + 361 - + SUBTOTAL(109,Table4910[Column2]) 6 - 405 + 404 - 406 + 405 - 407 + 406 - 409 + 408 - 409 + 408 diff --git a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet7.xml b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet7.xml index 58c7e76242..fbcee51bed 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet7.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet7.xml @@ -28,7 +28,7 @@ - + 387 @@ -38,386 +38,274 @@ - - - - - - + + + + + + - - - + + + 385 - + 386 - - - + + + 383 - + 12.1 - + 252.4 - + 500.9 - + 1204.7 - + 4000 - + 4701.3 - + 4890.1000000000004 - + 12052 - + 384 - - - + + + 54 - - - - - - - - + 30 - + 30 - - - + + + 256018 - - - - - - - - + 30 - + 30 - - - + + + 45 - - + 26 - - - - - - - + 26 - - - + + + 110120.5 - - + 26 - - - - - - - + 26 - - - + + + 41 - - - - + 26 - - - - - + 26 - - - + + + 25618 - - - - + 26 - - - - - + 26 - + 43 - - - + 13 - - - - - - + 13 - + 23000 - - - + 13 - - - - - - + 13 - + 49 - + 9 - - - - - - - - + 9 - + 2 - + 9 - - - - - - - - + 9 - + 47 - - - - - - + 42 - - - + 42 - + 50024 - - - - - - + 42 - - - + 42 - + 52 - - - - - + 27 - - - - + 27 - + 189576 - - - - - + 27 - - - - + 27 - + 56 - - - - - - - + 37 - - + 37 - + 5000 - - - - - - - + 37 - - + 37 - + 384 - + 9 - + 26 - + 13 - + 26 - + 27 - + 42 - + 37 - + 30 - + 210 diff --git a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet9.xml b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet9.xml index 55268cf02b..afbb11205a 100644 --- a/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet9.xml +++ b/tests/__xlsx__/xlsx_demo_data/xl/worksheets/sheet9.xml @@ -2,14 +2,14 @@ - - + + - + 399 diff --git a/tests/xlsx_import.test.ts b/tests/xlsx_import.test.ts index 19bd03e260..4eea921775 100644 --- a/tests/xlsx_import.test.ts +++ b/tests/xlsx_import.test.ts @@ -1,12 +1,12 @@ import { ICON_SETS } from "../src/components/icons/icons"; -import { buildSheetLink, lettersToNumber, markdownLink, toZone } from "../src/helpers"; +import { buildSheetLink, formatValue, lettersToNumber, markdownLink, toZone } from "../src/helpers"; import { Border, CellIsRule, IconSetRule, Style } from "../src/types"; import { BarChartDefinition } from "../src/types/chart/bar_chart"; import { LineChartDefinition } from "../src/types/chart/line_chart"; import { PieChartDefinition } from "../src/types/chart/pie_chart"; import { XLSXCfOperatorType, XLSXSharedFormula } from "../src/types/xlsx"; -import { convertXlsxFormat } from "../src/xlsx/conversion"; import { hexaToInt } from "../src/xlsx/conversion/color_conversion"; +import { convertXlsxFormat } from "../src/xlsx/conversion/format_conversion"; import { adaptFormula } from "../src/xlsx/conversion/formula_conversion"; import { TABLE_BORDER_STYLE, @@ -180,8 +180,7 @@ describe("Import xlsx data", () => { ["[$$]#,##0.000", "M6"], ["[$₪] #,##0", "M7"], ["#,##0[$ EUR €]", "M8"], - ["d/m/yy", "M9"], - ["not supported: multiple escaped sequences", "M10"], + ["not supported: multiple escaped sequences", "M9"], ])("Can import format %s", (format, cellXc) => { const testSheet = getWorkbookSheet("jestStyles", convertedData)!; const formattedCell = testSheet.cells[cellXc]!; @@ -779,24 +778,29 @@ test.each([ }); test.each([ - ["0.00", "0.00"], - ["0.00;0.00%", "0.00"], - ["0.000%", "0.000%"], - ["#,##0.00", "#,##0.00"], - ["m/d/yyyy", "m/d/yyyy"], - ["mmm/dddd/yy", "mmm/dddd/yy"], - ["mmmm/ddd/yyyy", "mmmm/ddd/yyyy"], - ["mmmmm/dd/yy", "mmmmm/dd/yy"], - ["m/d/yyyy\\ hh:mm:ss", "m/d/yyyy hh:mm:ss"], - ["hh:mm:ss a", "hh:mm:ss a"], - ['#,##0.00 "€"', "#,##0.00 [$€]"], - ["[$$-409]#,##0.000", "[$$]#,##0.000"], - ["[$-409]0.00", "0.00"], - ["d/m/yy;@", "d/m/yy"], - ["[$₪-40D] #,##0", "[$₪] #,##0"], - ['"€"#,##0.00 "€"', undefined], -])("convert format", async (excelFormat, convertedFormat) => { + ["0.00", "0.00", "0.00"], + ["0.00;0.00%", "0.00", "0.00"], + ["0.000%", "0.000%", "0.000%"], + ["#,##0.00", "#,##0.00", "0.00"], + ["m/d/yyyy", "m/d/yyyy", "12/30/1899"], + ["M/D/YYYY", "m/d/yyyy", "12/30/1899"], + ["mmmmm/dddd/yy", "mmm/dddd/yy", "Dec/Saturday/99"], + ["mmmm-ddd-yy", "mmmm-ddd-yy", "December-Sat-99"], + ["mmm dd yy", "mmm dd yy", "Dec 30 99"], + ["h AM/PM", "hh a", "12 AM"], + ["HHHH:MM a/m", "hh:mm a", "12:00 AM"], + ["m/d/yyyy\\ hh:mm:ss", "m/d/yyyy hh:mm:ss", "12/30/1899 00:00:00"], + ["hh:mm:ss a", "hh:mm:ss a", "12:00:00 AM"], + ['#,##0.00 "€"', "#,##0.00 [$€]", "0.00€"], + ["[$$-409]#,##0.000", "[$$]#,##0.000", "$0.000"], + ["[$-409]0.00", "0.00", "0.00"], + ["[$MM/DD/YYYY]0", "[$MM/DD/YYYY]0", "MM/DD/YYYY0"], + ["#,##0.00[$MM/DD/YYYY]", "#,##0.00[$MM/DD/YYYY]", "0.00MM/DD/YYYY"], + ["[$₪-40D] #,##0.00", "[$₪] #,##0.00", "₪0.00"], + ['"€"#,##0.00 "€"', undefined, "0"], +])("convert format %s", async (excelFormat, convertedFormat, expectedValue) => { expect( convertXlsxFormat(80, [{ id: 80, format: excelFormat }], new XLSXImportWarningManager()) ).toEqual(convertedFormat); + expect(formatValue(0, convertedFormat)).toEqual(expectedValue); });