UNPKG

excel4node

Version:

Library to create Formatted Excel Files.

466 lines (420 loc) 14.1 kB
var Column = require('./Column.js'), Row = require('./Row.js'), Cell = require('./Cell.js'), Image = require('./Images.js'), xml = require('xmlbuilder'); var WorkSheet = function(wb){ this.wb = wb; this.opts = {}; this.name = ''; this.hasGroupings = false; this.margins = { bottom:1.0, footer:.5, header:.5, left:.75, right:.75, top:1.0 }; this.printOptions = { centerHorizontal: false, centerVertical: true } this.sheetView = { workbookViewId:0, rightToLeft:0, zoomScale:100, zoomScaleNormal:100, zoomScalePageLayoutView:100 } this.sheet={}; this.sheet['@mc:Ignorable']="x14ac"; this.sheet['@xmlns']='http://schemas.openxmlformats.org/spreadsheetml/2006/main'; this.sheet['@xmlns:mc']="http://schemas.openxmlformats.org/markup-compatibility/2006"; this.sheet['@xmlns:r']='http://schemas.openxmlformats.org/officeDocument/2006/relationships'; this.sheet['@xmlns:x14ac']="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"; this.sheet.sheetPr = { outlinePr:{ '@summaryBelow':1 } } this.sheet.sheetViews = [ { sheetView:[] } ]; this.sheet.sheetFormatPr = { '@baseColWidth':10, '@defaultRowHeight':15, '@x14ac:dyDescent':0 }; this.sheet.sheetData = []; this.sheet.pageMargins = []; this.sheet.pageSetup = []; this.sheet.printOptions = []; this.cols = {}; this.rows = {}; this.Settings = { Outline:{ SummaryBelow : settings(this).outlineSummaryBelow } } }; WorkSheet.prototype.setName = function(name){ this.name = name; } WorkSheet.prototype.Cell = Cell.Cell; WorkSheet.prototype.Row = Row.Row; WorkSheet.prototype.Column = Column.Column; WorkSheet.prototype.Image = Image.Image; WorkSheet.prototype.getCell = getCell; WorkSheet.prototype.setWSOpts = setWSOpts; WorkSheet.prototype.toXML = toXML; WorkSheet.prototype.setValidation = setValidation; var countValidation = 0; function setValidation(data) { countValidation++; this.sheet.dataValidations = this.sheet.dataValidations || {}; this.sheet.dataValidations['@count'] = countValidation; this.sheet.dataValidations['#list'] = this.sheet.dataValidations['#list'] || []; var dataValidation = {}; Object.keys(data).forEach(function (key) { if (key == 'formulas') { return; } dataValidation['@' + key] = data[key]; }); data.formulas.forEach(function (f, i) { f = typeof f == 'number' ? f : '"' + f + '"'; dataValidation['formula' + (i + 1)] = f; }); this.sheet.dataValidations['#list'].push({ dataValidation: dataValidation }); } function getCell(a,b){ var props = {}; if(typeof(a) == 'string'){ props = a.toExcelRowCol(); }else if(typeof(a) == 'number' && typeof(b) == 'number'){ props.row = a; props.col = b; }else{ return undefined; } return thisWS.rows[props.row].cells[props.col]; } function settings(thisWS){ var theseSettings = {}; theseSettings.outlineSummaryBelow = function(val){ console.log("####################################################################################"); console.log("# WorkSheet.Settings is deprecated and will be removed in version 1.0.0 #"); console.log("# Create WorkBooks with opts paramater instead. #"); console.log("####################################################################################"); val = val?1:0; thisWS.sheet.sheetPr.outlinePr['@summaryBelow']=val; } return theseSettings; } function setWSOpts(opts){ var opts = opts?opts:{}; var thisWS = this; // Set Margins if(opts.margins){ this.margins.bottom = opts.margins.bottom?opts.margins.bottom:1.0; this.margins.footer = opts.margins.footer?opts.margins.footer:.5; this.margins.header = opts.margins.header?opts.margins.header:.5; this.margins.left = opts.margins.left?opts.margins.left:.75; this.margins.right = opts.margins.right?opts.margins.right:.75; this.margins.top = opts.margins.top?opts.margins.top:1.0; } Object.keys(this.margins).forEach(function(k){ var margin = {}; margin['@'+k] = thisWS.margins[k]; thisWS.sheet.pageMargins.push(margin); }); // Set Print Options if(opts.printOptions){ this.printOptions.centerHorizontal = opts.printOptions.centerHorizontal?opts.printOptions.centerHorizontal:false; this.printOptions.centerVertical = opts.printOptions.centerVertical?opts.printOptions.centerVertical:false; } this.sheet.printOptions.push({'@horizontalCentered':this.printOptions.centerHorizontal?1:0}); this.sheet.printOptions.push({'@verticalCentered':this.printOptions.centerVertical?1:0}); // Set Page View options var thisView = this.sheet.sheetViews[0].sheetView; if(opts.view){ if(parseInt(opts.view.zoom) != opts.view.zoom){ console.log("invalid value for zoom. value must be an integer. value was %s",opts.view.zoom); opts.view.zoom = 100; } this.sheetView.zoomScale = opts.view.zoom?opts.view.zoom:100; this.sheetView.zoomScaleNormal = opts.view.zoom?opts.view.zoom:100; this.sheetView.zoomScalePageLayoutView = opts.view.zoom?opts.view.zoom:100; if (opts.view.rtl) { this.sheetView.rightToLeft = 1; } } // Set Outline Options if(opts.outline){ thisWS.sheet.sheetPr.outlinePr = { '@summaryBelow':opts.outline.summaryBelow==false?0:1 }; } // Set Page Setup if (opts.fitToPage) { this.sheet.sheetPr.pageSetUpPr = {'@fitToPage':1}; this.sheet.pageSetup.push({'@fitToHeight':opts.fitToPage.fitToHeight?opts.fitToPage.fitToHeight:1}); this.sheet.pageSetup.push({'@fitToWidth':opts.fitToPage.fitToWidth?opts.fitToPage.fitToWidth:1}); this.sheet.pageSetup.push({'@orientation':opts.fitToPage.orientation ?opts.fitToPage.orientation :'portrait'}); this.sheet.pageSetup.push({'@horizontalDpi':opts.fitToPage.horizontalDpi?opts.fitToPage.horizontalDpi:4294967292}); this.sheet.pageSetup.push({'@verticalDpi':opts.fitToPage.verticalDpi?opts.fitToPage.verticalDpi:4294967292}); } thisView.push({'@workbookViewId':this.sheetView.workbookViewId?this.sheetView.workbookViewId:0}); thisView.push({'@zoomScale':this.sheetView.zoomScale?this.sheetView.zoomScale:100}); thisView.push({'@zoomScaleNormal':this.sheetView.zoomScaleNormal?this.sheetView.zoomScaleNormal:100}); thisView.push({'@zoomScalePageLayoutView':this.sheetView.zoomScalePageLayoutView?this.sheetView.zoomScalePageLayoutView:100}); thisView.push({'@rightToLeft':this.sheetView.rightToLeft?1:0}); } function toXML(){ var thisWS = this; var thisSheet = JSON.parse(JSON.stringify(thisWS.sheet)); var sheetData = thisSheet.sheetData; var xmlOutVars = {}; var xmlDebugVars = { pretty: true, indent: ' ',newline: '\n' }; /* Process groupings and add collapsed attributes to rows where applicable */ if(thisWS.hasGroupings){ var lastRowNum = Object.keys(thisWS.rows).sort()[Object.keys(thisWS.rows).length - 1]; var lastColNum = Object.keys(thisWS.cols).sort()[Object.keys(thisWS.cols).length - 1]; var rOutlineLevels = { curHighestLevel:0, 0:{ startRow:1, endRow:1, isHidden:0 } }; var cOutlineLevels = { curHighestLevel:0, 0:{ startCol:1, endCol:1, isHidden:0 } }; var summaryBelow = parseInt(thisSheet.sheetPr.outlinePr['@summaryBelow']) == 0 ? false : true; if(summaryBelow && thisWS.rows[lastRowNum].attributes.hidden){ thisWS.Row(parseInt(lastRowNum)+1); } if(summaryBelow && thisWS.cols[lastColNum].hidden){ thisWS.Column(parseInt(lastColNum)+1); } Object.keys(thisWS.rows).forEach(function(rNum,i){ var rID = parseInt(rNum); var curRow = thisWS.rows[rNum]; var thisLevel = curRow.attributes.outlineLevel?curRow.attributes.outlineLevel:0; var isHidden = curRow.attributes.hidden==1?curRow.attributes.hidden:0; var rowNum = curRow.attributes.r; rOutlineLevels[0].endRow=rID; rOutlineLevels[0].isHidden=isHidden; if(typeof(rOutlineLevels[thisLevel]) == 'undefined'){ rOutlineLevels[thisLevel] = { startRow:rID, endRow:rID, isHidden:isHidden } } if(thisLevel <= rOutlineLevels.curHighestLevel){ rOutlineLevels[thisLevel].endRow = rID; rOutlineLevels[thisLevel].isHidden = isHidden; } if(thisLevel != rOutlineLevels.curHighestLevel || rID == lastRowNum){ if(summaryBelow && thisLevel != rOutlineLevels.curHighestLevel){ if(rID == lastRowNum){ thisLevel=1; } for(oLi = rOutlineLevels.curHighestLevel; oLi > thisLevel; oLi--){ if(rOutlineLevels[oLi]){ var rowToCollapse = rOutlineLevels[oLi].endRow + 1; var lastRow = thisWS.Row(rowToCollapse); lastRow.setAttribute('collapsed',rOutlineLevels[oLi].isHidden); delete rOutlineLevels[oLi]; } } }else if(!summaryBelow && thisLevel != rOutlineLevels.curHighestLevel){ if(rOutlineLevels[thisLevel]){ if(thisLevel>rOutlineLevels.curHighestLevel){ var rowToCollapse = rOutlineLevels[rOutlineLevels.curHighestLevel].startRow; }else{ var rowToCollapse = rOutlineLevels[thisLevel].startRow; } var lastRow = thisWS.Row(rowToCollapse); lastRow.setAttribute('collapsed',rOutlineLevels[thisLevel].isHidden); rOutlineLevels[thisLevel].startRow = rowNum; } } } if(thisLevel!=rOutlineLevels.curHighestLevel){ rOutlineLevels.curHighestLevel=thisLevel; } }); Object.keys(thisWS.cols).forEach(function(cNum,i){ var cID = parseInt(cNum); var curCol = thisWS.cols[cNum]; var thisLevel = curCol.outlineLevel?curCol.outlineLevel:0; var isHidden = curCol.hidden==1?curCol.hidden:0; var colNum = curCol.min; cOutlineLevels[0].endCol=cID; cOutlineLevels[0].isHidden=isHidden; if(typeof(cOutlineLevels[thisLevel]) == 'undefined'){ cOutlineLevels[thisLevel] = { startCol:cID, endCol:cID, isHidden:isHidden } } if(thisLevel <= cOutlineLevels.curHighestLevel){ cOutlineLevels[thisLevel].endCol = cID; cOutlineLevels[thisLevel].isHidden = isHidden; } if(thisLevel != cOutlineLevels.curHighestLevel || cID == lastColNum){ if(summaryBelow && thisLevel != cOutlineLevels.curHighestLevel){ if(cID == lastColNum){ thisLevel=1; } for(oLi = cOutlineLevels.curHighestLevel; oLi > thisLevel; oLi--){ if(cOutlineLevels[oLi]){ var colToCollapse = cOutlineLevels[oLi].endCol + 1; var lastCol = thisWS.Column(colToCollapse); lastCol.setAttribute('collapsed',cOutlineLevels[oLi].isHidden); delete cOutlineLevels[oLi]; } } }else if(!summaryBelow && thisLevel != cOutlineLevels.curHighestLevel){ if(cOutlineLevels[thisLevel]){ if(thisLevel>cOutlineLevels.curHighestLevel){ var colToCollapse = cOutlineLevels[cOutlineLevels.curHighestLevel].startCol; }else{ var colToCollapse = cOutlineLevels[thisLevel].startCol; } var lastCol = thisWS.Column(colToCollapse); lastCol.setAttribute('collapsed',cOutlineLevels[thisLevel].isHidden); cOutlineLevels[thisLevel].startCol = colNum; } } } if(thisLevel!=cOutlineLevels.curHighestLevel){ cOutlineLevels.curHighestLevel=thisLevel; } }); } /* Process Column Definitions */ if(Object.keys(thisWS.cols).length > 0){ if(thisSheet.cols instanceof Array === false){ thisSheet.cols=[]; } Object.keys(thisWS.cols).forEach(function(i){ var c = thisWS.cols[i]; var thisCol = {col:[]}; Object.keys(c).forEach(function(k){ var tmpObj = {}; if(typeof(c[k]) != 'object'){ tmpObj['@'+k] = c[k]; thisCol.col.push(tmpObj); } }); thisSheet.cols.push(thisCol); }); } /* Process Rows of data */ Object.keys(thisWS.rows).forEach(function(r,i){ var thisRow = {row:[]}; Object.keys(thisWS.rows[r].attributes).forEach(function(a,i){ var attr = '@'+a; var obj = {}; obj[attr] = thisWS.rows[r].attributes[a]; thisRow.row.push(obj); }); Object.keys(thisWS.rows[r].cells).forEach(function(c,i){ var thisCellIndex = thisRow.row.push({'c':{}}); var thisCell = thisRow.row[thisCellIndex - 1]['c']; Object.keys(thisWS.rows[r].cells[c].attributes).forEach(function(a,i){ thisCell['@'+a] = thisWS.rows[r].cells[c].attributes[a]; }); Object.keys(thisWS.rows[r].cells[c].children).forEach(function(v,i){ thisCell[v] = thisWS.rows[r].cells[c].children[v]; }); }) sheetData.push(thisRow) }); /* Process and merged cells */ if(thisWS.mergeCells && thisWS.mergeCells.length>=0){ thisSheet.mergeCells = []; thisSheet.mergeCells.push({'@count':thisWS.mergeCells.length}); thisWS.mergeCells.forEach(function(cr){ thisSheet.mergeCells.push({'mergeCell':{'@ref':cr}}); }); }; /* Process hyperlinks */ if(thisWS.hyperlinks && thisWS.hyperlinks.length>=0){ thisSheet.hyperlinks = []; thisWS.hyperlinks.forEach(function(cr){ thisSheet.hyperlinks.push({'hyperlink':{'@ref':cr.ref,'@r:id':'rId' + cr.id}}); }); }; /* Excel complains if specific attributes on not in the correct order in the XML doc. */ var excelOrder = [ 'sheetPr', 'sheetViews', 'sheetFormatPr', 'cols', 'sheetData', 'autoFilter', 'mergeCells', 'hyperlinks', 'dataValidations', 'printOptions', 'pageMargins', 'pageSetup', 'drawing' ]; var orderedDef = []; Object.keys(thisSheet).forEach(function(k){ if(k.charAt(0)==='@'){ var def = {}; def[k] = thisSheet[k]; orderedDef.push(def); } }); excelOrder.forEach(function(k){ if(k=='autoFilter' && thisSheet[k]){ thisSheet.sheetPr['@enableFormatConditionsCalculation']='1'; thisSheet.sheetPr['@filterMode']='1'; var refParts = thisSheet[k][0]['@ref'].split(':'); var cell = refParts[1].toExcelRowCol(); refParts[1] = cell.col.toExcelAlpha() + thisSheet.sheetData.length; thisSheet[k][0]['@ref'] = refParts.join(':'); } if(thisSheet[k]){ var def = {}; def[k] = thisSheet[k]; orderedDef.push(def); } }); var wsXML = xml.create('worksheet',{version: '1.0', encoding: 'UTF-8', standalone: true}); orderedDef.forEach(function(obj){ wsXML.ele(obj); }); var xmlStr = wsXML.end(xmlOutVars); return xmlStr; } module.exports = WorkSheet;