Skip to content

Commit

Permalink
fix xlsx with formulas stored with ' string delimiters, like `'Raw …
Browse files Browse the repository at this point in the history
…Data'!$B$2` which were producing invalid js code when preparing handlebars calls
  • Loading branch information
bjrmatos committed Dec 21, 2023
1 parent 91daa06 commit 5b7c85e
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
27 changes: 25 additions & 2 deletions packages/jsreport-xlsx/lib/generation/preprocess/loop.js
Original file line number Diff line number Diff line change
Expand Up @@ -677,10 +677,10 @@ module.exports = (files) => {
continue
}

formulaEl.textContent = `{{xlsxSData type='formula' originalCellRef='${cellRef}' originalFormula='${formula}'`
formulaEl.textContent = `{{xlsxSData type='formula' originalCellRef='${cellRef}' originalFormula='${jsStringEscape(formula)}'`

if (sharedFormula?.type === 'source') {
formulaEl.setAttribute('ref', `{{xlsxSData type='formulaSharedRefRange' originalSharedRefRange='${sharedFormula.sourceRef}'}}`)
formulaEl.setAttribute('ref', `{{xlsxSData type='formulaSharedRefRange' originalSharedRefRange='${jsStringEscape(sharedFormula.sourceRef)}'}}`)
}

formulaEl.textContent += '}}'
Expand Down Expand Up @@ -1289,3 +1289,26 @@ function processClosingTag (doc, refElement, closeCall) {
refElement.parentNode.insertBefore(fakeElement, refElement.nextSibling)
return fakeElement
}

function jsStringEscape (string) {
return ('' + string).replace(/["'\\\n\r\u2028\u2029]/g, function (character) {
// Escape all characters not included in SingleStringCharacters and
// DoubleStringCharacters on
// http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
switch (character) {
case '"':
case "'":
case '\\':
return '\\' + character
// Four possible LineTerminator characters need to be escaped:
case '\n':
return '\\n'
case '\r':
return '\\r'
case '\u2028':
return '\\u2028'
case '\u2029':
return '\\u2029'
}
})
}
23 changes: 23 additions & 0 deletions packages/jsreport-xlsx/test/generation/baseTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -519,4 +519,27 @@ describe('xlsx generation - base', () => {
should(sheet.A4.v).be.eql(40)
should(sheet.B4.f).be.eql('A4+B!A5')
})

it('existing formulas that reference cells from other sheets with name stored with \' string delimiters should be handled', async () => {
const result = await reporter.render({
template: {
engine: 'handlebars',
recipe: 'xlsx',
xlsx: {
templateAsset: {
content: fs.readFileSync(
path.join(xlsxDirPath, 'existing-formula-cross-sheet-reference-with-name-string-delimiter.xlsx')
)
}
}
},
data: {}
})

fs.writeFileSync(outputPath, result.content)
const workbook = xlsx.read(result.content)
const sheet = workbook.Sheets[workbook.SheetNames[0]]
should(sheet.B2.f).be.eql("'Raw Data'!$B$2")
should(sheet.A9.f).be.eql('RawData!$A$15')
})
})
Binary file not shown.

0 comments on commit 5b7c85e

Please sign in to comment.