excel4node
Version:
Library to create Formatted Excel Files.
684 lines (592 loc) • 26.1 kB
JavaScript
const xml = require('xmlbuilder');
const utils = require('../utils.js');
const types = require('../types/index.js');
const hyperlinks = require('./classes/hyperlink');
const Picture = require('../drawing/picture.js');
let _addSheetPr = (promiseObj) => {
// §18.3.1.82 sheetPr (Sheet Properties)
return new Promise((resolve, reject) => {
let o = promiseObj.ws.opts;
// Check if any option that would require the sheetPr element to be added exists
if (
o.pageSetup.fitToHeight !== null ||
o.pageSetup.fitToWidth !== null ||
o.outline.summaryBelow !== null ||
o.outline.summaryRight !== null ||
o.autoFilter.ref !== null
) {
let ele = promiseObj.xml.ele('sheetPr');
if (o.autoFilter.ref) {
ele.att('enableFormatConditionsCalculation', 1);
ele.att('filterMode', 1);
}
if (o.outline.summaryBelow !== null || o.outline.summaryRight !== null) {
let outlineEle = ele.ele('outlinePr');
outlineEle.att('applyStyles', 1);
outlineEle.att('summaryBelow', o.outline.summaryBelow === true ? 1 : 0);
outlineEle.att('summaryRight', o.outline.summaryRight === true ? 1 : 0);
outlineEle.up();
}
// §18.3.1.65 pageSetUpPr (Page Setup Properties)
if (o.pageSetup.fitToHeight !== null || o.pageSetup.fitToWidth !== null) {
ele.ele('pageSetUpPr').att('fitToPage', 1).up();
}
ele.up();
}
resolve(promiseObj);
});
};
let _addDimension = (promiseObj) => {
// §18.3.1.35 dimension (Worksheet Dimensions)
return new Promise((resolve, reject) => {
let firstCell = 'A1';
let lastCell = `${utils.getExcelAlpha(promiseObj.ws.lastUsedCol)}${promiseObj.ws.lastUsedRow}`;
let ele = promiseObj.xml.ele('dimension');
ele.att('ref', `${firstCell}:${lastCell}`);
ele.up();
resolve(promiseObj);
});
};
let _addSheetViews = (promiseObj) => {
// §18.3.1.88 sheetViews (Sheet Views)
return new Promise((resolve, reject) => {
let o = promiseObj.ws.opts.sheetView;
let ele = promiseObj.xml.ele('sheetViews');
let sv = ele.ele('sheetView')
.att('showGridLines', o.showGridLines)
.att('workbookViewId', o.workbookViewId)
.att('rightToLeft', o.rightToLeft)
.att('zoomScale', o.zoomScale)
.att('zoomScaleNormal', o.zoomScaleNormal)
.att('zoomScalePageLayoutView', o.zoomScalePageLayoutView);
let modifiedPaneParams = [];
Object.keys(o.pane).forEach((k) => {
if (o.pane[k] !== null) {
modifiedPaneParams.push(k);
}
});
if (modifiedPaneParams.length > 0) {
let pEle = sv.ele('pane');
o.pane.xSplit !== null ? pEle.att('xSplit', o.pane.xSplit) : null;
o.pane.ySplit !== null ? pEle.att('ySplit', o.pane.ySplit) : null;
o.pane.topLeftCell !== null ? pEle.att('topLeftCell', o.pane.topLeftCell) : null;
o.pane.activePane !== null ? pEle.att('activePane', o.pane.activePane) : null;
o.pane.state !== null ? pEle.att('state', o.pane.state) : null;
pEle.up();
}
sv.up();
ele.up();
resolve(promiseObj);
});
};
let _addSheetFormatPr = (promiseObj) => {
// §18.3.1.81 sheetFormatPr (Sheet Format Properties)
return new Promise((resolve, reject) => {
let o = promiseObj.ws.opts.sheetFormat;
let ele = promiseObj.xml.ele('sheetFormatPr');
o.baseColWidth !== null ? ele.att('baseColWidth', o.baseColWidth) : null;
o.defaultColWidth !== null ? ele.att('defaultColWidth', o.defaultColWidth) : null;
o.defaultRowHeight !== null ? ele.att('defaultRowHeight', o.defaultRowHeight) : ele.att('defaultRowHeight', 16);
o.thickBottom !== null ? ele.att('thickBottom', utils.boolToInt(o.thickBottom)) : null;
o.thickTop !== null ? ele.att('thickTop', utils.boolToInt(o.thickTop)) : null;
if (typeof o.defaultRowHeight === 'number') {
ele.att('customHeight', '1');
}
ele.up();
resolve(promiseObj);
});
};
let _addCols = (promiseObj) => {
// §18.3.1.17 cols (Column Information)
return new Promise((resolve, reject) => {
if (promiseObj.ws.columnCount > 0) {
let colsEle = promiseObj.xml.ele('cols');
for (let colId in promiseObj.ws.cols) {
let col = promiseObj.ws.cols[colId];
let colEle = colsEle.ele('col');
col.min !== null ? colEle.att('min', col.min) : null;
col.max !== null ? colEle.att('max', col.max) : null;
col.width !== null ? colEle.att('width', col.width) : null;
col.style !== null ? colEle.att('style', col.style) : null;
col.hidden !== null ? colEle.att('hidden', utils.boolToInt(col.hidden)) : null;
col.customWidth !== null ? colEle.att('customWidth', utils.boolToInt(col.customWidth)) : null;
col.outlineLevel !== null ? colEle.att('outlineLevel', col.outlineLevel) : null;
col.collapsed !== null ? colEle.att('collapsed', utils.boolToInt(col.collapsed)) : null;
colEle.up();
}
colsEle.up();
}
resolve(promiseObj);
});
};
let _addSheetData = (promiseObj) => {
// §18.3.1.80 sheetData (Sheet Data)
return new Promise((resolve, reject) => {
let ele = promiseObj.xml.ele('sheetData');
let rows = Object.keys(promiseObj.ws.rows);
let processRows = (theseRows) => {
for (var r = 0; r < theseRows.length; r++) {
let thisRow = promiseObj.ws.rows[theseRows[r]];
thisRow.cellRefs.sort(utils.sortCellRefs);
let rEle = ele.ele('row');
rEle.att('r', thisRow.r);
if (promiseObj.ws.opts.disableRowSpansOptimization !== true && thisRow.spans) {
rEle.att('spans', thisRow.spans);
}
thisRow.s !== null ? rEle.att('s', thisRow.s) : null;
thisRow.customFormat !== null ? rEle.att('customFormat', thisRow.customFormat) : null;
thisRow.ht !== null ? rEle.att('ht', thisRow.ht) : null;
thisRow.hidden !== null ? rEle.att('hidden', thisRow.hidden) : null;
thisRow.customHeight === true || typeof promiseObj.ws.opts.sheetFormat.defaultRowHeight === 'number' ? rEle.att('customHeight', 1) : null;
thisRow.outlineLevel !== null ? rEle.att('outlineLevel', thisRow.outlineLevel) : null;
thisRow.collapsed !== null ? rEle.att('collapsed', thisRow.collapsed) : null;
thisRow.thickTop !== null ? rEle.att('thickTop', thisRow.thickTop) : null;
thisRow.thickBot !== null ? rEle.att('thickBot', thisRow.thickBot) : null;
for (var i = 0; i < thisRow.cellRefs.length; i++) {
promiseObj.ws.cells[thisRow.cellRefs[i]].addToXMLele(rEle);
}
rEle.up();
}
processNextRows();
};
let processNextRows = () => {
let theseRows = rows.splice(0, 500);
if (theseRows.length === 0) {
ele.up();
return resolve(promiseObj);
}
processRows(theseRows);
};
processNextRows();
});
};
let _addSheetProtection = (promiseObj) => {
// §18.3.1.85 sheetProtection (Sheet Protection Options)
return new Promise((resolve, reject) => {
let o = promiseObj.ws.opts.sheetProtection;
let includeSheetProtection = false;
Object.keys(o).forEach((k) => {
if (o[k] !== null) {
includeSheetProtection = true;
}
});
if (includeSheetProtection) {
// Set required fields with defaults if not specified
o.sheet = o.sheet !== null ? o.sheet : true;
o.objects = o.objects !== null ? o.objects : true;
o.scenarios = o.scenarios !== null ? o.scenarios : true;
let ele = promiseObj.xml.ele('sheetProtection');
Object.keys(o).forEach((k) => {
if (o[k] !== null) {
if (k === 'password') {
ele.att('password', utils.getHashOfPassword(o[k]));
} else {
ele.att(k, utils.boolToInt(o[k]));
}
}
});
ele.up();
}
resolve(promiseObj);
});
};
let _addAutoFilter = (promiseObj) => {
// §18.3.1.2 autoFilter (AutoFilter Settings)
return new Promise((resolve, reject) => {
let o = promiseObj.ws.opts.autoFilter;
if (typeof o.startRow === 'number') {
let ele = promiseObj.xml.ele('autoFilter');
let filterRow = promiseObj.ws.rows[o.startRow];
o.startCol = typeof o.startCol === 'number' ? o.startCol : null;
o.endCol = typeof o.endCol === 'number' ? o.endCol : null;
if (typeof o.endRow !== 'number') {
let firstEmptyRow = undefined;
let curRow = o.startRow;
while (firstEmptyRow === undefined) {
if (!promiseObj.ws.rows[curRow]) {
firstEmptyRow = curRow;
} else {
curRow++;
}
}
o.endRow = firstEmptyRow - 1;
}
// Columns to sort not manually set. filter all columns in this row containing data.
if (typeof o.startCol !== 'number' || typeof o.endCol !== 'number') {
o.startCol = filterRow.firstColumn;
o.endCol = filterRow.lastColumn;
}
let startCell = utils.getExcelAlpha(o.startCol) + o.startRow;
let endCell = utils.getExcelAlpha(o.endCol) + o.endRow;
ele.att('ref', `${startCell}:${endCell}`);
promiseObj.ws.wb.definedNameCollection.addDefinedName({
hidden: 1,
localSheetId: promiseObj.ws.localSheetId,
name: '_xlnm._FilterDatabase',
refFormula: '\'' + promiseObj.ws.name + '\'!' +
'$' + utils.getExcelAlpha(o.startCol) +
'$' + o.startRow +
':' +
'$' + utils.getExcelAlpha(o.endCol) +
'$' + o.endRow
});
ele.up();
}
resolve(promiseObj);
});
};
let _addMergeCells = (promiseObj) => {
// §18.3.1.55 mergeCells (Merge Cells)
return new Promise((resolve, reject) => {
if (promiseObj.ws.mergedCells instanceof Array && promiseObj.ws.mergedCells.length > 0) {
let ele = promiseObj.xml.ele('mergeCells').att('count', promiseObj.ws.mergedCells.length);
promiseObj.ws.mergedCells.forEach((cr) => {
ele.ele('mergeCell').att('ref', cr).up();
});
ele.up();
}
resolve(promiseObj);
});
};
let _addConditionalFormatting = (promiseObj) => {
// §18.3.1.18 conditionalFormatting (Conditional Formatting)
return new Promise((resolve, reject) => {
promiseObj.ws.cfRulesCollection.addToXMLele(promiseObj.xml);
resolve(promiseObj);
});
};
let _addHyperlinks = (promiseObj) => {
// §18.3.1.48 hyperlinks (Hyperlinks)
return new Promise((resolve, reject) => {
promiseObj.ws.hyperlinkCollection.addToXMLele(promiseObj.xml);
resolve(promiseObj);
});
};
let _addDataValidations = (promiseObj) => {
// §18.3.1.33 dataValidations (Data Validations)
return new Promise((resolve, reject) => {
if (promiseObj.ws.dataValidationCollection.length > 0) {
promiseObj.ws.dataValidationCollection.addToXMLele(promiseObj.xml);
}
resolve(promiseObj);
});
};
let _addPrintOptions = (promiseObj) => {
// §18.3.1.70 printOptions (Print Options)
return new Promise((resolve, reject) => {
let addPrintOptions = false;
let o = promiseObj.ws.opts.printOptions;
Object.keys(o).forEach((k) => {
if (o[k] !== null) {
addPrintOptions = true;
}
});
if (addPrintOptions) {
let poEle = promiseObj.xml.ele('printOptions');
o.centerHorizontal === true ? poEle.att('horizontalCentered', 1) : null;
o.centerVertical === true ? poEle.att('verticalCentered', 1) : null;
o.printHeadings === true ? poEle.att('headings', 1) : null;
if (o.printGridLines === true) {
poEle.att('gridLines', 1);
poEle.att('gridLinesSet', 1);
}
poEle.up();
}
resolve(promiseObj);
});
};
let _addPageMargins = (promiseObj) => {
// §18.3.1.62 pageMargins (Page Margins)
return new Promise((resolve, reject) => {
let o = promiseObj.ws.opts.margins;
promiseObj.xml.ele('pageMargins')
.att('left', o.left)
.att('right', o.right)
.att('top', o.top)
.att('bottom', o.bottom)
.att('header', o.header)
.att('footer', o.footer)
.up();
resolve(promiseObj);
});
};
let _addLegacyDrawing = (promiseObj) => {
return new Promise((resolve, reject) => {
const rId = promiseObj.ws.relationships.indexOf('commentsVml') + 1;
if(rId === 0) {
resolve(promiseObj);
} else {
promiseObj.xml.ele('legacyDrawing')
.att('r:id', 'rId' + rId)
.up();
resolve(promiseObj);
}
})
}
let _addPageSetup = (promiseObj) => {
// §18.3.1.63 pageSetup (Page Setup Settings)
return new Promise((resolve, reject) => {
let addPageSetup = false;
let o = promiseObj.ws.opts.pageSetup;
Object.keys(o).forEach((k) => {
if (o[k] !== null) {
addPageSetup = true;
}
});
if (addPageSetup === true) {
let psEle = promiseObj.xml.ele('pageSetup');
o.paperSize !== null ? psEle.att('paperSize', types.paperSize[o.paperSize]) : null;
o.paperHeight !== null ? psEle.att('paperHeight', o.paperHeight) : null;
o.paperWidth !== null ? psEle.att('paperWidth', o.paperWidth) : null;
o.scale !== null ? psEle.att('scale', o.scale) : null;
o.firstPageNumber !== null ? psEle.att('firstPageNumber', o.firstPageNumber) : null;
o.fitToWidth !== null ? psEle.att('fitToWidth', o.fitToWidth) : null;
o.fitToHeight !== null ? psEle.att('fitToHeight', o.fitToHeight) : null;
o.pageOrder !== null ? psEle.att('pageOrder', o.pageOrder) : null;
o.orientation !== null ? psEle.att('orientation', o.orientation) : null;
o.usePrinterDefaults !== null ? psEle.att('usePrinterDefaults', utils.boolToInt(o.usePrinterDefaults)) : null;
o.blackAndWhite !== null ? psEle.att('blackAndWhite', utils.boolToInt(o.blackAndWhite)) : null;
o.draft !== null ? psEle.att('draft', utils.boolToInt(o.draft)) : null;
o.cellComments !== null ? psEle.att('cellComments', o.cellComments) : null;
o.useFirstPageNumber !== null ? psEle.att('useFirstPageNumber', utils.boolToInt(o.useFirstPageNumber)) : null;
o.errors !== null ? psEle.att('errors', o.errors) : null;
o.horizontalDpi !== null ? psEle.att('horizontalDpi', o.horizontalDpi) : null;
o.verticalDpi !== null ? psEle.att('verticalDpi', o.verticalDpi) : null;
o.copies !== null ? psEle.att('copies', o.copies) : null;
psEle.up();
}
resolve(promiseObj);
});
};
let _addPageBreaks = (promiseObj) => {
// colBreaks (§18.3.1.14); rowBreaks (§18.3.1.74)
const rowBreaks = promiseObj.ws.pageBreaks.row;
if (rowBreaks.length > 0) {
const rbEle = promiseObj.xml.ele('rowBreaks');
rbEle.att('count', rowBreaks.length);
rbEle.att('manualBreakCount', rowBreaks.length);
rowBreaks.forEach(pos => {
const bEle = rbEle.ele('brk');
bEle.att('id', pos);
bEle.att('man', 1);
bEle.up();
});
rbEle.up();
}
const colBreaks = promiseObj.ws.pageBreaks.column;
if (colBreaks.length > 0) {
const cbEle = promiseObj.xml.ele('colBreaks');
cbEle.att('count', colBreaks.length);
cbEle.att('manualBreakCount', colBreaks.length);
colBreaks.forEach(pos => {
const bEle = cbEle.ele('brk');
bEle.att('id', pos);
bEle.att('man', 1);
bEle.up();
});
cbEle.up();
}
return promiseObj;
}
let _addHeaderFooter = (promiseObj) => {
// §18.3.1.46 headerFooter (Header Footer Settings)
return new Promise((resolve, reject) => {
let addHeaderFooter = false;
let o = promiseObj.ws.opts.headerFooter;
Object.keys(o).forEach((k) => {
if (o[k] !== null) {
addHeaderFooter = true;
}
});
if (addHeaderFooter === true) {
let hfEle = promiseObj.xml.ele('headerFooter');
o.alignWithMargins !== null ? hfEle.att('alignWithMargins', utils.boolToInt(o.alignWithMargins)) : null;
o.differentFirst !== null ? hfEle.att('differentFirst', utils.boolToInt(o.differentFirst)) : null;
o.differentOddEven !== null ? hfEle.att('differentOddEven', utils.boolToInt(o.differentOddEven)) : null;
o.scaleWithDoc !== null ? hfEle.att('scaleWithDoc', utils.boolToInt(o.scaleWithDoc)) : null;
o.oddHeader !== null ? hfEle.ele('oddHeader').text(o.oddHeader).up() : null;
o.oddFooter !== null ? hfEle.ele('oddFooter').text(o.oddFooter).up() : null;
o.evenHeader !== null ? hfEle.ele('evenHeader').text(o.evenHeader).up() : null;
o.evenFooter !== null ? hfEle.ele('evenFooter').text(o.evenFooter).up() : null;
o.firstHeader !== null ? hfEle.ele('firstHeader').text(o.firstHeader).up() : null;
o.firstFooter !== null ? hfEle.ele('firstFooter').text(o.firstFooter).up() : null;
hfEle.up();
}
resolve(promiseObj);
});
};
let _addDrawing = (promiseObj) => {
// §18.3.1.36 drawing (Drawing)
return new Promise((resolve, reject) => {
if (!promiseObj.ws.drawingCollection.isEmpty) {
let dId = promiseObj.ws.relationships.indexOf('drawing') + 1;
promiseObj.xml.ele('drawing').att('r:id', 'rId' + dId).up();
}
resolve(promiseObj);
});
};
let sheetXML = (ws) => {
return new Promise((resolve, reject) => {
let xmlProlog = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
let xmlString = '';
let wsXML = xml.begin({
'allowSurrogateChars': true,
}, (chunk) => {
xmlString += chunk;
})
.ele('worksheet')
.att('mc:Ignorable', 'x14ac')
.att('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main')
.att('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006')
.att('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships')
.att('xmlns:x14ac', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac');
// Excel complains if specific elements on not in the correct order in the XML doc as defined in §M.2.2
let promiseObj = { xml: wsXML, ws: ws };
_addSheetPr(promiseObj)
.then(_addDimension)
.then(_addSheetViews)
.then(_addSheetFormatPr)
.then(_addCols)
.then(_addSheetData)
.then(_addSheetProtection)
.then(_addAutoFilter)
.then(_addMergeCells)
.then(_addConditionalFormatting)
.then(_addDataValidations)
.then(_addHyperlinks)
.then(_addPrintOptions)
.then(_addPageMargins)
.then(_addLegacyDrawing)
.then(_addPageSetup)
.then(_addPageBreaks)
.then(_addHeaderFooter)
.then(_addDrawing)
.then((promiseObj) => {
return new Promise((resolve, reject) => {
wsXML.end();
resolve(xmlString);
});
})
.then((xml) => {
resolve(xml);
})
.catch((e) => {
throw new Error(e.stack);
});
});
};
let relsXML = (ws) => {
return new Promise((resolve, reject) => {
let sheetRelRequired = false;
if (ws.relationships.length > 0) {
sheetRelRequired = true;
}
if (sheetRelRequired === false) {
resolve();
}
let relXML = xml.create(
'Relationships',
{
'version': '1.0',
'encoding': 'UTF-8',
'standalone': true,
'allowSurrogateChars': true
}
);
relXML.att('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
ws.relationships.forEach((r, i) => {
let rId = 'rId' + (i + 1);
if (r instanceof hyperlinks.Hyperlink) {
relXML.ele('Relationship')
.att('Id', rId)
.att('Target', r.location)
.att('TargetMode', 'External')
.att('Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink');
} else if (r === 'drawing') {
relXML.ele('Relationship')
.att('Id', rId)
.att('Target', '../drawings/drawing' + ws.sheetId + '.xml')
.att('Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing');
} else if (r === 'comments') {
relXML.ele('Relationship')
.att('Id', rId)
.att('Target', '../comments' + ws.sheetId + '.xml')
.att('Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments');
} else if (r === 'commentsVml') {
relXML.ele('Relationship')
.att('Id', rId)
.att('Target', '../drawings/commentsVml' + ws.sheetId + '.vml')
.att('Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing');
}
});
let xmlString = relXML.doc().end();
resolve(xmlString);
});
};
let commentsXML = (ws) => {
return new Promise((resolve, reject) => {
const commentsXml = xml.create(
'comments',
{
'version': '1.0',
'encoding': 'UTF-8',
'standalone': true,
'allowSurrogateChars': true
}
);
commentsXml.att('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
commentsXml.ele('authors').ele('author').text(ws.wb.author);
const commentList = commentsXml.ele('commentList');
Object.keys(ws.comments).forEach(ref => {
commentList
.ele('comment')
.att('ref', ref)
.att('authorId', '0')
.att('guid', ws.comments[ref].uuid)
.ele('text')
.ele('t')
.text(ws.comments[ref].comment);
});
let xmlString = commentsXml.doc().end();
resolve(xmlString);
});
}
let commentsVmlXML = (ws) => {
return new Promise((resolve, reject) => {
// do not add XML prolog to document
const vmlXml = xml.begin().ele('xml');
vmlXml.att('xmlns:v', 'urn:schemas-microsoft-com:vml')
vmlXml.att('xmlns:o', 'urn:schemas-microsoft-com:office:office');
vmlXml.att('xmlns:x', 'urn:schemas-microsoft-com:office:excel');
const sl = vmlXml.ele('o:shapelayout').att('v:ext', 'edit');
sl.ele('o:idmap').att('v:ext', 'edit').att('data', ws.sheetId);
const st = vmlXml.ele('v:shapetype')
.att('id', '_x0000_t202')
.att('coordsize', '21600,21600')
.att('o:spt', '202')
.att('path', 'm,l,21600r21600,l21600,xe');
st.ele('v:stroke').att('joinstyle', 'miter');
st.ele('v:path').att('gradientshapeok', 't').att('o:connecttype', 'rect');
Object.keys(ws.comments).forEach((ref) => {
const {row, col, position, marginLeft, marginTop, width, height, zIndex, visibility, fillColor} = ws.comments[ref];
const shape = vmlXml.ele('v:shape');
shape.att('id', `_${ws.sheetId}_${row}_${col}`);
shape.att('type', "#_x0000_t202");
shape.att('style', `position:${position};margin-left:${marginLeft};margin-top:${marginTop};width:${width};height:${height};z-index:${zIndex};visibility:${visibility}`);
shape.att('fillcolor', fillColor);
shape.att('o:insetmode', 'auto');
shape.ele('v:path').att('o:connecttype', 'none');
const tb = shape.ele('v:textbox').att('style', 'mso-direction-alt:auto');
tb.ele('div').att('style', 'text-align:left');
const cd = shape.ele('x:ClientData').att('ObjectType', 'Note');
cd.ele('x:MoveWithCells');
cd.ele('x:SizeWithCells');
cd.ele('x:AutoFill').text('False');
cd.ele('x:Row').text(row - 1);
cd.ele('x:Column').text(col - 1);
});
let xmlString = vmlXml.doc().end();
resolve(xmlString);
});
}
module.exports = { sheetXML, relsXML, commentsXML, commentsVmlXML };