diff --git a/src/gen-charts.ts b/src/gen-charts.ts index 37f27396b..53a49cc23 100644 --- a/src/gen-charts.ts +++ b/src/gen-charts.ts @@ -955,6 +955,19 @@ function makeChartType (chartType: CHART_NAME, data: IOptsChartData[], opts: ICh obj.labels[0].forEach((label, idx) => (strXml += `${encodeXmlEntities(label)}`)) strXml += ' ' strXml += ' ' + } else if (obj.labels.length === 1) { + // Single-level string categories: emit the idiomatic single-level `c:strRef` + // (same form used by the pie/doughnut chart types below). A `c:multiLvlStrRef` + // with a single level is valid but non-idiomatic: PowerPoint tolerates it, but + // Google Slides / LibreOffice mis-render the category axis and strict parsers + // (e.g. pptxtojson) fail to read the labels. + strXml += ' ' + strXml += ` Sheet1!$A$2:$A$${obj.labels[0].length + 1}` + strXml += ' ' + strXml += ` ` + obj.labels[0].forEach((label, idx) => (strXml += `${encodeXmlEntities(label)}`)) + strXml += ' ' + strXml += ' ' } else { strXml += ' ' strXml += ` Sheet1!$A$2:$${getExcelColName(obj.labels.length)}$${obj.labels[0].length + 1}` diff --git a/src/gen-xml.ts b/src/gen-xml.ts index f1e3ecd9f..d3ea3390b 100644 --- a/src/gen-xml.ts +++ b/src/gen-xml.ts @@ -783,7 +783,12 @@ function slideObjectRelationsToXml (slide: PresSlide | SlideLayout, defaultRels: }) ; (slide._relsChart || []).forEach((rel: ISlideRelChart) => { lastRid = Math.max(lastRid, rel.rId) - strXml += `` + // Relationship targets are relative to the slide part, e.g. "../charts/chartN.xml" (what + // PowerPoint writes). The stored `rel.Target` is the absolute "/ppt/charts/chartN.xml" form, + // which is reused verbatim as the absolute Content_Types PartName. Absolute relationship + // targets are valid but non-idiomatic and are mishandled by stricter consumers (e.g. + // pptxtojson resolves them to an invalid path and drops the chart), so relativize here only. + strXml += `` }) ; (slide._relsMedia || []).forEach((rel: ISlideRelMedia) => { const relRid = rel.rId.toString()