UNPKG

@protobi/exceljs

Version:

Excel Workbook Manager - Temporary fork with pivot table enhancements and bug fixes pending upstream merge

119 lines (98 loc) 3.5 kB
const XmlStream = require('../../../utils/xml-stream'); const BaseXform = require('../base-xform'); class PivotCacheRecordsXform extends BaseXform { constructor() { super(); this.map = {}; } prepare(model) { // TK } get tag() { // http://www.datypic.com/sc/ooxml/e-ssml_pivotCacheRecords.html return 'pivotCacheRecords'; } render(xmlStream, model) { const {sourceSheet, cacheFields} = model; const sourceBodyRows = sourceSheet.getSheetValues().slice(2); xmlStream.openXml(XmlStream.StdDocAttributes); xmlStream.openNode(this.tag, { ...PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES, count: sourceBodyRows.length, }); xmlStream.writeXml(renderTable()); xmlStream.closeNode(); // Helpers function renderTable() { const rowsInXML = sourceBodyRows.map(row => { const realRow = row.slice(1); return [...renderRowLines(realRow)].join(''); }); return rowsInXML.join(''); } function* renderRowLines(row) { // PivotCache Record: http://www.datypic.com/sc/ooxml/e-ssml_r-1.html // Note: pretty-printing this for now to ease debugging. yield '\n <r>'; for (const [index, cellValue] of row.entries()) { yield '\n '; yield renderCell(cellValue, cacheFields[index].sharedItems); } yield '\n </r>'; } function renderCell(value, sharedItems) { // missing/null/undefined values // -------------------------------------------------- if (value === null || value === undefined) { // Missing Value: http://www.datypic.com/sc/ooxml/e-ssml_m-3.html return '<m />'; } // no shared items // -------------------------------------------------- if (sharedItems === null) { if (Number.isFinite(value)) { // Numeric value: http://www.datypic.com/sc/ooxml/e-ssml_n-2.html return `<n v="${value}" />`; } // Character Value: http://www.datypic.com/sc/ooxml/e-ssml_s-2.html return `<s v="${value}" />`; } // shared items // -------------------------------------------------- // Excel treats pivot values as case-insensitive, so we need to find // the index using case-insensitive comparison for strings let sharedItemsIndex; if (typeof value === 'string') { const lowerValue = value.toLowerCase(); sharedItemsIndex = sharedItems.findIndex(item => typeof item === 'string' && item.toLowerCase() === lowerValue); } else { sharedItemsIndex = sharedItems.indexOf(value); } if (sharedItemsIndex < 0) { throw new Error(`${JSON.stringify(value)} not in sharedItems ${JSON.stringify(sharedItems)}`); } // Shared Items Index: http://www.datypic.com/sc/ooxml/e-ssml_x-9.html return `<x v="${sharedItemsIndex}" />`; } } parseOpen(node) { // TK } parseText(text) { // TK } parseClose(name) { // TK } reconcile(model, options) { // TK } } PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES = { xmlns: 'http://schemas.openxmlformats.org/spreadsheetml/2006/main', 'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', 'xmlns:mc': 'http://schemas.openxmlformats.org/markup-compatibility/2006', 'mc:Ignorable': 'xr', 'xmlns:xr': 'http://schemas.microsoft.com/office/spreadsheetml/2014/revision', }; module.exports = PivotCacheRecordsXform;