From eb6d3924a958e37311fda363f480cf4299adcb85 Mon Sep 17 00:00:00 2001 From: Anthony Hendrickx Date: Fri, 20 Mar 2026 11:57:42 +0100 Subject: [PATCH] [IMP] charts: import/export title colors This PR aims to add the ability to import and export title and axis title color from/to xlsx file Related Task: Task: 4952020 --- src/xlsx/conversion/figure_conversion.ts | 1 + src/xlsx/extraction/chart_extractor.ts | 122 ++++- src/xlsx/functions/charts.ts | 9 +- .../__snapshots__/xlsx_export.test.ts.snap | 451 ++++++------------ tests/xlsx/xlsx_export.test.ts | 72 ++- tests/xlsx/xlsx_import_export.test.ts | 40 ++ 6 files changed, 390 insertions(+), 305 deletions(-) diff --git a/src/xlsx/conversion/figure_conversion.ts b/src/xlsx/conversion/figure_conversion.ts index 53459b4e3f..9a07dc5177 100644 --- a/src/xlsx/conversion/figure_conversion.ts +++ b/src/xlsx/conversion/figure_conversion.ts @@ -123,6 +123,7 @@ function convertChartData(chartData: ExcelChartDefinition): ChartDefinition c:title a:p a:pPr a:defRPr" + ); const barChartGrouping = this.extractChildAttr(rootChartElement, "c:grouping", "val", { default: "clustered", }).asString(); @@ -48,8 +54,9 @@ export class XlsxChartExtractor extends XlsxBaseExtractor { (el) => el.attributes.getNamedItem("val")?.value === "1" ); return { - title: { text: chartTitle }, + title: { text: chartTitle, ...chartTitleStyle }, type: CHART_TYPE_CONVERSION_MAP[chartType]!, + axesDesign: this.extractAxesDesign(rootChartElement), dataSets: this.extractChartDatasets( this.querySelectorAll(rootChartElement, `c:${chartType}`)!, chartType @@ -98,6 +105,10 @@ export class XlsxChartExtractor extends XlsxBaseExtractor { return textElement.textContent || ""; } ).join(""); + const chartTitleStyle = this.extractTitleStyle( + chartElement, + "c:chart > c:title a:p a:pPr a:defRPr" + ); const barChartGrouping = this.extractChildAttr(chartElement, "c:grouping", "val", { default: "clustered", }).asString(); @@ -106,8 +117,9 @@ export class XlsxChartExtractor extends XlsxBaseExtractor { (el) => el.attributes.getNamedItem("val")?.value === "1" ); return { - title: { text: chartTitle }, + title: { text: chartTitle, ...chartTitleStyle }, type: "combo", + axesDesign: this.extractAxesDesign(chartElement), dataSets: [ ...this.extractChartDatasets( this.querySelectorAll(chartElement, `c:barChart`), @@ -139,6 +151,112 @@ export class XlsxChartExtractor extends XlsxBaseExtractor { }; } + /** + * Extracts the style properties (bold, italic, font size and color) for a chart or axis title from a `a:defRPr` element in the XML. + * defRPr stands for "default run properties" and is the element that contains the default style properties for a text run in DrawingML. + * For more information on the `a:defRPr` element and the style properties it can contain, see ยง21.1.2.3.2 defRPr (Default Text Run Properties). + * The `titleQuery` parameter is the query to select the `a:defRPr` element that contains the style properties. + * Returns an object with the extracted style properties. If a property is not defined in the XML, it will be `undefined` in the returned object. + */ + private extractTitleStyle( + element: Element, + titleQuery: string + ): Pick { + const defRPr = this.querySelector(element, titleQuery); + if (!defRPr) { + return {}; + } + const bAttr = defRPr.getAttribute("b"); + const bold = bAttr === "1" || bAttr === "true" ? true : undefined; + const iAttr = defRPr.getAttribute("i"); + const italic = iAttr === "1" || iAttr === "true" ? true : undefined; + const szAttr = defRPr.getAttribute("sz"); + const fontSize = szAttr ? Math.round(parseInt(szAttr) / 100) : undefined; + const color = this.extractDrawingFillColor(defRPr); + return { bold, italic, fontSize, color }; + } + + private extractDrawingFillColor(element: Element): string | undefined { + const srgbClr = this.querySelector(element, "a:solidFill a:srgbClr"); + if (srgbClr) { + const val = srgbClr.getAttribute("val"); + return val && isColorValid(val) ? toHex(val) : undefined; + } + const schemeClr = this.querySelector(element, "a:solidFill a:schemeClr"); + if (schemeClr) { + const schemeName = schemeClr.getAttribute("val"); + if (schemeName) { + return this.resolveSchemeColor(schemeName); + } + } + return undefined; + } + + /** + * Resolve a DrawingML scheme color name (e.g. "accent1", "dk1") to its hex + * RGB value by looking it up in the theme's `a:clrScheme` element. + * Returns `undefined` if the theme is unavailable or the color cannot be found. + */ + private resolveSchemeColor(schemeName: string): string | undefined { + const themeFile = this.xlsxFileStructure.theme; + if (!themeFile) { + return undefined; + } + const schemeEl = this.querySelector(themeFile.file.xml, `a:clrScheme a:${schemeName}`); + if (!schemeEl) { + return undefined; + } + const srgbClr = this.querySelector(schemeEl, "a:srgbClr"); + if (srgbClr) { + const val = srgbClr.getAttribute("val"); + return val && isColorValid(val) ? toHex(val) : undefined; + } + + const sysClr = this.querySelector(schemeEl, "a:sysClr"); + if (sysClr) { + const lastClr = sysClr.getAttribute("lastClr"); + return lastClr && isColorValid(lastClr) ? toHex(lastClr) : undefined; + } + return undefined; + } + + private extractAxisTitleDesign(axElement: Element | null): TitleDesign | undefined { + if (axElement === null) { + return undefined; + } + const titleText = this.mapOnElements( + { parent: axElement, query: "c:title a:t" }, + (el) => el.textContent || "" + ).join(""); + if (!titleText) { + return undefined; + } + const style = this.extractTitleStyle(axElement, "c:title a:p a:pPr a:defRPr"); + return { text: titleText, ...style }; + } + + private extractAxesDesign(chartElement: Element): AxesDesign | undefined { + const catAx = this.querySelector(chartElement, "c:catAx"); + const valAx = this.querySelector(chartElement, "c:valAx"); + const axPos = catAx ? this.extractChildAttr(catAx, "c:axPos", "val")?.asString() : undefined; + const isHorizontalChart = axPos === "l" || axPos === "r"; + const xAx = isHorizontalChart ? valAx : catAx; + const yAx = isHorizontalChart ? catAx : valAx; + const xTitle = this.extractAxisTitleDesign(xAx); + const yTitle = this.extractAxisTitleDesign(yAx); + if (!xTitle && !yTitle) { + return undefined; + } + const axesDesign: AxesDesign = {}; + if (xTitle) { + axesDesign.x = { title: xTitle }; + } + if (yTitle) { + axesDesign.y = { title: yTitle }; + } + return axesDesign; + } + private extractChartDatasets( chartElements: NodeListOf, chartType: XLSXChartType diff --git a/src/xlsx/functions/charts.ts b/src/xlsx/functions/charts.ts index 730ecb4d31..063fe88aed 100644 --- a/src/xlsx/functions/charts.ts +++ b/src/xlsx/functions/charts.ts @@ -64,7 +64,9 @@ export function createChart( // to manually position the chart in the figure container let title = escapeXml``; if (chart.data.title?.text) { - const titleColor = toXlsxHexColor(chartMutedFontColor(chart.data.backgroundColor)); + const titleColor = chart.data.title.color + ? toXlsxHexColor(chart.data.title.color) + : toXlsxHexColor(chartMutedFontColor(chart.data.backgroundColor)); const fontSize = chart.data.title.fontSize ?? CHART_TITLE_FONT_SIZE; title = escapeXml/*xml*/ ` @@ -179,13 +181,14 @@ function insertText( - + ${solidFill(fontColor)} - ${text} diff --git a/tests/xlsx/__snapshots__/xlsx_export.test.ts.snap b/tests/xlsx/__snapshots__/xlsx_export.test.ts.snap index ff12f22c8e..893898967c 100644 --- a/tests/xlsx/__snapshots__/xlsx_export.test.ts.snap +++ b/tests/xlsx/__snapshots__/xlsx_export.test.ts.snap @@ -34,7 +34,7 @@ exports[`Test XLSX export Charts Chart legend is set to none position 1`] = ` - + @@ -43,7 +43,6 @@ exports[`Test XLSX export Charts Chart legend is set to none position 1`] = ` - test @@ -202,7 +201,7 @@ exports[`Test XLSX export Charts Chart legend is set to none position 1`] = ` - + @@ -211,7 +210,6 @@ exports[`Test XLSX export Charts Chart legend is set to none position 1`] = ` - @@ -267,7 +265,7 @@ exports[`Test XLSX export Charts Chart legend is set to none position 1`] = ` - + @@ -276,7 +274,6 @@ exports[`Test XLSX export Charts Chart legend is set to none position 1`] = ` - @@ -677,7 +674,7 @@ exports[`Test XLSX export Charts Export chart overflowing outside the sheet 1`] - + @@ -686,7 +683,6 @@ exports[`Test XLSX export Charts Export chart overflowing outside the sheet 1`] - test @@ -831,7 +827,7 @@ exports[`Test XLSX export Charts Export chart overflowing outside the sheet 1`] - + @@ -840,7 +836,6 @@ exports[`Test XLSX export Charts Export chart overflowing outside the sheet 1`] - @@ -896,7 +891,7 @@ exports[`Test XLSX export Charts Export chart overflowing outside the sheet 1`] - + @@ -905,7 +900,6 @@ exports[`Test XLSX export Charts Export chart overflowing outside the sheet 1`] - @@ -1324,7 +1318,7 @@ exports[`Test XLSX export Charts chart dataset without title 1`] = ` - + @@ -1333,7 +1327,6 @@ exports[`Test XLSX export Charts chart dataset without title 1`] = ` - test @@ -1478,7 +1471,7 @@ exports[`Test XLSX export Charts chart dataset without title 1`] = ` - + @@ -1487,7 +1480,6 @@ exports[`Test XLSX export Charts chart dataset without title 1`] = ` - @@ -1543,7 +1535,7 @@ exports[`Test XLSX export Charts chart dataset without title 1`] = ` - + @@ -1552,7 +1544,6 @@ exports[`Test XLSX export Charts chart dataset without title 1`] = ` - @@ -1972,7 +1963,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -1981,7 +1972,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - test @@ -2140,7 +2130,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -2149,7 +2139,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - @@ -2205,7 +2194,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -2214,7 +2203,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - @@ -2288,7 +2276,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -2297,7 +2285,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - test @@ -2497,7 +2484,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -2506,7 +2493,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - test @@ -2688,7 +2674,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -2697,7 +2683,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - @@ -2753,7 +2738,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -2762,7 +2747,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - @@ -2836,7 +2820,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -2845,7 +2829,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - test @@ -2923,7 +2906,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -2932,7 +2915,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - test @@ -3115,7 +3097,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -3124,7 +3106,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - @@ -3180,7 +3161,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -3189,7 +3170,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - @@ -3263,7 +3243,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -3272,7 +3252,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - test @@ -3453,7 +3432,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -3462,7 +3441,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - @@ -3518,7 +3496,7 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - + @@ -3527,7 +3505,6 @@ exports[`Test XLSX export Charts chart font color is white with a dark backgroun - @@ -4230,7 +4207,7 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - + @@ -4239,7 +4216,6 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - test @@ -4421,7 +4397,7 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - + @@ -4430,7 +4406,6 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - @@ -4486,7 +4461,7 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - + @@ -4495,7 +4470,6 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - @@ -4742,7 +4716,7 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - + @@ -4751,7 +4725,6 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - test @@ -4910,7 +4883,7 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - + @@ -4919,7 +4892,6 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - @@ -4975,7 +4947,7 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - + @@ -4984,7 +4956,6 @@ exports[`Test XLSX export Charts charts in different sheets 1`] = ` - @@ -5342,7 +5313,7 @@ exports[`Test XLSX export Charts doughnut chart 1`] = ` - + @@ -5351,7 +5322,6 @@ exports[`Test XLSX export Charts doughnut chart 1`] = ` - test @@ -5922,7 +5892,7 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - + @@ -5931,7 +5901,6 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - test @@ -6090,7 +6059,7 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - + @@ -6099,7 +6068,6 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - @@ -6155,7 +6123,7 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - + @@ -6164,7 +6132,6 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - @@ -6238,7 +6205,7 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - + @@ -6247,7 +6214,6 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - test @@ -6406,7 +6372,7 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - + @@ -6415,7 +6381,6 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - @@ -6471,7 +6436,7 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - + @@ -6480,7 +6445,6 @@ exports[`Test XLSX export Charts exported results will not be influenced by \`da - @@ -6947,7 +6911,7 @@ exports[`Test XLSX export Charts horizontal bar chart 1`] = ` - + @@ -6956,7 +6920,6 @@ exports[`Test XLSX export Charts horizontal bar chart 1`] = ` - test @@ -7115,7 +7078,7 @@ exports[`Test XLSX export Charts horizontal bar chart 1`] = ` - + @@ -7124,7 +7087,6 @@ exports[`Test XLSX export Charts horizontal bar chart 1`] = ` - @@ -7180,7 +7142,7 @@ exports[`Test XLSX export Charts horizontal bar chart 1`] = ` - + @@ -7189,7 +7151,6 @@ exports[`Test XLSX export Charts horizontal bar chart 1`] = ` - @@ -7608,7 +7569,7 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - + @@ -7617,7 +7578,6 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - test @@ -7799,7 +7759,7 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - + @@ -7808,7 +7768,6 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - @@ -7864,7 +7823,7 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - + @@ -7873,7 +7832,6 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - @@ -7947,7 +7905,7 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - + @@ -7956,7 +7914,6 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - test @@ -8115,7 +8072,7 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - + @@ -8124,7 +8081,6 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - @@ -8180,7 +8136,7 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - + @@ -8189,7 +8145,6 @@ exports[`Test XLSX export Charts multiple charts in the same sheet 1`] = ` - @@ -8656,7 +8611,7 @@ exports[`Test XLSX export Charts pie chart with only title dataset 1`] = ` - + @@ -8665,7 +8620,6 @@ exports[`Test XLSX export Charts pie chart with only title dataset 1`] = ` - test @@ -8979,7 +8933,7 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - + @@ -8988,7 +8942,6 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - test @@ -9162,7 +9115,7 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - + @@ -9171,7 +9124,6 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - @@ -9230,7 +9182,7 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - + @@ -9239,7 +9191,6 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - @@ -9295,7 +9246,7 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - + @@ -9304,7 +9255,6 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - @@ -9359,7 +9309,7 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - + @@ -9368,7 +9318,6 @@ exports[`Test XLSX export Charts pyramid chart 1`] = ` - @@ -9787,7 +9736,7 @@ exports[`Test XLSX export Charts simple bar chart with customized axis 1`] = ` - + @@ -9796,7 +9745,6 @@ exports[`Test XLSX export Charts simple bar chart with customized axis 1`] = ` - test @@ -9899,7 +9847,7 @@ exports[`Test XLSX export Charts simple bar chart with customized axis 1`] = ` - + @@ -9908,7 +9856,6 @@ exports[`Test XLSX export Charts simple bar chart with customized axis 1`] = ` - Coucou @@ -9966,7 +9913,7 @@ exports[`Test XLSX export Charts simple bar chart with customized axis 1`] = ` - + @@ -9975,7 +9922,6 @@ exports[`Test XLSX export Charts simple bar chart with customized axis 1`] = ` - Coucou 3 @@ -10396,7 +10342,7 @@ exports[`Test XLSX export Charts simple bar chart with customized dataset 1`] = - + @@ -10405,7 +10351,6 @@ exports[`Test XLSX export Charts simple bar chart with customized dataset 1`] = - test @@ -10515,7 +10460,7 @@ exports[`Test XLSX export Charts simple bar chart with customized dataset 1`] = - + @@ -10524,7 +10469,6 @@ exports[`Test XLSX export Charts simple bar chart with customized dataset 1`] = - @@ -10580,7 +10524,7 @@ exports[`Test XLSX export Charts simple bar chart with customized dataset 1`] = - + @@ -10589,7 +10533,6 @@ exports[`Test XLSX export Charts simple bar chart with customized dataset 1`] = - @@ -11008,16 +10951,15 @@ exports[`Test XLSX export Charts simple bar chart with customized title 1`] = ` - + - + - Coucou @@ -11129,7 +11071,7 @@ exports[`Test XLSX export Charts simple bar chart with customized title 1`] = ` - + @@ -11138,7 +11080,6 @@ exports[`Test XLSX export Charts simple bar chart with customized title 1`] = ` - @@ -11194,7 +11135,7 @@ exports[`Test XLSX export Charts simple bar chart with customized title 1`] = ` - + @@ -11203,7 +11144,6 @@ exports[`Test XLSX export Charts simple bar chart with customized title 1`] = ` - @@ -11622,7 +11562,7 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object] ] 1`] - + @@ -11631,7 +11571,6 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object] ] 1`] - test @@ -11743,7 +11682,7 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object] ] 1`] - + @@ -11752,7 +11691,6 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object] ] 1`] - @@ -11808,7 +11746,7 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object] ] 1`] - + @@ -11817,7 +11755,6 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object] ] 1`] - @@ -12236,7 +12173,7 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object], [Obje - + @@ -12245,7 +12182,6 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object], [Obje - test @@ -12404,7 +12340,7 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object], [Obje - + @@ -12413,7 +12349,6 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object], [Obje - @@ -12469,7 +12404,7 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object], [Obje - + @@ -12478,7 +12413,6 @@ exports[`Test XLSX export Charts simple bar chart with dataset [ [Object], [Obje - @@ -12897,7 +12831,7 @@ exports[`Test XLSX export Charts simple combo chart with customized axis 1`] = ` - + @@ -12906,7 +12840,6 @@ exports[`Test XLSX export Charts simple combo chart with customized axis 1`] = ` - test @@ -13017,7 +12950,7 @@ exports[`Test XLSX export Charts simple combo chart with customized axis 1`] = ` - + @@ -13026,7 +12959,6 @@ exports[`Test XLSX export Charts simple combo chart with customized axis 1`] = ` - Coucou @@ -13084,7 +13016,7 @@ exports[`Test XLSX export Charts simple combo chart with customized axis 1`] = ` - + @@ -13093,7 +13025,6 @@ exports[`Test XLSX export Charts simple combo chart with customized axis 1`] = ` - Coucou 3 @@ -13514,7 +13445,7 @@ exports[`Test XLSX export Charts simple combo chart with customized dataset 1`] - + @@ -13523,7 +13454,6 @@ exports[`Test XLSX export Charts simple combo chart with customized dataset 1`] - test @@ -13632,7 +13562,7 @@ exports[`Test XLSX export Charts simple combo chart with customized dataset 1`] - + @@ -13641,7 +13571,6 @@ exports[`Test XLSX export Charts simple combo chart with customized dataset 1`] - @@ -13697,7 +13626,7 @@ exports[`Test XLSX export Charts simple combo chart with customized dataset 1`] - + @@ -13706,7 +13635,6 @@ exports[`Test XLSX export Charts simple combo chart with customized dataset 1`] - @@ -14125,16 +14053,15 @@ exports[`Test XLSX export Charts simple combo chart with customized title 1`] = - + - + - Coucou @@ -14245,7 +14172,7 @@ exports[`Test XLSX export Charts simple combo chart with customized title 1`] = - + @@ -14254,7 +14181,6 @@ exports[`Test XLSX export Charts simple combo chart with customized title 1`] = - @@ -14310,7 +14236,7 @@ exports[`Test XLSX export Charts simple combo chart with customized title 1`] = - + @@ -14319,7 +14245,6 @@ exports[`Test XLSX export Charts simple combo chart with customized title 1`] = - @@ -14738,7 +14663,7 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object] ] 1` - + @@ -14747,7 +14672,6 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object] ] 1` - test @@ -14858,7 +14782,7 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object] ] 1` - + @@ -14867,7 +14791,6 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object] ] 1` - @@ -14923,7 +14846,7 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object] ] 1` - + @@ -14932,7 +14855,6 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object] ] 1` - @@ -15351,7 +15273,7 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object], [Ob - + @@ -15360,7 +15282,6 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object], [Ob - test @@ -15548,7 +15469,7 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object], [Ob - + @@ -15557,7 +15478,6 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object], [Ob - @@ -15613,7 +15533,7 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object], [Ob - + @@ -15622,7 +15542,6 @@ exports[`Test XLSX export Charts simple combo chart with dataset [ [Object], [Ob - @@ -16041,7 +15960,7 @@ exports[`Test XLSX export Charts simple line chart with customized axis 1`] = ` - + @@ -16050,7 +15969,6 @@ exports[`Test XLSX export Charts simple line chart with customized axis 1`] = ` - test @@ -16172,7 +16090,7 @@ exports[`Test XLSX export Charts simple line chart with customized axis 1`] = ` - + @@ -16181,7 +16099,6 @@ exports[`Test XLSX export Charts simple line chart with customized axis 1`] = ` - Coucou @@ -16239,7 +16156,7 @@ exports[`Test XLSX export Charts simple line chart with customized axis 1`] = ` - + @@ -16248,7 +16165,6 @@ exports[`Test XLSX export Charts simple line chart with customized axis 1`] = ` - Coucou 3 @@ -16669,7 +16585,7 @@ exports[`Test XLSX export Charts simple line chart with customized dataset 1`] = - + @@ -16678,7 +16594,6 @@ exports[`Test XLSX export Charts simple line chart with customized dataset 1`] = - test @@ -16798,7 +16713,7 @@ exports[`Test XLSX export Charts simple line chart with customized dataset 1`] = - + @@ -16807,7 +16722,6 @@ exports[`Test XLSX export Charts simple line chart with customized dataset 1`] = - @@ -16863,7 +16777,7 @@ exports[`Test XLSX export Charts simple line chart with customized dataset 1`] = - + @@ -16872,7 +16786,6 @@ exports[`Test XLSX export Charts simple line chart with customized dataset 1`] = - @@ -17291,16 +17204,15 @@ exports[`Test XLSX export Charts simple line chart with customized title 1`] = ` - + - + - Coucou @@ -17422,7 +17334,7 @@ exports[`Test XLSX export Charts simple line chart with customized title 1`] = ` - + @@ -17431,7 +17343,6 @@ exports[`Test XLSX export Charts simple line chart with customized title 1`] = ` - @@ -17487,7 +17398,7 @@ exports[`Test XLSX export Charts simple line chart with customized title 1`] = ` - + @@ -17496,7 +17407,6 @@ exports[`Test XLSX export Charts simple line chart with customized title 1`] = ` - @@ -17915,7 +17825,7 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object] ] 1`] - + @@ -17924,7 +17834,6 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object] ] 1`] - test @@ -18046,7 +17955,7 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object] ] 1`] - + @@ -18055,7 +17964,6 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object] ] 1`] - @@ -18111,7 +18019,7 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object] ] 1`] - + @@ -18120,7 +18028,6 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object] ] 1`] - @@ -18539,7 +18446,7 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object], [Obj - + @@ -18548,7 +18455,6 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object], [Obj - test @@ -18730,7 +18636,7 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object], [Obj - + @@ -18739,7 +18645,6 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object], [Obj - @@ -18795,7 +18700,7 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object], [Obj - + @@ -18804,7 +18709,6 @@ exports[`Test XLSX export Charts simple line chart with dataset [ [Object], [Obj - @@ -19223,7 +19127,7 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ [Object] ] 1`] - + @@ -19232,7 +19136,6 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ [Object] ] 1`] - test @@ -19729,7 +19632,7 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ [Object], [Obje - + @@ -19738,7 +19641,6 @@ exports[`Test XLSX export Charts simple pie chart with dataset [ [Object], [Obje - test @@ -20309,7 +20211,7 @@ exports[`Test XLSX export Charts simple radar chart with customized axis 1`] = ` - + @@ -20318,7 +20220,6 @@ exports[`Test XLSX export Charts simple radar chart with customized axis 1`] = ` - test @@ -20439,7 +20340,7 @@ exports[`Test XLSX export Charts simple radar chart with customized axis 1`] = ` - + @@ -20448,7 +20349,6 @@ exports[`Test XLSX export Charts simple radar chart with customized axis 1`] = ` - @@ -20504,7 +20404,7 @@ exports[`Test XLSX export Charts simple radar chart with customized axis 1`] = ` - + @@ -20513,7 +20413,6 @@ exports[`Test XLSX export Charts simple radar chart with customized axis 1`] = ` - @@ -20932,7 +20831,7 @@ exports[`Test XLSX export Charts simple radar chart with customized dataset 1`] - + @@ -20941,7 +20840,6 @@ exports[`Test XLSX export Charts simple radar chart with customized dataset 1`] - test @@ -21060,7 +20958,7 @@ exports[`Test XLSX export Charts simple radar chart with customized dataset 1`] - + @@ -21069,7 +20967,6 @@ exports[`Test XLSX export Charts simple radar chart with customized dataset 1`] - @@ -21125,7 +21022,7 @@ exports[`Test XLSX export Charts simple radar chart with customized dataset 1`] - + @@ -21134,7 +21031,6 @@ exports[`Test XLSX export Charts simple radar chart with customized dataset 1`] - @@ -21553,16 +21449,15 @@ exports[`Test XLSX export Charts simple radar chart with customized title 1`] = - + - + - Coucou @@ -21683,7 +21578,7 @@ exports[`Test XLSX export Charts simple radar chart with customized title 1`] = - + @@ -21692,7 +21587,6 @@ exports[`Test XLSX export Charts simple radar chart with customized title 1`] = - @@ -21748,7 +21642,7 @@ exports[`Test XLSX export Charts simple radar chart with customized title 1`] = - + @@ -21757,7 +21651,6 @@ exports[`Test XLSX export Charts simple radar chart with customized title 1`] = - @@ -22176,7 +22069,7 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object] ] 1` - + @@ -22185,7 +22078,6 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object] ] 1` - test @@ -22306,7 +22198,7 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object] ] 1` - + @@ -22315,7 +22207,6 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object] ] 1` - @@ -22371,7 +22262,7 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object] ] 1` - + @@ -22380,7 +22271,6 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object] ] 1` - @@ -22799,7 +22689,7 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object], [Ob - + @@ -22808,7 +22698,6 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object], [Ob - test @@ -22989,7 +22878,7 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object], [Ob - + @@ -22998,7 +22887,6 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object], [Ob - @@ -23054,7 +22942,7 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object], [Ob - + @@ -23063,7 +22951,6 @@ exports[`Test XLSX export Charts simple radar chart with dataset [ [Object], [Ob - @@ -23482,7 +23369,7 @@ exports[`Test XLSX export Charts simple scatter chart with customized axis 1`] = - + @@ -23491,7 +23378,6 @@ exports[`Test XLSX export Charts simple scatter chart with customized axis 1`] = - test @@ -23614,7 +23500,7 @@ exports[`Test XLSX export Charts simple scatter chart with customized axis 1`] = - + @@ -23623,7 +23509,6 @@ exports[`Test XLSX export Charts simple scatter chart with customized axis 1`] = - Coucou @@ -23681,7 +23566,7 @@ exports[`Test XLSX export Charts simple scatter chart with customized axis 1`] = - + @@ -23690,7 +23575,6 @@ exports[`Test XLSX export Charts simple scatter chart with customized axis 1`] = - Coucou 3 @@ -24111,7 +23995,7 @@ exports[`Test XLSX export Charts simple scatter chart with customized dataset 1` - + @@ -24120,7 +24004,6 @@ exports[`Test XLSX export Charts simple scatter chart with customized dataset 1` - test @@ -24241,7 +24124,7 @@ exports[`Test XLSX export Charts simple scatter chart with customized dataset 1` - + @@ -24250,7 +24133,6 @@ exports[`Test XLSX export Charts simple scatter chart with customized dataset 1` - @@ -24306,7 +24188,7 @@ exports[`Test XLSX export Charts simple scatter chart with customized dataset 1` - + @@ -24315,7 +24197,6 @@ exports[`Test XLSX export Charts simple scatter chart with customized dataset 1` - @@ -24734,16 +24615,15 @@ exports[`Test XLSX export Charts simple scatter chart with customized title 1`] - + - + - Coucou @@ -24866,7 +24746,7 @@ exports[`Test XLSX export Charts simple scatter chart with customized title 1`] - + @@ -24875,7 +24755,6 @@ exports[`Test XLSX export Charts simple scatter chart with customized title 1`] - @@ -24931,7 +24810,7 @@ exports[`Test XLSX export Charts simple scatter chart with customized title 1`] - + @@ -24940,7 +24819,6 @@ exports[`Test XLSX export Charts simple scatter chart with customized title 1`] - @@ -25359,7 +25237,7 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object] ] - + @@ -25368,7 +25246,6 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object] ] - test @@ -25491,7 +25368,7 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object] ] - + @@ -25500,7 +25377,6 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object] ] - @@ -25556,7 +25432,7 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object] ] - + @@ -25565,7 +25441,6 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object] ] - @@ -25984,7 +25859,7 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object], [ - + @@ -25993,7 +25868,6 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object], [ - test @@ -26176,7 +26050,7 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object], [ - + @@ -26185,7 +26059,6 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object], [ - @@ -26241,7 +26114,7 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object], [ - + @@ -26250,7 +26123,6 @@ exports[`Test XLSX export Charts simple scatter chart with dataset [ [Object], [ - @@ -26669,7 +26541,7 @@ exports[`Test XLSX export Charts stacked bar chart 1`] = ` - + @@ -26678,7 +26550,6 @@ exports[`Test XLSX export Charts stacked bar chart 1`] = ` - test @@ -26837,7 +26708,7 @@ exports[`Test XLSX export Charts stacked bar chart 1`] = ` - + @@ -26846,7 +26717,6 @@ exports[`Test XLSX export Charts stacked bar chart 1`] = ` - @@ -26902,7 +26772,7 @@ exports[`Test XLSX export Charts stacked bar chart 1`] = ` - + @@ -26911,7 +26781,6 @@ exports[`Test XLSX export Charts stacked bar chart 1`] = ` - @@ -39141,7 +39010,7 @@ exports[`Test XLSX export multiple elements are exported in the correct order 1` - + @@ -39150,7 +39019,6 @@ exports[`Test XLSX export multiple elements are exported in the correct order 1` - test @@ -39295,7 +39163,7 @@ exports[`Test XLSX export multiple elements are exported in the correct order 1` - + @@ -39304,7 +39172,6 @@ exports[`Test XLSX export multiple elements are exported in the correct order 1` - @@ -39360,7 +39227,7 @@ exports[`Test XLSX export multiple elements are exported in the correct order 1` - + @@ -39369,7 +39236,6 @@ exports[`Test XLSX export multiple elements are exported in the correct order 1` - @@ -39716,7 +39582,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -39725,7 +39591,6 @@ exports[`Test XLSX export references with headers should be converted to referen - test @@ -39936,7 +39801,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -39945,7 +39810,6 @@ exports[`Test XLSX export references with headers should be converted to referen - @@ -40001,7 +39865,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -40010,7 +39874,6 @@ exports[`Test XLSX export references with headers should be converted to referen - @@ -40084,7 +39947,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -40093,7 +39956,6 @@ exports[`Test XLSX export references with headers should be converted to referen - test @@ -40280,7 +40142,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -40289,7 +40151,6 @@ exports[`Test XLSX export references with headers should be converted to referen - @@ -40345,7 +40206,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -40354,7 +40215,6 @@ exports[`Test XLSX export references with headers should be converted to referen - @@ -40428,7 +40288,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -40437,7 +40297,6 @@ exports[`Test XLSX export references with headers should be converted to referen - test @@ -42158,7 +42017,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -42167,7 +42026,6 @@ exports[`Test XLSX export references with headers should be converted to referen - test @@ -42380,7 +42238,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -42389,7 +42247,6 @@ exports[`Test XLSX export references with headers should be converted to referen - @@ -42445,7 +42302,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -42454,7 +42311,6 @@ exports[`Test XLSX export references with headers should be converted to referen - @@ -42528,7 +42384,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -42537,7 +42393,6 @@ exports[`Test XLSX export references with headers should be converted to referen - test @@ -42718,7 +42573,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -42727,7 +42582,6 @@ exports[`Test XLSX export references with headers should be converted to referen - @@ -42783,7 +42637,7 @@ exports[`Test XLSX export references with headers should be converted to referen - + @@ -42792,7 +42646,6 @@ exports[`Test XLSX export references with headers should be converted to referen - diff --git a/tests/xlsx/xlsx_export.test.ts b/tests/xlsx/xlsx_export.test.ts index 143c51f549..3e51a715cf 100644 --- a/tests/xlsx/xlsx_export.test.ts +++ b/tests/xlsx/xlsx_export.test.ts @@ -8,7 +8,12 @@ import { Model } from "../../src/model"; import { XLSXExportXMLFile, XMLString } from "../../src/types/xlsx"; import { hexaToInt } from "../../src/xlsx/conversion/color_conversion"; import { adaptFormulaToExcel } from "../../src/xlsx/functions/cells"; -import { escapeXml, parseXML } from "../../src/xlsx/helpers/xml_helpers"; +import { + escapeQueryNameSpaces, + escapeTagNamespaces, + escapeXml, + parseXML, +} from "../../src/xlsx/helpers/xml_helpers"; import { arg } from "../../src/functions/arguments"; import { functionRegistry } from "../../src/functions/function_registry"; @@ -1717,6 +1722,71 @@ describe("Test XLSX export", () => { expect(await exportPrettifiedXlsx(model)).toMatchSnapshot(); }); + test("chart title color is exported", async () => { + const model = new Model(chartData); + createChart( + model, + { + ...toChartDataSource({ + dataSets: [{ dataRange: "Sheet1!B1:B4" }], + labelRange: "Sheet1!A2:A4", + }), + title: { + text: "My title", + color: "#ff0000", + }, + type: "bar", + }, + "1" + ); + const exportedXlsx = await exportPrettifiedXlsx(model); + + const chartFile = exportedXlsx.files.find((f) => f["contentType"] === "chart")!; + const xml = parseXML(new XMLString(escapeTagNamespaces(chartFile["content"].toString()))); + const srgbClr = xml.querySelector( + escapeQueryNameSpaces("c:chart > c:title a:solidFill a:srgbClr") + ); + expect(srgbClr?.getAttribute("val")).toBe("FF0000"); + }); + + test("chart axis title style is exported", async () => { + const model = new Model(chartData); + createChart( + model, + { + ...toChartDataSource({ + dataSets: [{ dataRange: "Sheet1!B1:B4" }], + labelRange: "Sheet1!A2:A4", + }), + axesDesign: { + x: { title: { text: "X axis", color: "#ff0000", bold: true, fontSize: 16 } }, + y: { title: { text: "Y axis", color: "#00ff00", italic: true } }, + }, + type: "bar", + }, + "1" + ); + const exportedXlsx = await exportPrettifiedXlsx(model); + const chartFile = exportedXlsx.files.find((f) => f["contentType"] === "chart")!; + const xml = parseXML(new XMLString(escapeTagNamespaces(chartFile["content"].toString()))); + + const catAxDefRPr = xml.querySelector(escapeQueryNameSpaces("c:catAx c:title a:defRPr")); + expect(catAxDefRPr?.getAttribute("b")).toBe("1"); + const catAxRPr = xml.querySelector(escapeQueryNameSpaces("c:catAx c:title a:defRPr")); + expect(catAxRPr?.getAttribute("sz")).toBe("1600"); + const catAxSrgbClr = catAxDefRPr?.querySelector( + escapeQueryNameSpaces("a:solidFill a:srgbClr") + ); + expect(catAxSrgbClr?.getAttribute("val")).toBe("FF0000"); + + const valAxDefRPr = xml.querySelector(escapeQueryNameSpaces("c:valAx c:title a:defRPr")); + expect(valAxDefRPr?.getAttribute("i")).toBe("1"); + const valAxSrgbClr = valAxDefRPr?.querySelector( + escapeQueryNameSpaces("a:solidFill a:srgbClr") + ); + expect(valAxSrgbClr?.getAttribute("val")).toBe("00FF00"); + }); + test("Export chart overflowing outside the sheet", async () => { const model = new Model(chartData); createChart( diff --git a/tests/xlsx/xlsx_import_export.test.ts b/tests/xlsx/xlsx_import_export.test.ts index 47fc432df8..9b9a8c25be 100644 --- a/tests/xlsx/xlsx_import_export.test.ts +++ b/tests/xlsx/xlsx_import_export.test.ts @@ -10,6 +10,7 @@ import { import { LINK_COLOR } from "../../src/constants"; import { buildSheetLink } from "../../src/helpers/misc"; import { toZone } from "../../src/helpers/zones"; +import { BarChartDefinition } from "../../src/types/chart/bar_chart"; import { isXLSXExportXMLFile } from "../../src/xlsx/helpers/xlsx_helper"; import { toChartDataSource } from "../test_helpers/chart_helpers"; import { @@ -450,6 +451,45 @@ describe("Export data to xlsx then import it", () => { expect(newChart).toMatchObject(chartDef); }); + test("Chart title style is preserved after export/import", async () => { + const title = { text: "My Chart", color: "#FF0000", fontSize: 18, bold: true, italic: true }; + createChart( + model, + { + ...toChartDataSource({ dataSets: [{ dataRange: "Sheet1!B1:B4" }] }), + type: "bar", + title, + }, + "1" + ); + const importedModel = await exportToXlsxThenImport(model); + const newChartId = importedModel.getters.getChartIds(sheetId)[0]; + const definition = importedModel.getters.getChartDefinition(newChartId); + expect(definition.title).toEqual(title); + }); + + test("Chart axis title color is preserved after export/import", async () => { + createChart( + model, + { + ...toChartDataSource({ dataSets: [{ dataRange: "Sheet1!B1:B4" }] }), + type: "bar", + axesDesign: { + x: { title: { text: "X axis", color: "#ff0000" } }, + y: { title: { text: "Y axis", color: "#00ff00" } }, + }, + }, + "1" + ); + const importedModel = await exportToXlsxThenImport(model); + const newChartId = importedModel.getters.getChartIds(sheetId)[0]; + const definition = importedModel.getters.getChartDefinition( + newChartId + ) as BarChartDefinition; + expect(definition.axesDesign?.x?.title?.color?.toUpperCase()).toBe("#FF0000"); + expect(definition.axesDesign?.y?.title?.color?.toUpperCase()).toBe("#00FF00"); + }); + test("hyperlinks", async () => { createSheet(model, { sheetId: "42", name: "she!et2" }); const sheetLink = buildSheetLink("42");