UNPKG

exceljs

Version:

Excel Workbook Manager - Read and Write xlsx and csv Files.

1,942 lines (1,773 loc) 1.3 MB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ExcelJS = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 'use strict'; var PromishLib = require('../utils/promish'); function setValue(key, value, overwrite) { if (overwrite === undefined) { // only avoid overwrite if explicitly disabled overwrite = true; } switch (key.toLowerCase()) { case 'promise': if (!overwrite && PromishLib.Promish) return; PromishLib.Promish = value; break; default: break; } } module.exports = setValue; },{"../utils/promish":15}],2:[function(require,module,exports){ /** * Copyright (c) 2015-2017 Guyon Roche * LICENCE: MIT - please refer to LICENCE file included with this module * or https://github.com/guyonroche/exceljs/blob/master/LICENSE */ 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var fs = require('fs'); var csv = require('fast-csv'); var moment = require('moment'); var PromishLib = require('../utils/promish'); var utils = require('../utils/utils'); var CSV = module.exports = function (workbook) { this.workbook = workbook; this.worksheet = null; }; /* eslint-disable quote-props */ var SpecialValues = { 'true': true, 'false': false, '#N/A': { error: '#N/A' }, '#REF!': { error: '#REF!' }, '#NAME?': { error: '#NAME?' }, '#DIV/0!': { error: '#DIV/0!' }, '#NULL!': { error: '#NULL!' }, '#VALUE!': { error: '#VALUE!' }, '#NUM!': { error: '#NUM!' } }; /* eslint-ensable quote-props */ CSV.prototype = { readFile: function readFile(filename, options) { var self = this; options = options || {}; var stream; return utils.fs.exists(filename).then(function (exists) { if (!exists) { throw new Error('File not found: ' + filename); } stream = fs.createReadStream(filename); return self.read(stream, options); }).then(function (worksheet) { stream.close(); return worksheet; }); }, read: function read(stream, options) { var _this = this; options = options || {}; return new PromishLib.Promish(function (resolve, reject) { var csvStream = _this.createInputStream(options).on('worksheet', resolve).on('error', reject); stream.pipe(csvStream); }); }, createInputStream: function createInputStream(options) { options = options || {}; var worksheet = this.workbook.addWorksheet(options.sheetName); var dateFormats = options.dateFormats || [moment.ISO_8601, 'MM-DD-YYYY', 'YYYY-MM-DD']; var map = options.map || function (datum) { if (datum === '') { return null; } if (!isNaN(datum)) { return parseFloat(datum); } var dt = moment(datum, dateFormats, true); if (dt.isValid()) { return new Date(dt.valueOf()); } var special = SpecialValues[datum]; if (special !== undefined) { return special; } return datum; }; var csvStream = csv(options).on('data', function (data) { worksheet.addRow(data.map(map)); }).on('end', function () { csvStream.emit('worksheet', worksheet); }); return csvStream; }, write: function write(stream, options) { var _this2 = this; return new PromishLib.Promish(function (resolve, reject) { options = options || {}; // var encoding = options.encoding || 'utf8'; // var separator = options.separator || ','; // var quoteChar = options.quoteChar || '\''; var worksheet = _this2.workbook.getWorksheet(options.sheetName || options.sheetId); var csvStream = csv.createWriteStream(options); stream.on('finish', function () { resolve(); }); csvStream.on('error', reject); csvStream.pipe(stream); var dateFormat = options.dateFormat; var map = options.map || function (value) { if (value) { if (value.text || value.hyperlink) { return value.hyperlink || value.text || ''; } if (value.formula || value.result) { return value.result || ''; } if (value instanceof Date) { return dateFormat ? moment(value).format(dateFormat) : moment(value).format(); } if (value.error) { return value.error; } if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') { return JSON.stringify(value); } } return value; }; var includeEmptyRows = options.includeEmptyRows === undefined || options.includeEmptyRows; var lastRow = 1; if (worksheet) { worksheet.eachRow(function (row, rowNumber) { if (includeEmptyRows) { while (lastRow++ < rowNumber - 1) { csvStream.write([]); } } var values = row.values; values.shift(); csvStream.write(values.map(map)); lastRow = rowNumber; }); } csvStream.end(); }); }, writeFile: function writeFile(filename, options) { options = options || {}; var streamOptions = { encoding: options.encoding || 'utf8' }; var stream = fs.createWriteStream(filename, streamOptions); return this.write(stream, options); } }; },{"../utils/promish":15,"../utils/utils":20,"fast-csv":125,"fs":93,"moment":176}],3:[function(require,module,exports){ /** * Copyright (c) 2014-2017 Guyon Roche * LICENCE: MIT - please refer to LICENCE file included with this module * or https://github.com/guyonroche/exceljs/blob/master/LICENSE */ 'use strict'; var colCache = require('../utils/col-cache'); var Enums = require('./enums'); var _require = require('../utils/shared-formula'), slideFormula = _require.slideFormula; // Cell requirements // Operate inside a worksheet // Store and retrieve a value with a range of types: text, number, date, hyperlink, reference, formula, etc. // Manage/use and manipulate cell format either as local to cell or inherited from column or row. var Cell = module.exports = function (row, column, address) { if (!row || !column) { throw new Error('A Cell needs a Row'); } this._row = row; this._column = column; colCache.validateAddress(address); this._address = address; // TODO: lazy evaluation of this._value this._value = Value.create(Cell.Types.Null, this); this.style = this._mergeStyle(row.style, column.style, {}); this._mergeCount = 0; }; Cell.Types = Enums.ValueType; Cell.prototype = { get worksheet() { return this._row.worksheet; }, get workbook() { return this._row.worksheet.workbook; }, // help GC by removing cyclic (and other) references destroy: function destroy() { delete this.style; delete this._value; delete this._row; delete this._column; delete this._address; }, // ========================================================================= // Styles stuff get numFmt() { return this.style.numFmt; }, set numFmt(value) { this.style.numFmt = value; }, get font() { return this.style.font; }, set font(value) { this.style.font = value; }, get alignment() { return this.style.alignment; }, set alignment(value) { this.style.alignment = value; }, get border() { return this.style.border; }, set border(value) { this.style.border = value; }, get fill() { return this.style.fill; }, set fill(value) { this.style.fill = value; }, _mergeStyle: function _mergeStyle(rowStyle, colStyle, style) { var numFmt = rowStyle && rowStyle.numFmt || colStyle && colStyle.numFmt; if (numFmt) style.numFmt = numFmt; var font = rowStyle && rowStyle.font || colStyle && colStyle.font; if (font) style.font = font; var alignment = rowStyle && rowStyle.alignment || colStyle && colStyle.alignment; if (alignment) style.alignment = alignment; var border = rowStyle && rowStyle.border || colStyle && colStyle.border; if (border) style.border = border; var fill = rowStyle && rowStyle.fill || colStyle && colStyle.fill; if (fill) style.fill = fill; return style; }, // ========================================================================= // return the address for this cell get address() { return this._address; }, get row() { return this._row.number; }, get col() { return this._column.number; }, get $col$row() { return '$' + this._column.letter + '$' + this.row; }, // ========================================================================= // Value stuff get type() { return this._value.type; }, get effectiveType() { return this._value.effectiveType; }, toCsvString: function toCsvString() { return this._value.toCsvString(); }, // ========================================================================= // Merge stuff addMergeRef: function addMergeRef() { this._mergeCount++; }, releaseMergeRef: function releaseMergeRef() { this._mergeCount--; }, get isMerged() { return this._mergeCount > 0 || this.type === Cell.Types.Merge; }, merge: function merge(master) { this._value.release(); this._value = Value.create(Cell.Types.Merge, this, master); this.style = master.style; }, unmerge: function unmerge() { if (this.type === Cell.Types.Merge) { this._value.release(); this._value = Value.create(Cell.Types.Null, this); this.style = this._mergeStyle(this._row.style, this._column.style, {}); } }, isMergedTo: function isMergedTo(master) { if (this._value.type !== Cell.Types.Merge) return false; return this._value.isMergedTo(master); }, get master() { if (this.type === Cell.Types.Merge) { return this._value.master; } return this; // an unmerged cell is its own master }, get isHyperlink() { return this._value.type === Cell.Types.Hyperlink; }, get hyperlink() { return this._value.hyperlink; }, // return the value get value() { return this._value.value; }, // set the value - can be number, string or raw set value(v) { // special case - merge cells set their master's value if (this.type === Cell.Types.Merge) { this._value.master.value = v; return; } this._value.release(); // assign value this._value = Value.create(Value.getType(v), this, v); }, get text() { return this._value.toString(); }, toString: function toString() { return this.text; }, _upgradeToHyperlink: function _upgradeToHyperlink(hyperlink) { // if this cell is a string, turn it into a Hyperlink if (this.type === Cell.Types.String) { this._value = Value.create(Cell.Types.Hyperlink, this, { text: this._value.value, hyperlink: hyperlink }); } }, // ========================================================================= // Formula stuff get formula() { return this._value.formula; }, get result() { return this._value.result; }, get formulaType() { return this._value.formulaType; }, // ========================================================================= // Name stuff get fullAddress() { var worksheet = this._row.worksheet; return { sheetName: worksheet.name, address: this.address, row: this.row, col: this.col }; }, get name() { return this.names[0]; }, set name(value) { this.names = [value]; }, get names() { return this.workbook.definedNames.getNamesEx(this.fullAddress); }, set names(value) { var self = this; var definedNames = this.workbook.definedNames; this.workbook.definedNames.removeAllNames(self.fullAddress); value.forEach(function (name) { definedNames.addEx(self.fullAddress, name); }); }, addName: function addName(name) { this.workbook.definedNames.addEx(this.fullAddress, name); }, removeName: function removeName(name) { this.workbook.definedNames.removeEx(this.fullAddress, name); }, removeAllNames: function removeAllNames() { this.workbook.definedNames.removeAllNames(this.fullAddress); }, // ========================================================================= // Data Validation stuff get _dataValidations() { return this.worksheet.dataValidations; }, get dataValidation() { return this._dataValidations.find(this.address); }, set dataValidation(value) { this._dataValidations.add(this.address, value); }, // ========================================================================= // Model stuff get model() { var model = this._value.model; model.style = this.style; return model; }, set model(value) { this._value.release(); this._value = Value.create(value.type, this); this._value.model = value; if (value.style) { this.style = value.style; } else { this.style = {}; } } }; // ============================================================================= // Internal Value Types var NullValue = function NullValue(cell) { this.model = { address: cell.address, type: Cell.Types.Null }; }; NullValue.prototype = { get value() { return null; }, set value(value) { // nothing to do }, get type() { return Cell.Types.Null; }, get effectiveType() { return Cell.Types.Null; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return ''; }, release: function release() {}, toString: function toString() { return ''; } }; var NumberValue = function NumberValue(cell, value) { this.model = { address: cell.address, type: Cell.Types.Number, value: value }; }; NumberValue.prototype = { get value() { return this.model.value; }, set value(value) { this.model.value = value; }, get type() { return Cell.Types.Number; }, get effectiveType() { return Cell.Types.Number; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return '' + this.model.value; }, release: function release() {}, toString: function toString() { return this.model.value.toString(); } }; var StringValue = function StringValue(cell, value) { this.model = { address: cell.address, type: Cell.Types.String, value: value }; }; StringValue.prototype = { get value() { return this.model.value; }, set value(value) { this.model.value = value; }, get type() { return Cell.Types.String; }, get effectiveType() { return Cell.Types.String; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return '"' + this.model.value.replace(/"/g, '""') + '"'; }, release: function release() {}, toString: function toString() { return this.model.value; } }; var RichTextValue = function RichTextValue(cell, value) { this.model = { address: cell.address, type: Cell.Types.String, value: value }; }; RichTextValue.prototype = { get value() { return this.model.value; }, set value(value) { this.model.value = value; }, toString: function toString() { return this.model.value.richText.map(function (t) { return t.text; }).join(''); }, get type() { return Cell.Types.RichText; }, get effectiveType() { return Cell.Types.RichText; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return '"' + this.text.replace(/"/g, '""') + '"'; }, release: function release() {} }; var DateValue = function DateValue(cell, value) { this.model = { address: cell.address, type: Cell.Types.Date, value: value }; }; DateValue.prototype = { get value() { return this.model.value; }, set value(value) { this.model.value = value; }, get type() { return Cell.Types.Date; }, get effectiveType() { return Cell.Types.Date; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return this.model.value.toISOString(); }, release: function release() {}, toString: function toString() { return this.model.value.toString(); } }; var HyperlinkValue = function HyperlinkValue(cell, value) { this.model = { address: cell.address, type: Cell.Types.Hyperlink, text: value ? value.text : undefined, hyperlink: value ? value.hyperlink : undefined }; }; HyperlinkValue.prototype = { get value() { return { text: this.model.text, hyperlink: this.model.hyperlink }; }, set value(value) { this.model.text = value.text; this.model.hyperlink = value.hyperlink; }, get text() { return this.model.text; }, set text(value) { this.model.text = value; }, get hyperlink() { return this.model.hyperlink; }, set hyperlink(value) { this.model.hyperlink = value; }, get type() { return Cell.Types.Hyperlink; }, get effectiveType() { return Cell.Types.Hyperlink; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return this.model.hyperlink; }, release: function release() {}, toString: function toString() { return this.model.text; } }; var MergeValue = function MergeValue(cell, master) { this.model = { address: cell.address, type: Cell.Types.Merge, master: master ? master.address : undefined }; this._master = master; if (master) { master.addMergeRef(); } }; MergeValue.prototype = { get value() { return this._master.value; }, set value(value) { if (value instanceof Cell) { if (this._master) { this._master.releaseMergeRef(); } value.addMergeRef(); this._master = value; } else { this._master.value = value; } }, isMergedTo: function isMergedTo(master) { return master === this._master; }, get master() { return this._master; }, get type() { return Cell.Types.Merge; }, get effectiveType() { return this._master.effectiveType; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return ''; }, release: function release() { this._master.releaseMergeRef(); }, toString: function toString() { return this.value.toString(); } }; var FormulaValue = function FormulaValue(cell, value) { this.cell = cell; this.model = { address: cell.address, type: Cell.Types.Formula, formula: value ? value.formula : undefined, sharedFormula: value ? value.sharedFormula : undefined, result: value ? value.result : undefined }; }; FormulaValue.prototype = { get value() { return this.model.formula ? { formula: this.model.formula, result: this.model.result } : { sharedFormula: this.model.sharedFormula, result: this.model.result }; }, set value(value) { this.model.formula = value.formula; this.model.sharedFormula = value.sharedFormula; this.model.result = value.result; }, validate: function validate(value) { switch (Value.getType(value)) { case Cell.Types.Null: case Cell.Types.String: case Cell.Types.Number: case Cell.Types.Date: break; case Cell.Types.Hyperlink: case Cell.Types.Formula: default: throw new Error('Cannot process that type of result value'); } }, get dependencies() { // find all the ranges and cells mentioned in the formula var ranges = this.formula.match(/([a-zA-Z0-9]+!)?[A-Z]{1,3}\d{1,4}:[A-Z]{1,3}\d{1,4}/g); var cells = this.formula.replace(/([a-zA-Z0-9]+!)?[A-Z]{1,3}\d{1,4}:[A-Z]{1,3}\d{1,4}/g, '').match(/([a-zA-Z0-9]+!)?[A-Z]{1,3}\d{1,4}/g); return { ranges: ranges, cells: cells }; }, get formula() { return this.model.formula || this._getTranslatedFormula(); }, set formula(value) { this.model.formula = value; }, get formulaType() { if (this.model.formula) { return Enums.FormulaType.Master; } if (this.model.sharedFormula) { return Enums.FormulaType.Shared; } return Enums.FormulaType.None; }, get result() { return this.model.result; }, set result(value) { this.model.result = value; }, get type() { return Cell.Types.Formula; }, get effectiveType() { var v = this.model.result; if (v === null || v === undefined) { return Enums.ValueType.Null; } else if (v instanceof String || typeof v === 'string') { return Enums.ValueType.String; } else if (typeof v === 'number') { return Enums.ValueType.Number; } else if (v instanceof Date) { return Enums.ValueType.Date; } else if (v.text && v.hyperlink) { return Enums.ValueType.Hyperlink; } else if (v.formula) { return Enums.ValueType.Formula; } return Enums.ValueType.Null; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, _getTranslatedFormula: function _getTranslatedFormula() { if (!this._translatedFormula && this.model.sharedFormula) { var worksheet = this.cell.worksheet; var master = worksheet.findCell(this.model.sharedFormula); this._translatedFormula = master && slideFormula(master.formula, master.address, this.model.address); } return this._translatedFormula; }, toCsvString: function toCsvString() { return '' + (this.model.result || ''); }, release: function release() {}, toString: function toString() { return this.model.result ? this.model.result.toString() : ''; } }; var SharedStringValue = function SharedStringValue(cell, value) { this.model = { address: cell.address, type: Cell.Types.SharedString, value: value }; }; SharedStringValue.prototype = { get value() { return this.model.value; }, set value(value) { this.model.value = value; }, get type() { return Cell.Types.SharedString; }, get effectiveType() { return Cell.Types.SharedString; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return '' + this.model.value; }, release: function release() {}, toString: function toString() { return this.model.value.toString(); } }; var BooleanValue = function BooleanValue(cell, value) { this.model = { address: cell.address, type: Cell.Types.Boolean, value: value }; }; BooleanValue.prototype = { get value() { return this.model.value; }, set value(value) { this.model.value = value; }, get type() { return Cell.Types.Boolean; }, get effectiveType() { return Cell.Types.Boolean; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return this.model.value ? 1 : 0; }, release: function release() {}, toString: function toString() { return this.model.value.toString(); } }; var ErrorValue = function ErrorValue(cell, value) { this.model = { address: cell.address, type: Cell.Types.Error, value: value }; }; ErrorValue.prototype = { get value() { return this.model.value; }, set value(value) { this.model.value = value; }, get type() { return Cell.Types.Error; }, get effectiveType() { return Cell.Types.Error; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return this.toString(); }, release: function release() {}, toString: function toString() { return this.model.value.error.toString(); } }; var JSONValue = function JSONValue(cell, value) { this.model = { address: cell.address, type: Cell.Types.String, value: JSON.stringify(value), rawValue: value }; }; JSONValue.prototype = { get value() { return this.model.rawValue; }, set value(value) { this.model.rawValue = value; this.model.value = JSON.stringify(value); }, get type() { return Cell.Types.String; }, get effectiveType() { return Cell.Types.String; }, get address() { return this.model.address; }, set address(value) { this.model.address = value; }, toCsvString: function toCsvString() { return this.model.value; }, release: function release() {}, toString: function toString() { return this.model.value; } }; // Value is a place to hold common static Value type functions var Value = { getType: function getType(value) { if (value === null || value === undefined) { return Cell.Types.Null; } else if (value instanceof String || typeof value === 'string') { return Cell.Types.String; } else if (typeof value === 'number') { return Cell.Types.Number; } else if (typeof value === 'boolean') { return Cell.Types.Boolean; } else if (value instanceof Date) { return Cell.Types.Date; } else if (value.text && value.hyperlink) { return Cell.Types.Hyperlink; } else if (value.formula || value.sharedFormula) { return Cell.Types.Formula; } else if (value.richText) { return Cell.Types.RichText; } else if (value.sharedString) { return Cell.Types.SharedString; } else if (value.error) { return Cell.Types.Error; } return Cell.Types.JSON; }, // map valueType to constructor types: [{ t: Cell.Types.Null, f: NullValue }, { t: Cell.Types.Number, f: NumberValue }, { t: Cell.Types.String, f: StringValue }, { t: Cell.Types.Date, f: DateValue }, { t: Cell.Types.Hyperlink, f: HyperlinkValue }, { t: Cell.Types.Formula, f: FormulaValue }, { t: Cell.Types.Merge, f: MergeValue }, { t: Cell.Types.JSON, f: JSONValue }, { t: Cell.Types.SharedString, f: SharedStringValue }, { t: Cell.Types.RichText, f: RichTextValue }, { t: Cell.Types.Boolean, f: BooleanValue }, { t: Cell.Types.Error, f: ErrorValue }].reduce(function (p, t) { p[t.t] = t.f;return p; }, []), create: function create(type, cell, value) { var T = this.types[type]; if (!T) { throw new Error('Could not create Value of type ' + type); } return new T(cell, value); } }; },{"../utils/col-cache":14,"../utils/shared-formula":16,"./enums":7}],4:[function(require,module,exports){ /** * Copyright (c) 2014-2017 Guyon Roche * LICENCE: MIT - please refer to LICENCE file included with this module * or https://github.com/guyonroche/exceljs/blob/master/LICENSE */ 'use strict'; var _ = require('../utils/under-dash'); var colCache = require('../utils/col-cache'); // Column defines the column properties for 1 column. // This includes header rows, widths, key, (style), etc. // Worksheet will condense the columns as appropriate during serialization var Column = module.exports = function (worksheet, number, defn) { this._worksheet = worksheet; this._number = number; if (defn !== false) { // sometimes defn will follow this.defn = defn; } }; Column.prototype = { get number() { return this._number; }, get worksheet() { return this._worksheet; }, get letter() { return colCache.n2l(this._number); }, get isCustomWidth() { return this.width !== undefined && this.width !== 8; }, get defn() { return { header: this._header, key: this.key, width: this.width, style: this.style, hidden: this.hidden, outlineLevel: this.outlineLevel }; }, set defn(value) { if (value) { this.key = value.key; this.width = value.width; this.outlineLevel = value.outlineLevel; if (value.style) { this.style = value.style; } else { this.style = {}; } // headers must be set after style this.header = value.header; this._hidden = !!value.hidden; } else { delete this._header; delete this.key; delete this.width; this.style = {}; this.outlineLevel = 0; } }, get headers() { return this._header && this._header instanceof Array ? this._header : [this._header]; }, get header() { return this._header; }, set header(value) { var _this = this; if (value !== undefined) { this._header = value; this.headers.forEach(function (text, index) { _this._worksheet.getCell(index + 1, _this.number).value = text; }); } else { this._header = []; } }, get key() { return this._key; }, set key(value) { var column = this._key && this._worksheet.getColumnKey(this._key); if (column === this) { this._worksheet.deleteColumnKey(this._key); } this._key = value; if (value) { this._worksheet.setColumnKey(this._key, this); } }, get hidden() { return !!this._hidden; }, set hidden(value) { this._hidden = value; }, get outlineLevel() { return this._outlineLevel || 0; }, set outlineLevel(value) { this._outlineLevel = value; }, get collapsed() { return !!(this._outlineLevel && this._outlineLevel >= this._worksheet.properties.outlineLevelCol); }, toString: function toString() { return JSON.stringify({ key: this.key, width: this.width, headers: this.headers.length ? this.headers : undefined }); }, equivalentTo: function equivalentTo(other) { return this.width === other.width && this.hidden === other.hidden && this.outlineLevel === other.outlineLevel && _.isEqual(this.style, other.style); }, get isDefault() { if (this.isCustomWidth) { return false; } if (this.hidden) { return false; } if (this.outlineLevel) { return false; } var s = this.style; if (s && (s.font || s.numFmt || s.alignment || s.border || s.fill)) { return false; } return true; }, get headerCount() { return this.headers.length; }, eachCell: function eachCell(options, iteratee) { var colNumber = this.number; if (!iteratee) { iteratee = options; options = null; } if (options && options.includeEmpty) { this._worksheet.eachRow(options, function (row, rowNumber) { iteratee(row.getCell(colNumber), rowNumber); }); } else { this._worksheet.eachRow(function (row, rowNumber) { var cell = row.findCell(colNumber); if (cell) { iteratee(cell, rowNumber); } }); } }, // ========================================================================= // styles _applyStyle: function _applyStyle(name, value) { this.style[name] = value; this.eachCell(function (cell) { cell[name] = value; }); return value; }, get numFmt() { return this.style.numFmt; }, set numFmt(value) { this._applyStyle('numFmt', value); }, get font() { return this.style.font; }, set font(value) { this._applyStyle('font', value); }, get alignment() { return this.style.alignment; }, set alignment(value) { this._applyStyle('alignment', value); }, get border() { return this.style.border; }, set border(value) { this._applyStyle('border', value); }, get fill() { return this.style.fill; }, set fill(value) { this._applyStyle('fill', value); } }; // ============================================================================= // static functions Column.toModel = function (columns) { // Convert array of Column into compressed list cols var cols = []; var col = null; if (columns) { columns.forEach(function (column, index) { if (column.isDefault) { if (col) { col = null; } } else if (!col || !column.equivalentTo(col)) { col = { min: index + 1, max: index + 1, width: column.width, style: column.style, isCustomWidth: column.isCustomWidth, hidden: column.hidden, outlineLevel: column.outlineLevel, collapsed: column.collapsed }; cols.push(col); } else { col.max = index + 1; } }); } return cols.length ? cols : undefined; }; Column.fromModel = function (worksheet, cols) { cols = cols || []; var columns = []; var count = 1; var index = 0; while (index < cols.length) { var col = cols[index++]; while (count < col.min) { columns.push(new Column(worksheet, count++)); } while (count <= col.max) { columns.push(new Column(worksheet, count++, col)); } } return columns.length ? columns : null; }; },{"../utils/col-cache":14,"../utils/under-dash":19}],5:[function(require,module,exports){ /** * Copyright (c) 2016-2017 Guyon Roche * LICENCE: MIT - please refer to LICENCE file included with this module * or https://github.com/guyonroche/exceljs/blob/master/LICENSE */ 'use strict'; var DataValidations = module.exports = function (model) { this.model = model || {}; }; DataValidations.prototype = { add: function add(address, validation) { return this.model[address] = validation; }, find: function find(address) { return this.model[address]; }, remove: function remove(address) { this.model[address] = undefined; } }; },{}],6:[function(require,module,exports){ /** * Copyright (c) 2016-2017 Guyon Roche * LICENCE: MIT - please refer to LICENCE file included with this module * or https://github.com/guyonroche/exceljs/blob/master/LICENSE */ 'use strict'; var _ = require('../utils/under-dash'); var colCache = require('../utils/col-cache'); var CellMatrix = require('../utils/cell-matrix'); var Range = require('./range'); var rangeRegexp = /[$](\w+)[$](\d+)(:[$](\w+)[$](\d+))?/; var DefinedNames = module.exports = function () { this.matrixMap = {}; }; DefinedNames.prototype = { getMatrix: function getMatrix(name) { return this.matrixMap[name] || (this.matrixMap[name] = new CellMatrix()); }, // add a name to a cell. locStr in the form SheetName!$col$row or SheetName!$c1$r1:$c2:$r2 add: function add(locStr, name) { var location = colCache.decodeEx(locStr); this.addEx(location, name); }, addEx: function addEx(location, name) { var matrix = this.getMatrix(name); if (location.top) { for (var col = location.left; col <= location.right; col++) { for (var row = location.top; row <= location.bottom; row++) { var address = { sheetName: location.sheetName, address: colCache.n2l(col) + row, row: row, col: col }; matrix.addCellEx(address); } } } else { matrix.addCellEx(location); } }, remove: function remove(locStr, name) { var location = colCache.decodeEx(locStr); this.removeEx(location, name); }, removeEx: function removeEx(location, name) { var matrix = this.getMatrix(name); matrix.removeCellEx(location); }, removeAllNames: function removeAllNames(location) { _.each(this.matrixMap, function (matrix) { matrix.removeCellEx(location); }); }, forEach: function forEach(callback) { _.each(this.matrixMap, function (matrix, name) { matrix.forEach(function (cell) { callback(name, cell); }); }); }, // get all the names of a cell getNames: function getNames(addressStr) { return this.getNamesEx(colCache.decodeEx(addressStr)); }, getNamesEx: function getNamesEx(address) { return _.map(this.matrixMap, function (matrix, name) { return matrix.findCellEx(address) && name; }).filter(Boolean); }, _explore: function _explore(matrix, cell) { cell.mark = false; var sheetName = cell.sheetName; var range = new Range(cell.row, cell.col, cell.row, cell.col, sheetName); var x, y; // grow vertical - only one col to worry about function vGrow(yy, edge) { var c = matrix.findCellAt(sheetName, yy, cell.col); if (!c || !c.mark) { return false; } range[edge] = yy; c.mark = false; return true; } for (y = cell.row - 1; vGrow(y, 'top'); y--) {} for (y = cell.row + 1; vGrow(y, 'bottom'); y++) {} // grow horizontal - ensure all rows can grow function hGrow(xx, edge) { var c, cells = []; for (y = range.top; y <= range.bottom; y++) { c = matrix.findCellAt(sheetName, y, xx); if (c && c.mark) { cells.push(c); } else { return false; } } range[edge] = xx; for (var i = 0; i < cells.length; i++) { cells[i].mark = false; } return true; } for (x = cell.col - 1; hGrow(x, 'left'); x--) {} for (x = cell.col + 1; hGrow(x, 'right'); x++) {} return range; }, getRanges: function getRanges(name, matrix) { var _this = this; matrix = matrix || this.matrixMap[name]; if (!matrix) { return { name: name, ranges: [] }; } // mark and sweep! matrix.forEach(function (cell) { cell.mark = true; }); var ranges = matrix.map(function (cell) { return cell.mark && _this._explore(matrix, cell); }).filter(Boolean).map(function (range) { return range.$shortRange; }); return { name: name, ranges: ranges }; }, get model() { var self = this; // To get names per cell - just iterate over all names finding cells if they exist return _.map(this.matrixMap, function (matrix, name) { return self.getRanges(name, matrix); }).filter(function (definedName) { return definedName.ranges.length; }); }, set model(value) { // value is [ { name, ranges }, ... ] var matrixMap = this.matrixMap = {}; value.forEach(function (definedName) { var matrix = matrixMap[definedName.name] = new CellMatrix(); definedName.ranges.forEach(function (rangeStr) { if (rangeRegexp.test(rangeStr.split('!').pop() || '')) { matrix.addCell(rangeStr); } }); }); } }; },{"../utils/cell-matrix":13,"../utils/col-cache":14,"../utils/under-dash":19,"./range":8}],7:[function(require,module,exports){ /** * Copyright (c) 2016-2017 Guyon Roche * LICENCE: MIT - please refer to LICENCE file included with this module * or https://github.com/guyonroche/exceljs/blob/master/LICENSE */ 'use strict'; module.exports = { ValueType: { Null: 0, Merge: 1, Number: 2, String: 3, Date: 4, Hyperlink: 5, Formula: 6, SharedString: 7, RichText: 8, Boolean: 9, Error: 10 }, FormulaType: { None: 0, Master: 1, Shared: 2 }, RelationshipType: { None: 0, OfficeDocument: 1, Worksheet: 2, CalcChain: 3, SharedStrings: 4, Styles: 5, Theme: 6, Hyperlink: 7 }, DocumentType: { Xlsx: 1 }, ReadingOrder: { LeftToRight: 1, RightToLeft: 2 }, ErrorValue: { NotApplicable: '#N/A', Ref: '#REF!', Name: '#NAME?', DivZero: '#DIV/0!', Null: '#NULL!', Value: '#VALUE!', Num: '#NUM!' } }; },{}],8:[function(require,module,exports){ /** * Copyright (c) 2014-2017 Guyon Roche * LICENCE: MIT - please refer to LICENCE file included with this module * or https://github.com/guyonroche/exceljs/blob/master/LICENSE */ 'use strict'; var colCache = require('./../utils/col-cache'); // used by worksheet to calculate sheet dimensions var Range = module.exports = function () { this.decode(arguments); }; Range.prototype = { _set_tlbr: function _set_tlbr(t, l, b, r, s) { this.model = { top: Math.min(t, b), left: Math.min(l, r), bottom: Math.max(t, b), right: Math.max(l, r), sheetName: s }; }, _set_tl_br: function _set_tl_br(tl, br, s) { tl = colCache.decodeAddress(tl); br = colCache.decodeAddress(br); this._set_tlbr(tl.row, tl.col, br.row, br.col, s); }, decode: function decode(argv) { switch (argv.length) { case 5: // [t,l,b,r,s] this._set_tlbr(argv[0], argv[1], argv[2], argv[3], argv[4]); break; case 4: // [t,l,b,r] this._set_tlbr(argv[0], argv[1], argv[2], argv[3]); break; case 3: // [tl,br,s] this._set_tl_br(argv[0], argv[1], argv[2]); break; case 2: // [tl,br] this._set_tl_br(argv[0], argv[1]); break; case 1: var value = argv[0]; if (value instanceof Range) { // copy constructor this.model = { top: value.model.top, left: value.model.left, bottom: value.model.bottom, right: value.model.right, sheetName: value.sheetName }; } else if (value instanceof Array) { // an arguments array this.decode(value); } else if (value.top && value.left && value.bottom && value.right) { // a model this.model = { top: value.top, left: value.left, bottom: value.bottom, right: value.right, sheetName: value.sheetName }; } else { // [sheetName!]tl:br var tlbr = colCache.decodeEx(value); if (tlbr.top) { this.model = { top: tlbr.top, left: tlbr.left, bottom: tlbr.bottom, right: tlbr.right, sheetName: tlbr.sheetName }; } else { this.model = { top: tlbr.row, left: tlbr.col, bottom: tlbr.row, right: tlbr.col, sheetName: tlbr.sheetName }; } } break; case 0: this.model = { top: 0, left: 0, bottom: 0, right: 0 }; break; default: throw new Error('Invalid number of arguments to _getDimensions() - ' + argv.length); } }, get top() { return this.model.top || 1; }, set top(value) { this.model.top = value; }, get left() { return this.model.left || 1; }, set left(value) { this.model.left = value; }, get bottom() { return this.model.bottom || 1; }, set bottom(value) { this.model.bottom = value; }, get right() { return this.model.right || 1; }, set right(value) { this.model.right = value; }, get sheetName() { return this.model.sheetName; }, set sheetName(value) { this.model.sheetName = value; }, get _serialisedSheetName() { var sheetName = this.model.sheetName; if (sheetName) { if (/^[a-zA-Z0-9]*$/.test(sheetName)) { return sheetName + '!'; } return '\'' + sheetName + '\'!'; } return ''; }, expand: function expand(top, left, bottom, right) { if (!this.model.top || top < this.top) this.top = top; if (!this.model.left || left < this.left) this.left = left; if (!this.model.bottom || bottom > this.bottom) this.bottom = bottom; if (!this.model.right || right > this.right) this.right = right; }, expandRow: function expandRow(row) { if (row) { var dimensions = row.dimensions; if (dimensions) { this.expand(row.number, dimensions.min, row.number, dimensions.max); } } }, expandToAddress: function expandToAddress(addressStr) { var address = colCache.decodeEx(addressStr); this.expand(address.row, address.col, address.row, address.col); }, get tl() { return colCache.n2l(this.left) + this.top; }, get $t$l() { return '$' + colCache.n2l(this.left) + '$' + this.top; }, get br() { return colCache.n2l(this.right) + this.bottom; }, get $b$r() { return '$' + colCache.n2l(this.right) + '$' + this.bottom; }, get range() { return this._serialisedSheetName + this.tl + ':' + this.br; }, get $range() { return this._serialisedSheetName + this.$t$l + ':' + this.$b$r; }, get shortRange() { return this.count > 1 ? this.range : this._serialisedSheetName + this.tl; }, get $shortRange() { return this.count > 1 ? this.$range : this._serialisedSheetName + this.$t$l; }, get count() { return (1 + this.bottom - this.top) * (1 + this.right - this.left); }, toString: function toString() { return this.range; }, intersects: function intersects(other) { if (other.sheetName && this.sheetName && other.sheetName !== this.sheetName) return false; if (other.bottom < this.top) return false; if (other.top > this.bottom) return false; if (other.right < this.left) return false; if (other.left > this.right) return false; return true; }, contains: function contains(addressStr) { var address = colCache.decodeEx(addressStr); return this.containsEx(address); }, containsEx: function containsEx(address) { if (address.sheetName && this.sheetName && address.sheetName !== this.sheetName) return false; return address.row >= this.top && address.row <= this.bottom && address.col >= this.left && address.col <= this.right; } }; },{"./../utils/col-cache":14}],9:[function(require,module,exports){ /** * Copyright (c) 2014-2017 Guyon Roche * LICENCE: MIT - please refer to LICENCE file included with this module * or https://github.com/guyonroche/exceljs/blob/master/LICENSE */ 'use strict'; var _ = require('../utils/under-dash'); var Enums = require('./enums'); var colCache = require('./../utils/col-cache'); var Cell = require('./cell'); var Row = module.exports = function (worksheet, number) { this._worksheet = worksheet; this._number = number; this._cells = []; this.style = {}; this.outlineLevel = 0; }; Row.prototype = { // return the row number get number() { return this._number; }, get worksheet() { return this._worksheet; }, // Inform Streaming Writer that this row (and all rows before it) are complete // and ready to write. Has no effect on Worksheet document commit: function commit() { this._worksheet._commitRow(this); // eslint-disable-line no-underscore-dangle }, // helps GC by breaking cyclic references destroy: function destroy() { delete this._worksheet; delete this._cells; delete this.style; }, findCell: function findCell(colNumber) { return this._cells[colNumber - 1]; }, // given {address, row, col}, find or create new cell getCellEx: function getCellEx(address) { var cell = this._cells[address.col - 1]; if (!cell) { var column = this._worksheet.getColumn(address.col); cell = new Cell(this, column, address.address); this._cells[address.col - 1] = cell; } return cell; }, // get cell by key, letter or column number getCell: function getCell(col) { if (typeof col === 'string') { // is it a key? var column = this._worksheet.getColumnKey(col); if (column) { col = column.number; } else { col = colCache.l2n(col); } } return this._cells[col - 1] || this.getCellEx({ address: colCache.encodeAddress(this._number, col), row: this._number, col: col }); }, // remove cell(s) and shift all higher cells down by count splice: function splice(start, count) { var inserts = Array.prototype.slice.call(arguments, 2); var nKeep = start + count; var nExpand = inserts.length - count; var nEnd = this._cells.length; var i, cSrc, cDst; if (nExpand < 0) { // remove cells for (i = nKeep; i <= nEnd; i++) { cSrc = this._cells[i - 1]; if (cSrc) { this.getCell(i + nExpand).value = cSrc.value; cSrc.value = null; } else { cDst = this._cells[i + nExpand - 1]; if (cDst) { cDst.value = null; } } } } else if (nExpand > 0) { // insert new cells for (i = nEnd; i >= nKeep; i--) { cSrc = this._cells[i - 1]; if (cSrc) { this.getCell(i + nExpand).value = cSrc.value; } else { this._cells[i + nExpand - 1] = undefined; } } } // now add the new values for (i = 0; i < inserts.length; i++) { this.getCell(start + i).value = inserts[i]; } }, // Iterate over all non-null cells in this row eachCell: function eachCell(options, iteratee) { if (!iteratee) { iteratee = options; options = null; } if (opt