Properly support currency fields
Some checks failed
Build and Deploy / build (push) Failing after 5m8s
Build and Deploy / deploy (push) Has been skipped

This commit is contained in:
Skylar Ittner 2026-02-05 03:32:14 -07:00
parent 3d98e41d2b
commit e6e09a0361

View File

@ -31,7 +31,7 @@ const manifestXml = `<?xml version="1.0" encoding="UTF-8"?>
* @param {Map<SheetName, SheetRawContent>} sheetsData
* @returns {Promise<ArrayBuffer>}
*/
export async function createOdsFile(sheetsData) {
export async function createOdsFile(sheetsData, currencyData = null) {
// Create a new zip writer
const zipWriter = new ZipWriter(new BlobWriter('application/vnd.oasis.opendocument.spreadsheet'));
@ -49,7 +49,7 @@ export async function createOdsFile(sheetsData) {
}
);
const contentXml = generateContentFileXMLString(sheetsData);
const contentXml = generateContentFileXMLString(sheetsData, currencyData);
zipWriter.add("content.xml", new TextReader(contentXml), {level: 9});
zipWriter.add("styles.xml", new TextReader(stylesXml));
@ -67,7 +67,7 @@ export async function createOdsFile(sheetsData) {
* @param {Map<SheetName, SheetRawContent>} sheetsData
* @returns {string}
*/
function generateContentFileXMLString(sheetsData) {
function generateContentFileXMLString(sheetsData, currencyData) {
const doc = createDocument('urn:oasis:names:tc:opendocument:xmlns:office:1.0', 'office:document-content');
const root = doc.documentElement;
@ -80,6 +80,40 @@ function generateContentFileXMLString(sheetsData) {
root.setAttribute('office:version', '1.2');
const styleNode = doc.createElement("office:automatic-styles");
var currencyStyleName = "currencyStyle";
if (currencyData != null) {
currencyStyleName = `currency${currencyData.currencyCode.toUpperCase()}`;
const numberStyle = doc.createElement("number:currency-style");
numberStyle.setAttribute("style:name", currencyStyleName);
const numberCurrencySymbolStyle = doc.createElement("number:currency-symbol");
numberCurrencySymbolStyle.setAttribute("number:language", "en");
numberCurrencySymbolStyle.setAttribute("number:country", currencyData.countryCode.toUpperCase());
numberCurrencySymbolStyle.textContent = currencyData.currencySymbol;
numberStyle.appendChild(numberCurrencySymbolStyle);
const numberCurrencyStyle = doc.createElement("number:number");
numberCurrencyStyle.setAttribute("number:min-integer-digits", "1");
numberCurrencyStyle.setAttribute("number:decimal-places", `${currencyData.decimalPlaces}`);
numberCurrencyStyle.setAttribute("number:min-decimal-places", `${currencyData.decimalPlaces}`);
numberCurrencyStyle.setAttribute("number:grouping", "true");
numberStyle.appendChild(numberCurrencyStyle);
styleNode.appendChild(numberStyle);
const currencyCellStyleNode = doc.createElement("style:style");
currencyCellStyleNode.setAttribute("style:name", "currencycell");
currencyCellStyleNode.setAttribute("style:family", "table-cell");
currencyCellStyleNode.setAttribute("style:data-style-name", currencyStyleName);
const currencyCellTableCellProperties = doc.createElement("style:table-cell-properties");
currencyCellStyleNode.appendChild(currencyCellTableCellProperties);
styleNode.appendChild(currencyCellStyleNode);
}
const boldCellStyleNode = doc.createElement("style:style");
boldCellStyleNode.setAttribute("style:name", "boldcell");
boldCellStyleNode.setAttribute("style:family", "table-cell");
@ -88,6 +122,7 @@ function generateContentFileXMLString(sheetsData) {
boldCellStyleNode.appendChild(boldCellTextPropsNode);
styleNode.appendChild(boldCellStyleNode);
root.appendChild(styleNode);
const bodyNode = doc.createElement('office:body');
@ -105,10 +140,11 @@ function generateContentFileXMLString(sheetsData) {
var columnsWidthChars = {};
for (let r = 0; r < sheetData.length; r++) {
for (let c = 0; c < sheetData[r].length; c++) {
var len = ((sheetData[r][c].display ?? sheetData[r][c].value) + "").length;
if (typeof columnsWidthChars[c] == "undefined") {
columnsWidthChars[c] = sheetData[r][c].value.length;
columnsWidthChars[c] = len;
}
columnsWidthChars[c] = Math.max(columnsWidthChars[c], sheetData[r][c].value.length);
columnsWidthChars[c] = Math.max(columnsWidthChars[c], len);
}
}
@ -151,6 +187,14 @@ function generateContentFileXMLString(sheetsData) {
cellNode.setAttribute('office:value', cell.value.toString());
cellNode.setAttribute('office:value-type', 'percentage');
break;
case 'currency':
cellNode.setAttribute('office:value', cell.value.toString());
cellNode.setAttribute('office:value-type', 'currency');
if (currencyData != null) {
cellNode.setAttribute("table:style-name", "currencycell");
cellNode.setAttribute('office:currency', currencyData.currencyCode.toUpperCase());
}
break;
case 'date':
cellNode.setAttribute('office:date-value', cell.value.toString());
break;
@ -166,7 +210,11 @@ function generateContentFileXMLString(sheetsData) {
if (cellType !== 'string') {
const textNode = doc.createElement('text:p');
if (typeof cell.display != "undefined") {
textNode.textContent = cell.display.toString();
} else {
textNode.textContent = cell.value.toString();
}
cellNode.appendChild(textNode);
}
}