diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 000000000..99c975c29 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,26 @@ +{ + "curly": true, + "eqeqeq": true, + "immed": true, + "newcap": true, + "noarg": true, + "undef": true, + "unused": false, + "node": true , + "bitwise": true, + "indent": 2, + "noempty": true, + "quotmark": "single", + "strict": true, + "trailing": true, + "forin": true, + "camelcase": false, + "jasmine": true, + "latedef": true, + "globals": { + "describe": false, + "it": false, + "unescape": false + }, + "esnext": true +} \ No newline at end of file diff --git a/lib/doc/defined-names.js b/lib/doc/defined-names.js index a26ae6e0a..f75f6f08b 100644 --- a/lib/doc/defined-names.js +++ b/lib/doc/defined-names.js @@ -61,6 +61,10 @@ DefinedNames.prototype = { } }, + remove: function(locStr, name) { + var location = colCache.decodeEx(locStr); + this.removeEx(location, name); + }, removeEx: function(location, name) { var matrix = this.getMatrix(name); matrix.removeCellEx(location); @@ -132,16 +136,13 @@ DefinedNames.prototype = { return dimensions; }, - get model() { + getRanges: function(name, matrix) { var self = this; + matrix = matrix || this.matrixMap[name]; - // Rethink! - // Have cell-matrix per name! Easy to serialise - // To get names per cell - just iterate over all names finding cells if they exist - return _.map(this.matrixMap, function(matrix, name) { - // mark and sweep! - matrix.forEach(function(cell) { cell.mark = true; }); - var ranges = matrix.map(function(cell) { + // mark and sweep! + matrix.forEach(function(cell) { cell.mark = true; }); + var ranges = matrix.map(function(cell) { if (cell.mark) { var dimensions = self._explore(matrix, cell); var range = cell.sheetName + '!' + (dimensions.count > 1 ? dimensions.$range : dimensions.$t$l); @@ -150,9 +151,16 @@ DefinedNames.prototype = { }) .filter(function(range) { return range; }); - return { - name: name, ranges: ranges - }; + 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); }); }, set model(value) { diff --git a/lib/stream/xlsx/workbook-reader.js b/lib/stream/xlsx/workbook-reader.js index a0e67015a..093d686fe 100644 --- a/lib/stream/xlsx/workbook-reader.js +++ b/lib/stream/xlsx/workbook-reader.js @@ -1,229 +1,241 @@ /** * Copyright (c) 2015 Guyon Roche - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal + * of this software and associated documentation files (the 'Software'), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. - * + * */ -"use strict"; - -var fs = require("fs"); -var events = require("events"); -var Stream = require("stream"); -var Promise = require("bluebird"); -var _ = require("underscore"); -var unzip = require("unzip"); -var Sax = require("sax"); - -var utils = require("../../utils/utils"); -var Enums = require("../../doc/enums"); -var StreamBuf = require("../../utils/stream-buf"); -var StutteredPipe = require("../../utils/stuttered-pipe"); -var FlowControl = require("../../utils/flow-control"); -var AutoDrain = require("../../utils/auto-drain"); - -var RelType = require("../../xlsx/rel-type"); -var StyleManager = require("../../xlsx/stylemanager"); -var SharedStrings = require("../../utils/shared-strings"); - -var WorksheetReader = require("./worksheet-reader"); -var HyperlinkReader = require("./hyperlink-reader"); +'use strict'; + +var fs = require('fs'); +var events = require('events'); +var Stream = require('stream'); +//var Bluebird = require('bluebird'); +var _ = require('underscore'); +var unzip = require('unzip'); +var Sax = require('sax'); + +var utils = require('../../utils/utils'); +//var Enums = require('../../doc/enums'); +//var StreamBuf = require('../../utils/stream-buf'); +//var StutteredPipe = require('../../utils/stuttered-pipe'); +var FlowControl = require('../../utils/flow-control'); +//var AutoDrain = require('../../utils/auto-drain'); + +//var RelType = require('../../xlsx/rel-type'); +var StyleManager = require('../../xlsx/stylemanager'); +//var SharedStrings = require('../../utils/shared-strings'); + +var WorksheetReader = require('./worksheet-reader'); +var HyperlinkReader = require('./hyperlink-reader'); var WorkbookReader = module.exports = function(options) { - this.options = options = options || {}; - - // until we actually parse a styles.xml file, just assume we're not handling styles - // (but we do need to handle dates) - this.styles = new StyleManager.Mock(); - - // worksheet readers, indexed by sheetNo - this.worksheetReaders = {}; - - // hyperlink readers, indexed by sheetNo - this.hyperlinkReaders = {}; - - // count the open readers - this.readers = 0; - - // end of stream check - this.atEnd = false; -} + this.options = options = options || {}; + + // until we actually parse a styles.xml file, just assume we're not handling styles + // (but we do need to handle dates) + this.styles = new StyleManager.Mock(); + + // worksheet readers, indexed by sheetNo + this.worksheetReaders = {}; + + // hyperlink readers, indexed by sheetNo + this.hyperlinkReaders = {}; + + // count the open readers + this.readers = 0; + + // end of stream check + this.atEnd = false; +}; utils.inherits(WorkbookReader, events.EventEmitter, { - _getStream: function(input) { - if (input instanceof Stream.Readable) { - return input; - } - if (_.isString(input)) { - return fs.createReadStream(input); - } - throw new Error("Could not recognise input"); - }, - - get flowControl() { - if (!this._flowControl) { - this._flowControl = new FlowControl(this.options); - } - return this._flowControl; - }, - - options: { - entries: ["emit"], - sharedStrings: ["cache", "emit"], - styles: ["cache"], - hyperlinks: ["cache", "emit"], - worksheets: ["emit"] - }, - read: function(input, options) { - var self = this; - var stream = this.stream = this._getStream(input); - var zip = this.zip = unzip.Parse(); - - zip.on('entry',function (entry) { - switch(entry.path) { - case "_rels/.rels": - case "xl/workbook.xml": - case "xl/_rels/workbook.xml.rels": - entry.autodrain(); - break; - case "xl/sharedStrings.xml": - self._parseSharedStrings(entry, options); - break; - case "xl/styles.xml": - self._parseStyles(entry, options); - break; - default: - if (entry.path.match(/xl\/worksheets\/sheet\d+\.xml/)) { - var match = entry.path.match(/xl\/worksheets\/sheet(\d+)\.xml/) - var sheetNo = match[1]; - self._parseWorksheet(entry, sheetNo, options); - } else if (entry.path.match(/xl\/worksheets\/_rels\/sheet\d+\.xml.rels/)) { - var match = entry.path.match(/xl\/worksheets\/_rels\/sheet(\d+)\.xml.rels/) - var sheetNo = match[1]; - self._parseHyperlinks(entry, sheetNo, options); - } else { - entry.autodrain(); - } - break; - } - }); - stream.on('close', function () { - self.emit("end"); - self.atEnd = true; - if (!self.readers) { - self.emit("finished"); - } - }); - - // Pipe stream into top flow-control - this.flowControl.pipe(zip); - stream.pipe(this.flowControl); - }, - _emitEntry: function(options, payload) { - if (options.entries === "emit") { - this.emit("entry", payload); - } - }, - _parseSharedStrings: function(entry, options) { - this._emitEntry(options, {type: "shared-strings"}); - var self = this; - var sharedStrings = null; - switch(options.sharedStrings) { - case "cache": - sharedStrings = this.sharedStrings = []; - break; - case "emit": - break; - default: - entry.autodrain(); - return; - } - - var parser = Sax.createStream(true, {}); - var inT = false; - var t = null; - var index = 0; - var sharedStrings = []; - parser.on('opentag', function(node) { - if (node.name == "t") { - t = null; - inT = true; - } - }); - parser.on('closetag', function (name) { - if (inT && (name == "t")) { - if (sharedStrings) { - sharedStrings.push(t); - } else { - self.emit("shared-string", { index: index++, text: t}); - } - t = null; - } - }); - parser.on('text', function (text) { - t = t ? t + text : text; - }); - parser.on('error', function (error) { - self.emit('error', error); - }); - entry.pipe(parser); - }, - _parseStyles: function(entry, options) { - var self = this; - this._emitEntry(options, {type: "styles"}); - if (options.styles !== "cache") { + _getStream: function(input) { + if (input instanceof Stream.Readable) { + return input; + } + if (_.isString(input)) { + return fs.createReadStream(input); + } + throw new Error('Could not recognise input'); + }, + + get flowControl() { + if (!this._flowControl) { + this._flowControl = new FlowControl(this.options); + } + return this._flowControl; + }, + + options: { + entries: ['emit'], + sharedStrings: ['cache', 'emit'], + styles: ['cache'], + hyperlinks: ['cache', 'emit'], + worksheets: ['emit'] + }, + read: function(input, options) { + var self = this; + var stream = this.stream = this._getStream(input); + var zip = this.zip = unzip.Parse(); + + zip.on('entry',function (entry) { + console.log(entry.path) + var match, sheetNo; + switch(entry.path) { + case '_rels/.rels': + case 'xl/workbook.xml': + case 'xl/_rels/workbook.xml.rels': + entry.autodrain(); + break; + case 'xl/sharedStrings.xml': + self._parseSharedStrings(entry, options); + break; + case 'xl/styles.xml': + self._parseStyles(entry, options); + break; + default: + if (entry.path.match(/xl\/worksheets\/sheet\d+\.xml/)) { + match = entry.path.match(/xl\/worksheets\/sheet(\d+)\.xml/) + sheetNo = match[1]; + self._parseWorksheet(entry, sheetNo, options); + } else if (entry.path.match(/xl\/worksheets\/_rels\/sheet\d+\.xml.rels/)) { + match = entry.path.match(/xl\/worksheets\/_rels\/sheet(\d+)\.xml.rels/) + sheetNo = match[1]; + self._parseHyperlinks(entry, sheetNo, options); + } else { entry.autodrain(); - return; - } - this.styles = new StyleManager(); - this.styles.parse(entry); - }, - _getReader: function(Type, collection, sheetNo) { - var self = this; - var reader = collection[sheetNo]; - if (!reader) { - reader = new Type(this, sheetNo); - self.readers++; - reader.on("finished", function() { - if (!--self.readers) { - if (self.atEnd) { - self.emit("finished"); - } - } - }); - collection[sheetNo] = reader; + } + break; + } + }); + zip.on('finished', function() { + console.log('on close') + self.emit('end'); + self.atEnd = true; + if (!self.readers) { + self.emit('finished'); } - return reader; - }, - _parseWorksheet: function(entry, sheetNo, options) { - this._emitEntry(options, {type: "worksheet", id: sheetNo}); - var worksheetReader = this._getReader(WorksheetReader, this.worksheetReaders, sheetNo); - if (options.worksheets === "emit") { - this.emit("worksheet", worksheetReader); + }); + //stream.on('close', function () { + // console.log('on close') + // self.emit('end'); + // self.atEnd = true; + // if (!self.readers) { + // self.emit('finished'); + // } + //}); + + // Pipe stream into top flow-control + this.flowControl.pipe(zip); + stream.pipe(this.flowControl); + }, + _emitEntry: function(options, payload) { + if (options.entries === 'emit') { + this.emit('entry', payload); + } + }, + _parseSharedStrings: function(entry, options) { + this._emitEntry(options, {type: 'shared-strings'}); + var self = this; + var sharedStrings = null; + switch(options.sharedStrings) { + case 'cache': + sharedStrings = this.sharedStrings = []; + break; + case 'emit': + break; + default: + entry.autodrain(); + return; + } + + var parser = Sax.createStream(true, {}); + var inT = false; + var t = null; + var index = 0; + sharedStrings = []; + parser.on('opentag', function(node) { + if (node.name === 't') { + t = null; + inT = true; + } + }); + parser.on('closetag', function (name) { + if (inT && (name === 't')) { + if (sharedStrings) { + sharedStrings.push(t); + } else { + self.emit('shared-string', { index: index++, text: t}); } - worksheetReader.read(entry, options, this.hyperlinkReaders[sheetNo]); - }, - _parseHyperlinks: function(entry, sheetNo, options) { - this._emitEntry(options, {type: "hyerlinks", id: sheetNo}); - var hyperlinksReader = this._getReader(HyperlinkReader, this.hyperlinkReaders, sheetNo); - if (options.hyperlinks === "emit") { - this.emit("hyperlinks", hyperlinksReader); + t = null; + } + }); + parser.on('text', function (text) { + t = t ? t + text : text; + }); + parser.on('error', function (error) { + self.emit('error', error); + }); + entry.pipe(parser); + }, + _parseStyles: function(entry, options) { + var self = this; + this._emitEntry(options, {type: 'styles'}); + if (options.styles !== 'cache') { + entry.autodrain(); + return; + } + this.styles = new StyleManager(); + this.styles.parse(entry); + }, + _getReader: function(Type, collection, sheetNo) { + var self = this; + var reader = collection[sheetNo]; + if (!reader) { + reader = new Type(this, sheetNo); + self.readers++; + reader.on('finished', function() { + if (!--self.readers) { + if (self.atEnd) { + self.emit('finished'); + } } - hyperlinksReader.read(entry, options); + }); + collection[sheetNo] = reader; + } + return reader; + }, + _parseWorksheet: function(entry, sheetNo, options) { + this._emitEntry(options, {type: 'worksheet', id: sheetNo}); + var worksheetReader = this._getReader(WorksheetReader, this.worksheetReaders, sheetNo); + console.log('found worksheet', sheetNo) + if (options.worksheets === 'emit') { + this.emit('worksheet', worksheetReader); + } + worksheetReader.read(entry, options, this.hyperlinkReaders[sheetNo]); + }, + _parseHyperlinks: function(entry, sheetNo, options) { + this._emitEntry(options, {type: 'hyerlinks', id: sheetNo}); + var hyperlinksReader = this._getReader(HyperlinkReader, this.hyperlinkReaders, sheetNo); + if (options.hyperlinks === 'emit') { + this.emit('hyperlinks', hyperlinksReader); } + hyperlinksReader.read(entry, options); + } }); diff --git a/lib/stream/xlsx/worksheet-reader.js b/lib/stream/xlsx/worksheet-reader.js index 385c2dc3e..b3500dc58 100644 --- a/lib/stream/xlsx/worksheet-reader.js +++ b/lib/stream/xlsx/worksheet-reader.js @@ -1,326 +1,326 @@ /** * Copyright (c) 2015 Guyon Roche - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal + * of this software and associated documentation files (the 'Software'), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. - * + * */ -"use strict"; +'use strict'; -var fs = require("fs"); -var events = require("events"); -var Promise = require("bluebird"); -var _ = require("underscore"); -var Sax = require("sax"); +var fs = require('fs'); +var events = require('events'); +//var Bluebird = require('bluebird'); +//var _ = require('underscore'); +var Sax = require('sax'); -var utils = require("../../utils/utils"); -var colCache = require("../../utils/col-cache"); -var Enums = require("../../doc/enums"); -var Dimensions = require("../../utils/dimensions"); +var utils = require('../../utils/utils'); +var colCache = require('../../utils/col-cache'); +//var Enums = require('../../doc/enums'); +var Dimensions = require('../../utils/dimensions'); -var Row = require("../../doc/row"); -var Column = require("../../doc/column"); +var Row = require('../../doc/row'); +var Column = require('../../doc/column'); var WorksheetReader = module.exports = function(workbook, id) { - this.workbook = workbook; - this.id = id; - - // and a name - this.name = "Sheet" + this.id; - - // column definitions - this._columns = null; - this._keys = {}; - - // keep a record of dimensions - this._dimensions = new Dimensions(); -} + this.workbook = workbook; + this.id = id; + + // and a name + this.name = 'Sheet' + this.id; + + // column definitions + this._columns = null; + this._keys = {}; + + // keep a record of dimensions + this._dimensions = new Dimensions(); +}; utils.inherits(WorksheetReader, events.EventEmitter, { - // destroy - not a valid operation for a streaming writer - // even though some streamers might be able to, it's a bad idea. - destroy: function() { - throw new Error("Invalid Operation: destroy"); - }, - - // return the current dimensions of the writer - get dimensions() { - return this._dimensions; - }, - - // ========================================================================= - // Columns - - // get the current columns array. - get columns() { - return this._columns; - }, - - // get a single column by col number. If it doesn't exist, it and any gaps before it - // are created. - getColumn: function(c) { - if (typeof c == "string"){ - // if it matches a key'd column, return that - var col = this._keys[c]; - if (col) return col; - - // otherise, assume letter - c = colCache.l2n(c); - } - if (!this._columns) { this._columns = []; } - if (c > this._columns.length) { - var n = this._columns.length + 1; - while (n <= c) { - this._columns.push(new Column(this, n++)); + // destroy - not a valid operation for a streaming writer + // even though some streamers might be able to, it's a bad idea. + destroy: function() { + throw new Error('Invalid Operation: destroy'); + }, + + // return the current dimensions of the writer + get dimensions() { + return this._dimensions; + }, + + // ========================================================================= + // Columns + + // get the current columns array. + get columns() { + return this._columns; + }, + + // get a single column by col number. If it doesn't exist, it and any gaps before it + // are created. + getColumn: function(c) { + if (typeof c === 'string'){ + // if it matches a key'd column, return that + var col = this._keys[c]; + if (col) { return col; } + + // otherise, assume letter + c = colCache.l2n(c); + } + if (!this._columns) { this._columns = []; } + if (c > this._columns.length) { + var n = this._columns.length + 1; + while (n <= c) { + this._columns.push(new Column(this, n++)); + } + } + return this._columns[c-1]; + }, + + // ========================================================================= + // Read + + _emitRow: function(row) { + var self = this; + this.emit('row', row); + }, + + read: function(entry, options, hyperlinkReader) { + var self = this; + + var emitSheet = false; + var prepSheet = false; + var emitHyperlinks = false; + var hyperlinks = null; + switch (options.worksheets) { + case 'emit': + emitSheet = true; + break; + case 'prep': + prepSheet = true; + break; + } + switch(options.hyperlinks) { + case 'emit': + emitHyperlinks = true; + break; + case 'cache': + this.hyperlinks = hyperlinks = {}; + break; + } + if (!emitSheet && !emitHyperlinks && !hyperlinks) { + entry.autodrain(); + return; + } + + // references + var sharedStrings = this.workbook.sharedStrings; + var styles = this.workbook.styles; + + // xml position + var inCols = false; + var inRows = false; + var inHyperlinks = false; + + // parse state + var cols = null; + var row = null; + var c = null; + var current = null; + + var parser = Sax.createStream(true, {}); + parser.on('opentag', function(node) { + if (emitSheet) { + switch (node.name) { + case 'cols': + inCols = true; + cols = []; + break; + case 'sheetData': + inRows = true; + break; + + case 'col': + if (inCols) { + cols.push({ + min: parseInt(node.attributes.min), + max: parseInt(node.attributes.max), + width: parseFloat(node.attributes.width), + styleId: parseInt(node.attributes.style || '0') + }); } - } - return this._columns[c-1]; - }, - - // ========================================================================= - // Read - - _emitRow: function(row) { - var self = this; - this.emit("row", row); - }, - - read: function(entry, options, hyperlinkReader) { - var self = this; - - var emitSheet = false; - var prepSheet = false; - var emitHyperlinks = false; - var hyperlinks = null; - switch (options.worksheets) { - case "emit": - emitSheet = true; - break; - case "prep": - prepSheet = true; - break; - } - switch(options.hyperlinks) { - case "emit": - emitHyperlinks = true; - break; - case "cache": - this.hyperlinks = hyperlinks = {}; - break; - } - if (!emitSheet && !emitHyperlinks && !hyperlinks) { - entry.autodrain(); - return; - } - - // references - var sharedStrings = this.workbook.sharedStrings; - var styles = this.workbook.styles; - - // xml position - var inCols = false; - var inRows = false; - var inHyperlinks = false; - - // parse state - var cols = null; - var row = null; - var c = null; - var current = null; - - var parser = Sax.createStream(true, {}); - parser.on('opentag', function(node) { - if (emitSheet) { - switch (node.name) { - case "cols": - inCols = true; - cols = []; - break; - case "sheetData": - inRows = true; - break; - - case "col": - if (inCols) { - cols.push({ - min: parseInt(node.attributes.min), - max: parseInt(node.attributes.max), - width: parseFloat(node.attributes.width), - styleId: parseInt(node.attributes.style || "0") - }); - } - break; - - case "row": - if (inRows) { - var r = parseInt(node.attributes.r); - row = new Row(self, r); - if (node.attributes.ht) { - row.height = parseFloat(node.attributes.ht); - } - if (node.attributes.s) { - var styleId = parseInt(node.attributes.s); - row.style = styles.getStyleModel(styleId); - } - } - break; - case "c": - if (row) { - c = { - ref: node.attributes.r, - s: parseInt(node.attributes.s), - t: node.attributes.t - }; - } - break; - case "f": - if (c) { - current = c.f = { text: "" }; - } - break; - case "v": - if (c) { - current = c.v = { text: "" }; - } - break; - case "mergeCell": - } + break; + + case 'row': + if (inRows) { + var r = parseInt(node.attributes.r); + row = new Row(self, r); + if (node.attributes.ht) { + row.height = parseFloat(node.attributes.ht); + } + if (node.attributes.s) { + var styleId = parseInt(node.attributes.s); + row.style = styles.getStyleModel(styleId); + } } - - - // ================================================================= - // - if (emitHyperlinks || hyperlinks) { - switch (node.name) { - case "hyperlinks": - inHyperlinks = true; - break; - case "hyperlink": - if (inHyperlinks) { - var hyperlink = { - ref: node.attributes.ref, - rId: node.attributes["r:id"] - }; - if (emitHyperlinks) { - self.emit("hyperlink", hyperlink); - } else { - hyperlinks[hyperlink.ref] = hyperlink; - } - } - break; - } + break; + case 'c': + if (row) { + c = { + ref: node.attributes.r, + s: parseInt(node.attributes.s), + t: node.attributes.t + }; } - }); - - // only text data is for sheet values - parser.on('text', function (text) { - if (emitSheet) { - if (current) { - current.text += text; - } + break; + case 'f': + if (c) { + current = c.f = { text: '' }; } - }); - - parser.on('closetag', function(name) { - if (emitSheet) { - switch (name) { - case "cols": - inCols = false; - self._columns = Column.fromModel(cols); - break; - case "sheetData": - inRows = false; - break; - - case "row": - self._dimensions.expandRow(row); - self._emitRow(row); - row = null; - break; - - case "c": - if (row && c) { - var address = colCache.decodeAddress(c.ref); - var cell = row.getCell(address.col); - if (c.s) { - cell.style = self.workbook.styles.getStyleModel(c.s); - } - - if (c.f) { - var value = { - formula: c.f.text - }; - if (c.v) { - if (c.t == "str") { - value.result = utils.xmlDecode(c.v.text); - } else { - value.result = parseFloat(c.v.text); - } - } - cell.value = value; - } else if (c.v) { - switch(c.t) { - case "s": - var index = parseInt(c.v.text); - if (sharedStrings) { - cell.value = sharedStrings.getString(index); - } else { - cell.value = { - sharedString: index - }; - } - break; - case "str": - cell.value = utils.xmlDecode(c.v.text); - break; - default: - if (utils.isDateFmt(cell.numFmt)) { - cell.value = utils.excelToDate(parseFloat(c.v.text)); - } else { - cell.value = parseFloat(c.v.text); - } - break; - } - } - c = null; - } - break; - } + break; + case 'v': + if (c) { + current = c.v = { text: '' }; + } + break; + case 'mergeCell': + } + } + + + // ================================================================= + // + if (emitHyperlinks || hyperlinks) { + switch (node.name) { + case 'hyperlinks': + inHyperlinks = true; + break; + case 'hyperlink': + if (inHyperlinks) { + var hyperlink = { + ref: node.attributes.ref, + rId: node.attributes['r:id'] + }; + if (emitHyperlinks) { + self.emit('hyperlink', hyperlink); + } else { + hyperlinks[hyperlink.ref] = hyperlink; + } } - if (emitHyperlinks || hyperlinks) { - switch (name) { - case "hyperlinks": - inHyperlinks = false; - break; + break; + } + } + }); + + // only text data is for sheet values + parser.on('text', function (text) { + if (emitSheet) { + if (current) { + current.text += text; + } + } + }); + + parser.on('closetag', function(name) { + if (emitSheet) { + switch (name) { + case 'cols': + inCols = false; + self._columns = Column.fromModel(cols); + break; + case 'sheetData': + inRows = false; + break; + + case 'row': + self._dimensions.expandRow(row); + self._emitRow(row); + row = null; + break; + + case 'c': + if (row && c) { + var address = colCache.decodeAddress(c.ref); + var cell = row.getCell(address.col); + if (c.s) { + cell.style = self.workbook.styles.getStyleModel(c.s); + } + + if (c.f) { + var value = { + formula: c.f.text + }; + if (c.v) { + if (c.t === 'str') { + value.result = utils.xmlDecode(c.v.text); + } else { + value.result = parseFloat(c.v.text); + } + } + cell.value = value; + } else if (c.v) { + switch(c.t) { + case 's': + var index = parseInt(c.v.text); + if (sharedStrings) { + cell.value = sharedStrings.getString(index); + } else { + cell.value = { + sharedString: index + }; + } + break; + case 'str': + cell.value = utils.xmlDecode(c.v.text); + break; + default: + if (utils.isDateFmt(cell.numFmt)) { + cell.value = utils.excelToDate(parseFloat(c.v.text)); + } else { + cell.value = parseFloat(c.v.text); + } + break; } + } + c = null; } - }); - parser.on('error', function (error) { - self.emit('error', error); - }); - parser.on('end', function() { - self.emit('finished'); - }); - - // create a down-stream flow-control to regulate the stream - var flowControl = this.workbook.flowControl.createChild(); - flowControl.pipe(parser, {sync: true}); - entry.pipe(flowControl); - } + break; + } + } + if (emitHyperlinks || hyperlinks) { + switch (name) { + case 'hyperlinks': + inHyperlinks = false; + break; + } + } + }); + parser.on('error', function (error) { + self.emit('error', error); + }); + parser.on('end', function() { + self.emit('finished'); + }); + + // create a down-stream flow-control to regulate the stream + var flowControl = this.workbook.flowControl.createChild(); + flowControl.pipe(parser, {sync: true}); + entry.pipe(flowControl); + } }); diff --git a/spec/.jshintrc b/spec/.jshintrc new file mode 100644 index 000000000..d5f4f1411 --- /dev/null +++ b/spec/.jshintrc @@ -0,0 +1,10 @@ +{ + "extends": "../.jshintrc", + "mocha": true, + "globals": { + "expect": true + }, + "expr": true, + "elision": true, + "laxcomma": true +} \ No newline at end of file diff --git a/spec/integration/workbook-xlsx-reader.spec.js b/spec/integration/workbook-xlsx-reader.spec.js new file mode 100644 index 000000000..d088a469c --- /dev/null +++ b/spec/integration/workbook-xlsx-reader.spec.js @@ -0,0 +1,30 @@ +'use strict'; + +//var expect = require('chai').expect; +var Bluebird = require('bluebird'); +var fs = require('fs'); +var fsa = Bluebird.promisifyAll(fs); +//var _ = require('underscore'); +var Excel = require('../../excel'); +var testutils = require('./../testutils'); +//var utils = require('../../lib/utils/utils'); + +// need some architectural changes to make stream read work properly +// because of: shared strings, sheet names, etc are not read in guaranteed order +describe.skip('WorkbookReader', function() { + describe('Serialise', function() { + after(function() { + // delete the working file, don't care about errors + return fsa.unlinkAsync('./wbr.test.xlsx').catch(function(){}); + }); + + it('xlsx file', function() { + var wb = testutils.createTestBook(true, Excel.Workbook); + + return wb.xlsx.writeFile('./wbr.test.xlsx') + .then(function() { + return testutils.checkTestBookReader('./wbr.test.xlsx'); + }); + }); + }); +}); diff --git a/spec/integration/workbook.spec.js b/spec/integration/workbook.spec.js index 8f700b713..d8cb5651d 100644 --- a/spec/integration/workbook.spec.js +++ b/spec/integration/workbook.spec.js @@ -13,165 +13,299 @@ var testutils = require('./../testutils'); describe('Workbook', function() { - it('creates sheets and saves with correct names', function() { - var wb = new Excel.Workbook(); - var ws1 = wb.addWorksheet('Hello, World!'); - expect(ws1.name).to.equal('Hello, World!'); + describe('Serialise', function() { - var ws2 = wb.addWorksheet(); - expect(ws2.name).to.match(/sheet\d+/); + after(function() { + return fsa.unlinkAsync('./wb.test.xlsx') + .catch(function() {}); + }); - var ws3 = wb.addWorksheet('This & That'); + it('creates sheets and saves with correct names', function() { + var wb = new Excel.Workbook(); + var ws1 = wb.addWorksheet('Hello, World!'); + expect(ws1.name).to.equal('Hello, World!'); - return wb.xlsx.writeFile('./wb.test.xlsx') - .then(function() { - var wb2 = new Excel.Workbook(); - return wb2.xlsx.readFile('./wb.test.xlsx'); - }) - .then(function(wb2) { - expect(wb2.getWorksheet('Hello, World!')).to.be.ok; - expect(wb2.getWorksheet('This & That')).to.be.ok; - }) - .catch(function(error) { - expect(error && error.message).to.not.be.ok; - }) - .finally(function() { - return fsa.unlinkAsync('./wb.test.xlsx'); - }); - }); + var ws2 = wb.addWorksheet(); + expect(ws2.name).to.match(/sheet\d+/); - it('serialises and deserialises by model', function() { - var wb = testutils.createTestBook(false, Excel.Workbook); + var ws3 = wb.addWorksheet('This & That'); - return testutils.cloneByModel(wb, Excel.Workbook) - .then(function(wb2) { - testutils.checkTestBook(wb2, 'model'); - }) - .catch(function(error) { - console.log(error.message); - expect(error && error.message).to.be.undefined; - }); - }); + return wb.xlsx.writeFile('./wb.test.xlsx') + .then(function() { + var wb2 = new Excel.Workbook(); + return wb2.xlsx.readFile('./wb.test.xlsx'); + }) + .then(function(wb2) { + expect(wb2.getWorksheet('Hello, World!')).to.be.ok; + expect(wb2.getWorksheet('This & That')).to.be.ok; + }); + }); - it('serializes and deserializes to xlsx file properly', function() { + it('serializes and deserializes to xlsx file properly', function() { - var wb = testutils.createTestBook(true, Excel.Workbook); - //fs.writeFileSync('./testmodel.json', JSON.stringify(wb.model, null, ' ')); + var wb = testutils.createTestBook(true, Excel.Workbook); + //fs.writeFileSync('./testmodel.json', JSON.stringify(wb.model, null, ' ')); - return wb.xlsx.writeFile('./wb.test.xlsx') - .then(function() { - var wb2 = new Excel.Workbook(); - return wb2.xlsx.readFile('./wb.test.xlsx'); - }) - .then(function(wb2) { - testutils.checkTestBook(wb2, 'xlsx', true); - }) - .catch(function(error) { - expect(error && error.message).to.not.be.ok; - }) - .finally(function() { - return fsa.unlinkAsync('./wb.test.xlsx'); - }); - }); + return wb.xlsx.writeFile('./wb.test.xlsx') + .then(function() { + var wb2 = new Excel.Workbook(); + return wb2.xlsx.readFile('./wb.test.xlsx'); + }) + .then(function(wb2) { + testutils.checkTestBook(wb2, 'xlsx', true); + }); + }); - it('serializes row styles and columns properly', function() { - var wb = new Excel.Workbook(); - var ws = wb.addWorksheet('blort'); - - ws.columns = [ - { header: 'A1', width: 10 }, - { header: 'B1', width: 20, style: { font: testutils.styles.fonts.comicSansUdB16, alignment: testutils.styles.alignments[1].alignment } }, - { header: 'C1', width: 30 } - ]; - - ws.getRow(2).font = testutils.styles.fonts.broadwayRedOutline20; - - ws.getCell('A2').value = 'A2'; - ws.getCell('B2').value = 'B2'; - ws.getCell('C2').value = 'C2'; - ws.getCell('A3').value = 'A3'; - ws.getCell('B3').value = 'B3'; - ws.getCell('C3').value = 'C3'; - - return wb.xlsx.writeFile('./wb.test.xlsx') - .then(function() { - var wb2 = new Excel.Workbook(); - return wb2.xlsx.readFile('./wb.test.xlsx'); - }) - .then(function(wb2) { - var ws2 = wb2.getWorksheet('blort'); - _.each(['A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3'], function(address) { - expect(ws2.getCell(address).value).to.equal(address); + it('serializes row styles and columns properly', function() { + var wb = new Excel.Workbook(); + var ws = wb.addWorksheet('blort'); + + ws.columns = [ + { header: 'A1', width: 10 }, + { header: 'B1', width: 20, style: { font: testutils.styles.fonts.comicSansUdB16, alignment: testutils.styles.alignments[1].alignment } }, + { header: 'C1', width: 30 } + ]; + + ws.getRow(2).font = testutils.styles.fonts.broadwayRedOutline20; + + ws.getCell('A2').value = 'A2'; + ws.getCell('B2').value = 'B2'; + ws.getCell('C2').value = 'C2'; + ws.getCell('A3').value = 'A3'; + ws.getCell('B3').value = 'B3'; + ws.getCell('C3').value = 'C3'; + + return wb.xlsx.writeFile('./wb.test.xlsx') + .then(function() { + var wb2 = new Excel.Workbook(); + return wb2.xlsx.readFile('./wb.test.xlsx'); + }) + .then(function(wb2) { + var ws2 = wb2.getWorksheet('blort'); + _.each(['A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3'], function(address) { + expect(ws2.getCell(address).value).to.equal(address); + }); + expect(ws2.getCell('B1').font).to.deep.equal(testutils.styles.fonts.comicSansUdB16); + expect(ws2.getCell('B1').alignment).to.deep.equal(testutils.styles.alignments[1].alignment); + expect(ws2.getCell('A2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); + expect(ws2.getCell('B2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); + expect(ws2.getCell('C2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); + expect(ws2.getCell('B3').font).to.deep.equal(testutils.styles.fonts.comicSansUdB16); + expect(ws2.getCell('B3').alignment).to.deep.equal(testutils.styles.alignments[1].alignment); + + expect(ws2.getColumn(2).font).to.deep.equal(testutils.styles.fonts.comicSansUdB16); + expect(ws2.getColumn(2).alignment).to.deep.equal(testutils.styles.alignments[1].alignment); + + expect(ws2.getRow(2).font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); }); - expect(ws2.getCell('B1').font).to.deep.equal(testutils.styles.fonts.comicSansUdB16); - expect(ws2.getCell('B1').alignment).to.deep.equal(testutils.styles.alignments[1].alignment); - expect(ws2.getCell('A2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); - expect(ws2.getCell('B2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); - expect(ws2.getCell('C2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); - expect(ws2.getCell('B3').font).to.deep.equal(testutils.styles.fonts.comicSansUdB16); - expect(ws2.getCell('B3').alignment).to.deep.equal(testutils.styles.alignments[1].alignment); - - expect(ws2.getColumn(2).font).to.deep.equal(testutils.styles.fonts.comicSansUdB16); - expect(ws2.getColumn(2).alignment).to.deep.equal(testutils.styles.alignments[1].alignment); - - expect(ws2.getRow(2).font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); - }) - .catch(function(error) { - expect(error && error.message).to.not.be.ok; - }) - .finally(function() { - return fsa.unlinkAsync('./wb.test.xlsx'); - }); - }); + }); - it('serializes and deserializes a lot of sheets to xlsx file properly', function() { - this.timeout(10000); + it('serializes and deserializes a lot of sheets to xlsx file properly', function() { + this.timeout(10000); - var i; - var wb = new Excel.Workbook(); - var numSheets = 90; - // add numSheets sheets - for (i = 1; i <= numSheets; i++) { - var ws = wb.addWorksheet('sheet' + i); - ws.getCell('A1').value = i; - } - return wb.xlsx.writeFile('./wb.test.xlsx') - .then(function() { - var wb2 = new Excel.Workbook(); - return wb2.xlsx.readFile('./wb.test.xlsx'); - }) - .then(function(wb2) { - for (i = 1; i <= numSheets; i++) { - var ws2 = wb2.getWorksheet('sheet' + i); - expect(ws2).to.be.ok; - expect(ws2.getCell('A1').value).to.equal(i); - } - }) - .finally(function() { - return fsa.unlinkAsync('./wb.test.xlsx'); + var i; + var wb = new Excel.Workbook(); + var numSheets = 90; + // add numSheets sheets + for (i = 1; i <= numSheets; i++) { + var ws = wb.addWorksheet('sheet' + i); + ws.getCell('A1').value = i; + } + return wb.xlsx.writeFile('./wb.test.xlsx') + .then(function() { + var wb2 = new Excel.Workbook(); + return wb2.xlsx.readFile('./wb.test.xlsx'); + }) + .then(function(wb2) { + for (i = 1; i <= numSheets; i++) { + var ws2 = wb2.getWorksheet('sheet' + i); + expect(ws2).to.be.ok; + expect(ws2.getCell('A1').value).to.equal(i); + } + }); + }); + + it('serializes and deserialises to csv file properly', function() { + this.timeout(5000); + + var wb = testutils.createTestBook(true, Excel.Workbook); + //fs.writeFileSync('./testmodel.json', JSON.stringify(wb.model, null, ' ')); + + return wb.csv.writeFile('./wb.test.csv') + .then(function() { + var wb2 = new Excel.Workbook(); + return wb2.csv.readFile('./wb.test.csv') + .then(function() { + return wb2; + }); + }) + .then(function(wb2) { + testutils.checkTestBook(wb2, 'csv'); + }); + }); + + it('serialises and deserialises defined names', function() { + var wb1 = new Excel.Workbook(); + var ws1a = wb1.addWorksheet('blort'); + var ws1b = wb1.addWorksheet('foo'); + + function assign(sheet, address, value, name) { + var cell = sheet.getCell(address); + cell.value = value; + cell.name = name; + } + + // single entry + assign(ws1a, 'A1', 5, 'five'); + + // three amigos - horizontal line + assign(ws1a, 'A3', 3, 'amigos'); + assign(ws1a, 'B3', 3, 'amigos'); + assign(ws1a, 'C3', 3, 'amigos'); + + // three amigos - vertical line + assign(ws1a, 'E1', 3, 'verts'); + assign(ws1a, 'E2', 3, 'verts'); + assign(ws1a, 'E3', 3, 'verts'); + + // four square + assign(ws1a, 'C5', 4, 'squares'); + assign(ws1a, 'B6', 4, 'squares'); + assign(ws1a, 'C6', 4, 'squares'); + assign(ws1a, 'B5', 4, 'squares'); + + // long distance + assign(ws1a, 'B7', 2, 'sheets'); + assign(ws1b, 'B7', 2, 'sheets'); + + return wb1.xlsx.writeFile('./wb.test.xlsx') + .then(function() { + var wb2 = new Excel.Workbook(); + return wb2.xlsx.readFile('./wb.test.xlsx'); + }) + .then(function(wb2) { + var ws2a = wb2.getWorksheet('blort'); + var ws2b = wb2.getWorksheet('foo'); + + function check(sheet, address, value, name) { + var cell = sheet.getCell(address); + expect(cell.value).to.equal(value); + expect(cell.name).to.equal(name); + } + + // single entry + check(ws2a, 'A1', 5, 'five'); + + // three amigos - horizontal line + check(ws2a, 'A3', 3, 'amigos'); + check(ws2a, 'B3', 3, 'amigos'); + check(ws2a, 'C3', 3, 'amigos'); + + // three amigos - vertical line + check(ws2a, 'E1', 3, 'verts'); + check(ws2a, 'E2', 3, 'verts'); + check(ws2a, 'E3', 3, 'verts'); + + // four square + check(ws2a, 'C5', 4, 'squares'); + check(ws2a, 'B6', 4, 'squares'); + check(ws2a, 'C6', 4, 'squares'); + check(ws2a, 'B5', 4, 'squares'); + + // long distance + check(ws2a, 'B7', 2, 'sheets'); + check(ws2b, 'B7', 2, 'sheets'); + }); + }); + + describe('Merge Cells', function() { + it('serialises and deserialises properly', function() { + var wb = new Excel.Workbook(); + var ws = wb.addWorksheet('blort'); + + // initial values + ws.getCell('B2').value = 'B2'; + + ws.mergeCells('B2:C3'); + + return wb.xlsx.writeFile('./wb.test.xlsx') + .then(function() { + var wb2 = new Excel.Workbook(); + return wb2.xlsx.readFile('./wb.test.xlsx'); + }) + .then(function(wb2) { + var ws2 = wb2.getWorksheet('blort'); + + expect(ws2.getCell('B2').value).to.equal('B2'); + expect(ws2.getCell('B3').value).to.equal('B2'); + expect(ws2.getCell('C2').value).to.equal('B2'); + expect(ws2.getCell('C3').value).to.equal('B2'); + + expect(ws2.getCell('B2').type).to.equal(Excel.ValueType.String); + expect(ws2.getCell('B3').type).to.equal(Excel.ValueType.Merge); + expect(ws2.getCell('C2').type).to.equal(Excel.ValueType.Merge); + expect(ws2.getCell('C3').type).to.equal(Excel.ValueType.Merge); + }); }); - }); - it('serializes and deserialises to csv file properly', function() { - this.timeout(5000); + it('serialises and deserialises styles', function() { + var wb = new Excel.Workbook(); + var ws = wb.addWorksheet('blort'); + // initial values + var B2 = ws.getCell('B2'); + B2.value = 5; + B2.style.font = testutils.styles.fonts.broadwayRedOutline20; + B2.style.border = testutils.styles.borders.doubleRed; + B2.style.fill = testutils.styles.fills.blueWhiteHGrad; + B2.style.alignment = testutils.styles.namedAlignments.middleCentre; + B2.style.numFmt = testutils.styles.numFmts.numFmt1; - var wb = testutils.createTestBook(true, Excel.Workbook); - //fs.writeFileSync('./testmodel.json', JSON.stringify(wb.model, null, ' ')); + // expecting styles to be copied (see worksheet spec) + ws.mergeCells('B2:C3'); - return wb.csv.writeFile('./wb.test.csv') - .then(function() { - var wb2 = new Excel.Workbook(); - return wb2.csv.readFile('./wb.test.csv') + return wb.xlsx.writeFile('./wb.test.xlsx') .then(function() { - return wb2; + var wb2 = new Excel.Workbook(); + return wb2.xlsx.readFile('./wb.test.xlsx'); + }) + .then(function(wb2) { + var ws2 = wb2.getWorksheet('blort'); + + expect(ws2.getCell('B2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); + expect(ws2.getCell('B2').border).to.deep.equal(testutils.styles.borders.doubleRed); + expect(ws2.getCell('B2').fill).to.deep.equal(testutils.styles.fills.blueWhiteHGrad); + expect(ws2.getCell('B2').alignment).to.deep.equal(testutils.styles.namedAlignments.middleCentre); + expect(ws2.getCell('B2').numFmt).to.equal(testutils.styles.numFmts.numFmt1); + + expect(ws2.getCell('B3').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); + expect(ws2.getCell('B3').border).to.deep.equal(testutils.styles.borders.doubleRed); + expect(ws2.getCell('B3').fill).to.deep.equal(testutils.styles.fills.blueWhiteHGrad); + expect(ws2.getCell('B3').alignment).to.deep.equal(testutils.styles.namedAlignments.middleCentre); + expect(ws2.getCell('B3').numFmt).to.equal(testutils.styles.numFmts.numFmt1); + + expect(ws2.getCell('C2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); + expect(ws2.getCell('C2').border).to.deep.equal(testutils.styles.borders.doubleRed); + expect(ws2.getCell('C2').fill).to.deep.equal(testutils.styles.fills.blueWhiteHGrad); + expect(ws2.getCell('C2').alignment).to.deep.equal(testutils.styles.namedAlignments.middleCentre); + expect(ws2.getCell('C2').numFmt).to.equal(testutils.styles.numFmts.numFmt1); + + expect(ws2.getCell('C3').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); + expect(ws2.getCell('C3').border).to.deep.equal(testutils.styles.borders.doubleRed); + expect(ws2.getCell('C3').fill).to.deep.equal(testutils.styles.fills.blueWhiteHGrad); + expect(ws2.getCell('C3').alignment).to.deep.equal(testutils.styles.namedAlignments.middleCentre); + expect(ws2.getCell('C3').numFmt).to.equal(testutils.styles.numFmts.numFmt1); }); - }) + }); + }); + }); + + it('serialises and deserialises by model', function() { + var wb = testutils.createTestBook(false, Excel.Workbook); + + return testutils.cloneByModel(wb, Excel.Workbook) .then(function(wb2) { - testutils.checkTestBook(wb2, 'csv'); - }) - .finally(function() { - return fsa.unlinkAsync('./wb.test.csv'); + testutils.checkTestBook(wb2, 'model'); }); }); @@ -206,173 +340,4 @@ describe('Workbook', function() { expect(success).to.equal(2); }); }); - - it('serialises and deserialises defined names', function() { - var wb1 = new Excel.Workbook(); - var ws1a = wb1.addWorksheet('blort'); - var ws1b = wb1.addWorksheet('foo'); - - function assign(sheet, address, value, name) { - var cell = sheet.getCell(address); - cell.value = value; - cell.name = name; - } - - // single entry - assign(ws1a, 'A1', 5, 'five'); - - // three amigos - horizontal line - assign(ws1a, 'A3', 3, 'amigos'); - assign(ws1a, 'B3', 3, 'amigos'); - assign(ws1a, 'C3', 3, 'amigos'); - - // three amigos - vertical line - assign(ws1a, 'E1', 3, 'verts'); - assign(ws1a, 'E2', 3, 'verts'); - assign(ws1a, 'E3', 3, 'verts'); - - // four square - assign(ws1a, 'C5', 4, 'squares'); - assign(ws1a, 'B6', 4, 'squares'); - assign(ws1a, 'C6', 4, 'squares'); - assign(ws1a, 'B5', 4, 'squares'); - - // long distance - assign(ws1a, 'B7', 2, 'sheets'); - assign(ws1b, 'B7', 2, 'sheets'); - - return wb1.xlsx.writeFile('./wb.test.xlsx') - .then(function() { - var wb2 = new Excel.Workbook(); - return wb2.xlsx.readFile('./wb.test.xlsx'); - }) - .then(function(wb2) { - var ws2a = wb2.getWorksheet('blort'); - var ws2b = wb2.getWorksheet('foo'); - - function check(sheet, address, value, name) { - var cell = sheet.getCell(address); - expect(cell.value).to.equal(value); - expect(cell.name).to.equal(name); - } - - // single entry - check(ws2a, 'A1', 5, 'five'); - - // three amigos - horizontal line - check(ws2a, 'A3', 3, 'amigos'); - check(ws2a, 'B3', 3, 'amigos'); - check(ws2a, 'C3', 3, 'amigos'); - - // three amigos - vertical line - check(ws2a, 'E1', 3, 'verts'); - check(ws2a, 'E2', 3, 'verts'); - check(ws2a, 'E3', 3, 'verts'); - - // four square - check(ws2a, 'C5', 4, 'squares'); - check(ws2a, 'B6', 4, 'squares'); - check(ws2a, 'C6', 4, 'squares'); - check(ws2a, 'B5', 4, 'squares'); - - // long distance - check(ws2a, 'B7', 2, 'sheets'); - check(ws2b, 'B7', 2, 'sheets'); - - }) - .finally(function() { - //return fsa.unlinkAsync('./wb.test.xlsx'); - }); - }); - - describe('Merge Cells', function() { - it('serialises and deserialises properly', function() { - var wb = new Excel.Workbook(); - var ws = wb.addWorksheet('blort'); - - // initial values - ws.getCell('B2').value = 'B2'; - - ws.mergeCells('B2:C3'); - - return wb.xlsx.writeFile('./wb.test.xlsx') - .then(function() { - var wb2 = new Excel.Workbook(); - return wb2.xlsx.readFile('./wb.test.xlsx'); - }) - .then(function(wb2) { - var ws2 = wb2.getWorksheet('blort'); - - expect(ws2.getCell('B2').value).to.equal('B2'); - expect(ws2.getCell('B3').value).to.equal('B2'); - expect(ws2.getCell('C2').value).to.equal('B2'); - expect(ws2.getCell('C3').value).to.equal('B2'); - - expect(ws2.getCell('B2').type).to.equal(Excel.ValueType.String); - expect(ws2.getCell('B3').type).to.equal(Excel.ValueType.Merge); - expect(ws2.getCell('C2').type).to.equal(Excel.ValueType.Merge); - expect(ws2.getCell('C3').type).to.equal(Excel.ValueType.Merge); - }) - .finally(function() { - return fsa.unlinkAsync('./wb.test.xlsx'); - }); - }); - - it('serialises and deserialises styles', function() { - var wb = new Excel.Workbook(); - var ws = wb.addWorksheet('blort'); - - // initial values - var B2 = ws.getCell('B2'); - B2.value = 5; - B2.style.font = testutils.styles.fonts.broadwayRedOutline20; - B2.style.border = testutils.styles.borders.doubleRed; - B2.style.fill = testutils.styles.fills.blueWhiteHGrad; - B2.style.alignment = testutils.styles.namedAlignments.middleCentre; - B2.style.numFmt = testutils.styles.numFmts.numFmt1; - - // expecting styles to be copied (see worksheet spec) - ws.mergeCells('B2:C3'); - - return wb.xlsx.writeFile('./wb.test.xlsx') - .then(function() { - var wb2 = new Excel.Workbook(); - return wb2.xlsx.readFile('./wb.test.xlsx'); - }) - .then(function(wb2) { - var ws2 = wb2.getWorksheet('blort'); - - expect(ws2.getCell('B2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); - expect(ws2.getCell('B2').border).to.deep.equal(testutils.styles.borders.doubleRed); - expect(ws2.getCell('B2').fill).to.deep.equal(testutils.styles.fills.blueWhiteHGrad); - expect(ws2.getCell('B2').alignment).to.deep.equal(testutils.styles.namedAlignments.middleCentre); - expect(ws2.getCell('B2').numFmt).to.equal(testutils.styles.numFmts.numFmt1); - - expect(ws2.getCell('B3').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); - expect(ws2.getCell('B3').border).to.deep.equal(testutils.styles.borders.doubleRed); - expect(ws2.getCell('B3').fill).to.deep.equal(testutils.styles.fills.blueWhiteHGrad); - expect(ws2.getCell('B3').alignment).to.deep.equal(testutils.styles.namedAlignments.middleCentre); - expect(ws2.getCell('B3').numFmt).to.equal(testutils.styles.numFmts.numFmt1); - - expect(ws2.getCell('C2').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); - expect(ws2.getCell('C2').border).to.deep.equal(testutils.styles.borders.doubleRed); - expect(ws2.getCell('C2').fill).to.deep.equal(testutils.styles.fills.blueWhiteHGrad); - expect(ws2.getCell('C2').alignment).to.deep.equal(testutils.styles.namedAlignments.middleCentre); - expect(ws2.getCell('C2').numFmt).to.equal(testutils.styles.numFmts.numFmt1); - - expect(ws2.getCell('C3').font).to.deep.equal(testutils.styles.fonts.broadwayRedOutline20); - expect(ws2.getCell('C3').border).to.deep.equal(testutils.styles.borders.doubleRed); - expect(ws2.getCell('C3').fill).to.deep.equal(testutils.styles.fills.blueWhiteHGrad); - expect(ws2.getCell('C3').alignment).to.deep.equal(testutils.styles.namedAlignments.middleCentre); - expect(ws2.getCell('C3').numFmt).to.equal(testutils.styles.numFmts.numFmt1); - - }) - .catch(function(error) { - expect(error && error.message).to.not.be.ok; - }) - .finally(function() { - return fsa.unlinkAsync('./wb.test.xlsx'); - }); - }); - }); }); diff --git a/spec/testutils.js b/spec/testutils.js index 4699f3812..289d49533 100644 --- a/spec/testutils.js +++ b/spec/testutils.js @@ -1,34 +1,36 @@ -var expect = require("chai").expect; +'use strict'; -var Promise = require("bluebird"); -var _ = require("underscore"); -var MemoryStream = require("memorystream"); +var expect = require('chai').expect; -var Excel = require("../excel"); +var Bluebird = require('bluebird'); +var _ = require('underscore'); +var MemoryStream = require('memorystream'); + +var Excel = require('../excel'); var utils = module.exports = { - cloneByModel: function(thing1, type) { + cloneByModel: function(thing1, Type) { var model = thing1.model; - //console.log(JSON.stringify(model, null, " ")) - var thing2 = new type(); + //console.log(JSON.stringify(model, null, ' ')) + var thing2 = new Type(); thing2.model = model; - return Promise.resolve(thing2); + return Bluebird.resolve(thing2); }, - cloneByStream: function(thing1, type, end) { - var deferred = Promise.defer(); - end = end || "end"; + cloneByStream: function(thing1, Type, end) { + var deferred = Bluebird.defer(); + end = end || 'end'; - var thing2 = new type(); + var thing2 = new Type(); var stream = thing2.createInputStream(); stream.on(end, function() { deferred.resolve(thing2); }); - stream.on("error", function(error) { + stream.on('error', function(error) { deferred.reject(error); }); var memStream = new MemoryStream(); - memStream.on("error", function(error) { + memStream.on('error', function(error) { deferred.reject(error); }); memStream.pipe(stream); @@ -41,137 +43,137 @@ var utils = module.exports = { }, testValues: { num: 7, - str: "Hello, World!", + str: 'Hello, World!', str2: 'Talk to the H&', date: new Date(), formulas: [ - {formula: "A1", result: 7}, - {formula: "A2", result: undefined} + {formula: 'A1', result: 7}, + {formula: 'A2', result: undefined} ], - hyperlink: {hyperlink: "http://www.link.com", text: "www.link.com"}, - numFmt1: "# ?/?", - numFmt2: "[Green]#,##0 ;[Red](#,##0)", - numFmtDate: "dd, mmm yyyy" + hyperlink: {hyperlink: 'http://www.link.com', text: 'www.link.com'}, + numFmt1: '# ?/?', + numFmt2: '[Green]#,##0 ;[Red](#,##0)', + numFmtDate: 'dd, mmm yyyy' }, styles: { numFmts: { - numFmt1: "# ?/?", - numFmt2: "[Green]#,##0 ;[Red](#,##0)" + numFmt1: '# ?/?', + numFmt2: '[Green]#,##0 ;[Red](#,##0)' }, fonts: { - arialBlackUI14: { name: "Arial Black", family: 2, size: 14, underline: true, italic: true }, - comicSansUdB16: { name: "Comic Sans MS", family: 4, size: 16, underline: "double", bold: true }, - broadwayRedOutline20: { name: "Broadway", family: 5, size: 20, outline: true, color: { argb:"FFFF0000"}} + arialBlackUI14: { name: 'Arial Black', family: 2, size: 14, underline: true, italic: true }, + comicSansUdB16: { name: 'Comic Sans MS', family: 4, size: 16, underline: 'double', bold: true }, + broadwayRedOutline20: { name: 'Broadway', family: 5, size: 20, outline: true, color: { argb:'FFFF0000'}} }, alignments: [ - { text: "Top Left", alignment: { horizontal: "left", vertical: "top" } }, - { text: "Middle Centre", alignment: { horizontal: "center", vertical: "middle" } }, - { text: "Bottom Right", alignment: { horizontal: "right", vertical: "bottom" } }, - { text: "Wrap Text", alignment: { wrapText: true } }, - { text: "Indent 1", alignment: { indent: 1 } }, - { text: "Indent 2", alignment: { indent: 2 } }, - { text: "Rotate 15", alignment: { horizontal: "right", vertical: "bottom", textRotation: 15 } }, - { text: "Rotate 30", alignment: { horizontal: "right", vertical: "bottom", textRotation: 30 } }, - { text: "Rotate 45", alignment: { horizontal: "right", vertical: "bottom", textRotation: 45 } }, - { text: "Rotate 60", alignment: { horizontal: "right", vertical: "bottom", textRotation: 60 } }, - { text: "Rotate 75", alignment: { horizontal: "right", vertical: "bottom", textRotation: 75 } }, - { text: "Rotate 90", alignment: { horizontal: "right", vertical: "bottom", textRotation: 90 } }, - { text: "Rotate -15", alignment: { horizontal: "right", vertical: "bottom", textRotation: -55 } }, - { text: "Rotate -30", alignment: { horizontal: "right", vertical: "bottom", textRotation: -30 } }, - { text: "Rotate -45", alignment: { horizontal: "right", vertical: "bottom", textRotation: -45 } }, - { text: "Rotate -60", alignment: { horizontal: "right", vertical: "bottom", textRotation: -60 } }, - { text: "Rotate -75", alignment: { horizontal: "right", vertical: "bottom", textRotation: -75 } }, - { text: "Rotate -90", alignment: { horizontal: "right", vertical: "bottom", textRotation: -90 } }, - { text: "Vertical Text", alignment: { horizontal: "right", vertical: "bottom", textRotation: "vertical" } } + { text: 'Top Left', alignment: { horizontal: 'left', vertical: 'top' } }, + { text: 'Middle Centre', alignment: { horizontal: 'center', vertical: 'middle' } }, + { text: 'Bottom Right', alignment: { horizontal: 'right', vertical: 'bottom' } }, + { text: 'Wrap Text', alignment: { wrapText: true } }, + { text: 'Indent 1', alignment: { indent: 1 } }, + { text: 'Indent 2', alignment: { indent: 2 } }, + { text: 'Rotate 15', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: 15 } }, + { text: 'Rotate 30', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: 30 } }, + { text: 'Rotate 45', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: 45 } }, + { text: 'Rotate 60', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: 60 } }, + { text: 'Rotate 75', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: 75 } }, + { text: 'Rotate 90', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: 90 } }, + { text: 'Rotate -15', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: -55 } }, + { text: 'Rotate -30', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: -30 } }, + { text: 'Rotate -45', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: -45 } }, + { text: 'Rotate -60', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: -60 } }, + { text: 'Rotate -75', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: -75 } }, + { text: 'Rotate -90', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: -90 } }, + { text: 'Vertical Text', alignment: { horizontal: 'right', vertical: 'bottom', textRotation: 'vertical' } } ], namedAlignments: { - topLeft: { horizontal: "left", vertical: "top" }, - middleCentre: { horizontal: "center", vertical: "middle" }, - bottomRight: { horizontal: "right", vertical: "bottom" } + topLeft: { horizontal: 'left', vertical: 'top' }, + middleCentre: { horizontal: 'center', vertical: 'middle' }, + bottomRight: { horizontal: 'right', vertical: 'bottom' } }, badAlignments: [ - { text: "Rotate -91", alignment: { textRotation: -91 } }, - { text: "Rotate 91", alignment: { textRotation: 91 } }, - { text: "Indent -1", alignment: { indent: -1 } }, - { text: "Blank", alignment: { } } + { text: 'Rotate -91', alignment: { textRotation: -91 } }, + { text: 'Rotate 91', alignment: { textRotation: 91 } }, + { text: 'Indent -1', alignment: { indent: -1 } }, + { text: 'Blank', alignment: { } } ], borders: { - thin: { top: {style:"thin"}, left: {style:"thin"}, bottom: {style:"thin"}, right: {style:"thin"}}, - doubleRed: { top: {style:"double", color: {argb:"FFFF0000"}}, left: {style:"double", color: {argb:"FFFF0000"}}, bottom: {style:"double", color: {argb:"FFFF0000"}}, right: {style:"double", color: {argb:"FFFF0000"}}}, + thin: { top: {style:'thin'}, left: {style:'thin'}, bottom: {style:'thin'}, right: {style:'thin'}}, + doubleRed: { top: {style:'double', color: {argb:'FFFF0000'}}, left: {style:'double', color: {argb:'FFFF0000'}}, bottom: {style:'double', color: {argb:'FFFF0000'}}, right: {style:'double', color: {argb:'FFFF0000'}}}, thickRainbow: { - top: {style:"double", color: {argb:"FFFF00FF"}}, - left: {style:"double", color: {argb:"FF00FFFF"}}, - bottom: {style:"double", color: {argb:"FF00FF00"}}, - right: {style:"double", color: {argb:"FF00FF"}}, - diagonal: {style:"double", color: {argb:"FFFFFF00"}, up: true, down: true} + top: {style:'double', color: {argb:'FFFF00FF'}}, + left: {style:'double', color: {argb:'FF00FFFF'}}, + bottom: {style:'double', color: {argb:'FF00FF00'}}, + right: {style:'double', color: {argb:'FF00FF'}}, + diagonal: {style:'double', color: {argb:'FFFFFF00'}, up: true, down: true} } }, fills: { - redDarkVertical: {type: "pattern", pattern:"darkVertical", fgColor:{argb:"FFFF0000"}}, - redGreenDarkTrellis: {type: "pattern", pattern:"darkTrellis", - fgColor:{argb:"FFFF0000"}, bgColor:{argb:"FF00FF00"}}, - blueWhiteHGrad: {type: "gradient", gradient: "angle", degree: 0, - stops: [{position:0, color:{argb:"FF0000FF"}},{position:1, color:{argb:"FFFFFFFF"}}]}, - rgbPathGrad: {type: "gradient", gradient: "path", center:{left:0.5,top:0.5}, + redDarkVertical: {type: 'pattern', pattern:'darkVertical', fgColor:{argb:'FFFF0000'}}, + redGreenDarkTrellis: {type: 'pattern', pattern:'darkTrellis', + fgColor:{argb:'FFFF0000'}, bgColor:{argb:'FF00FF00'}}, + blueWhiteHGrad: {type: 'gradient', gradient: 'angle', degree: 0, + stops: [{position:0, color:{argb:'FF0000FF'}},{position:1, color:{argb:'FFFFFFFF'}}]}, + rgbPathGrad: {type: 'gradient', gradient: 'path', center:{left:0.5,top:0.5}, stops: [ - {position:0, color:{argb:"FFFF0000"}}, - {position:0.5, color:{argb:"FF00FF00"}}, - {position:1, color:{argb:"FF0000FF"}} + {position:0, color:{argb:'FFFF0000'}}, + {position:0.5, color:{argb:'FF00FF00'}}, + {position:1, color:{argb:'FF0000FF'}} ] } } }, - createTestBook: function(checkBadAlignments, workbookClass, options) { - var wb = new workbookClass(options); - var ws = wb.addWorksheet("blort"); - - ws.getCell("A1").value = 7; - ws.getCell("B1").value = utils.testValues.str; - ws.getCell("C1").value = utils.testValues.date; - ws.getCell("D1").value = utils.testValues.formulas[0]; - ws.getCell("E1").value = utils.testValues.formulas[1]; - ws.getCell("F1").value = utils.testValues.hyperlink; - ws.getCell("G1").value = utils.testValues.str2; + createTestBook: function(checkBadAlignments, WorkbookClass, options) { + var wb = new WorkbookClass(options); + var ws = wb.addWorksheet('blort'); + + ws.getCell('A1').value = 7; + ws.getCell('B1').value = utils.testValues.str; + ws.getCell('C1').value = utils.testValues.date; + ws.getCell('D1').value = utils.testValues.formulas[0]; + ws.getCell('E1').value = utils.testValues.formulas[1]; + ws.getCell('F1').value = utils.testValues.hyperlink; + ws.getCell('G1').value = utils.testValues.str2; ws.getRow(1).commit(); // merge cell square with numerical value - ws.getCell("A2").value = 5; - ws.mergeCells("A2:B3"); + ws.getCell('A2').value = 5; + ws.mergeCells('A2:B3'); // merge cell square with null value - ws.mergeCells("C2:D3"); + ws.mergeCells('C2:D3'); ws.getRow(3).commit(); - ws.getCell("A4").value = 1.5; - ws.getCell("A4").numFmt = utils.testValues.numFmt1; - ws.getCell("A4").border = utils.styles.borders.thin; - ws.getCell("C4").value = 1.5; - ws.getCell("C4").numFmt = utils.testValues.numFmt2; - ws.getCell("C4").border = utils.styles.borders.doubleRed; - ws.getCell("E4").value = 1.5; - ws.getCell("E4").border = utils.styles.borders.thickRainbow; + ws.getCell('A4').value = 1.5; + ws.getCell('A4').numFmt = utils.testValues.numFmt1; + ws.getCell('A4').border = utils.styles.borders.thin; + ws.getCell('C4').value = 1.5; + ws.getCell('C4').numFmt = utils.testValues.numFmt2; + ws.getCell('C4').border = utils.styles.borders.doubleRed; + ws.getCell('E4').value = 1.5; + ws.getCell('E4').border = utils.styles.borders.thickRainbow; ws.getRow(4).commit(); // test fonts and formats - ws.getCell("A5").value = utils.testValues.str; - ws.getCell("A5").font = utils.styles.fonts.arialBlackUI14; - ws.getCell("B5").value = utils.testValues.str; - ws.getCell("B5").font = utils.styles.fonts.broadwayRedOutline20; - ws.getCell("C5").value = utils.testValues.str; - ws.getCell("C5").font = utils.styles.fonts.comicSansUdB16; - - ws.getCell("D5").value = 1.6; - ws.getCell("D5").numFmt = utils.testValues.numFmt1; - ws.getCell("D5").font = utils.styles.fonts.arialBlackUI14; - - ws.getCell("E5").value = 1.6; - ws.getCell("E5").numFmt = utils.testValues.numFmt2; - ws.getCell("E5").font = utils.styles.fonts.broadwayRedOutline20; - - ws.getCell("F5").value = utils.testValues.date; - ws.getCell("F5").numFmt = utils.testValues.numFmtDate; - ws.getCell("F5").font = utils.styles.fonts.comicSansUdB16; + ws.getCell('A5').value = utils.testValues.str; + ws.getCell('A5').font = utils.styles.fonts.arialBlackUI14; + ws.getCell('B5').value = utils.testValues.str; + ws.getCell('B5').font = utils.styles.fonts.broadwayRedOutline20; + ws.getCell('C5').value = utils.testValues.str; + ws.getCell('C5').font = utils.styles.fonts.comicSansUdB16; + + ws.getCell('D5').value = 1.6; + ws.getCell('D5').numFmt = utils.testValues.numFmt1; + ws.getCell('D5').font = utils.styles.fonts.arialBlackUI14; + + ws.getCell('E5').value = 1.6; + ws.getCell('E5').numFmt = utils.testValues.numFmt2; + ws.getCell('E5').font = utils.styles.fonts.broadwayRedOutline20; + + ws.getCell('F5').value = utils.testValues.date; + ws.getCell('F5').numFmt = utils.testValues.numFmtDate; + ws.getCell('F5').font = utils.styles.fonts.comicSansUdB16; ws.getRow(5).commit(); ws.getRow(6).height = 42; @@ -197,13 +199,13 @@ var utils = module.exports = { var row8 = ws.getRow(8); row8.height = 40; - row8.getCell(1).value = "Blue White Horizontal Gradient"; + row8.getCell(1).value = 'Blue White Horizontal Gradient'; row8.getCell(1).fill = utils.styles.fills.blueWhiteHGrad; - row8.getCell(2).value = "Red Dark Vertical"; + row8.getCell(2).value = 'Red Dark Vertical'; row8.getCell(2).fill = utils.styles.fills.redDarkVertical; - row8.getCell(3).value = "Red Green Dark Trellis"; + row8.getCell(3).value = 'Red Green Dark Trellis'; row8.getCell(3).fill = utils.styles.fills.redGreenDarkTrellis; - row8.getCell(4).value = "RGB Path Gradient"; + row8.getCell(4).value = 'RGB Path Gradient'; row8.getCell(4).fill = utils.styles.fills.rgbPathGrad; row8.commit(); @@ -218,29 +220,30 @@ var utils = module.exports = { expect(font[name]).to.be.undefined; }); }, + checkTestBook: function(wb, docType, useStyles) { var sheetName; var checkFormulas, checkMerges, checkStyles, checkBadAlignments; var dateAccuracy; switch(docType) { - case "xlsx": - sheetName = "blort"; + case 'xlsx': + sheetName = 'blort'; checkFormulas = true; checkMerges = true; checkStyles = useStyles; checkBadAlignments = useStyles; dateAccuracy = 3; break; - case "model": - sheetName = "blort"; + case 'model': + sheetName = 'blort'; checkFormulas = true; checkMerges = true; checkStyles = true; checkBadAlignments = false; dateAccuracy = 3; break; - case "csv": - sheetName = "sheet1"; + case 'csv': + sheetName = 'sheet1'; checkFormulas = false; checkMerges = false; checkStyles = false; @@ -254,101 +257,101 @@ var utils = module.exports = { var ws = wb.getWorksheet(sheetName); expect(ws).to.not.be.undefined; - expect(ws.getCell("A1").value).to.equal(7); - expect(ws.getCell("A1").type).to.equal(Excel.ValueType.Number); - expect(ws.getCell("B1").value).to.equal(utils.testValues.str); - expect(ws.getCell("B1").type).to.equal(Excel.ValueType.String); - expect(Math.abs(ws.getCell("C1").value.getTime() - utils.testValues.date.getTime())).to.be.below(dateAccuracy); - expect(ws.getCell("C1").type).to.equal(Excel.ValueType.Date); + expect(ws.getCell('A1').value).to.equal(7); + expect(ws.getCell('A1').type).to.equal(Excel.ValueType.Number); + expect(ws.getCell('B1').value).to.equal(utils.testValues.str); + expect(ws.getCell('B1').type).to.equal(Excel.ValueType.String); + expect(Math.abs(ws.getCell('C1').value.getTime() - utils.testValues.date.getTime())).to.be.below(dateAccuracy); + expect(ws.getCell('C1').type).to.equal(Excel.ValueType.Date); if (checkFormulas) { - expect(ws.getCell("D1").value).to.deep.equal(utils.testValues.formulas[0]); - expect(ws.getCell("D1").type).to.equal(Excel.ValueType.Formula); - expect(ws.getCell("E1").value).to.deep.equal(utils.testValues.formulas[1]); - expect(ws.getCell("E1").type).to.equal(Excel.ValueType.Formula); - expect(ws.getCell("F1").value).to.deep.equal(utils.testValues.hyperlink); - expect(ws.getCell("F1").type).to.equal(Excel.ValueType.Hyperlink); - expect(ws.getCell("G1").value).to.equal(utils.testValues.str2); + expect(ws.getCell('D1').value).to.deep.equal(utils.testValues.formulas[0]); + expect(ws.getCell('D1').type).to.equal(Excel.ValueType.Formula); + expect(ws.getCell('E1').value).to.deep.equal(utils.testValues.formulas[1]); + expect(ws.getCell('E1').type).to.equal(Excel.ValueType.Formula); + expect(ws.getCell('F1').value).to.deep.equal(utils.testValues.hyperlink); + expect(ws.getCell('F1').type).to.equal(Excel.ValueType.Hyperlink); + expect(ws.getCell('G1').value).to.equal(utils.testValues.str2); } else { - expect(ws.getCell("D1").value).to.equal(utils.testValues.formulas[0].result); - expect(ws.getCell("D1").type).to.equal(Excel.ValueType.Number); - expect(ws.getCell("E1").value).to.be.null; - expect(ws.getCell("E1").type).to.equal(Excel.ValueType.Null); - expect(ws.getCell("F1").value).to.deep.equal(utils.testValues.hyperlink.hyperlink); - expect(ws.getCell("F1").type).to.equal(Excel.ValueType.String); - expect(ws.getCell("G1").value).to.equal(utils.testValues.str2); + expect(ws.getCell('D1').value).to.equal(utils.testValues.formulas[0].result); + expect(ws.getCell('D1').type).to.equal(Excel.ValueType.Number); + expect(ws.getCell('E1').value).to.be.null; + expect(ws.getCell('E1').type).to.equal(Excel.ValueType.Null); + expect(ws.getCell('F1').value).to.deep.equal(utils.testValues.hyperlink.hyperlink); + expect(ws.getCell('F1').type).to.equal(Excel.ValueType.String); + expect(ws.getCell('G1').value).to.equal(utils.testValues.str2); } // A2:B3 - expect(ws.getCell("A2").value).to.equal(5); - expect(ws.getCell("A2").type).to.equal(Excel.ValueType.Number); - expect(ws.getCell("A2").master).to.equal(ws.getCell("A2")); + expect(ws.getCell('A2').value).to.equal(5); + expect(ws.getCell('A2').type).to.equal(Excel.ValueType.Number); + expect(ws.getCell('A2').master).to.equal(ws.getCell('A2')); if (checkMerges) { - expect(ws.getCell("A3").value).to.equal(5); - expect(ws.getCell("A3").type).to.equal(Excel.ValueType.Merge); - expect(ws.getCell("A3").master).to.equal(ws.getCell("A2")); + expect(ws.getCell('A3').value).to.equal(5); + expect(ws.getCell('A3').type).to.equal(Excel.ValueType.Merge); + expect(ws.getCell('A3').master).to.equal(ws.getCell('A2')); - expect(ws.getCell("B2").value).to.equal(5); - expect(ws.getCell("B2").type).to.equal(Excel.ValueType.Merge); - expect(ws.getCell("B2").master).to.equal(ws.getCell("A2")); + expect(ws.getCell('B2').value).to.equal(5); + expect(ws.getCell('B2').type).to.equal(Excel.ValueType.Merge); + expect(ws.getCell('B2').master).to.equal(ws.getCell('A2')); - expect(ws.getCell("B3").value).to.equal(5); - expect(ws.getCell("B3").type).to.equal(Excel.ValueType.Merge); - expect(ws.getCell("B3").master).to.equal(ws.getCell("A2")); + expect(ws.getCell('B3').value).to.equal(5); + expect(ws.getCell('B3').type).to.equal(Excel.ValueType.Merge); + expect(ws.getCell('B3').master).to.equal(ws.getCell('A2')); // C2:D3 - expect(ws.getCell("C2").value).to.be.null; - expect(ws.getCell("C2").type).to.equal(Excel.ValueType.Null); - expect(ws.getCell("C2").master).to.equal(ws.getCell("C2")); + expect(ws.getCell('C2').value).to.be.null; + expect(ws.getCell('C2').type).to.equal(Excel.ValueType.Null); + expect(ws.getCell('C2').master).to.equal(ws.getCell('C2')); - expect(ws.getCell("D2").value).to.be.null; - expect(ws.getCell("D2").type).to.equal(Excel.ValueType.Merge); - expect(ws.getCell("D2").master).to.equal(ws.getCell("C2")); + expect(ws.getCell('D2').value).to.be.null; + expect(ws.getCell('D2').type).to.equal(Excel.ValueType.Merge); + expect(ws.getCell('D2').master).to.equal(ws.getCell('C2')); - expect(ws.getCell("C3").value).to.be.null; - expect(ws.getCell("C3").type).to.equal(Excel.ValueType.Merge); - expect(ws.getCell("C3").master).to.equal(ws.getCell("C2")); + expect(ws.getCell('C3').value).to.be.null; + expect(ws.getCell('C3').type).to.equal(Excel.ValueType.Merge); + expect(ws.getCell('C3').master).to.equal(ws.getCell('C2')); - expect(ws.getCell("D3").value).to.be.null; - expect(ws.getCell("D3").type).to.equal(Excel.ValueType.Merge); - expect(ws.getCell("D3").master).to.equal(ws.getCell("C2")); + expect(ws.getCell('D3').value).to.be.null; + expect(ws.getCell('D3').type).to.equal(Excel.ValueType.Merge); + expect(ws.getCell('D3').master).to.equal(ws.getCell('C2')); } if (checkStyles) { - expect(ws.getCell("A4").numFmt).to.equal(utils.testValues.numFmt1); - expect(ws.getCell("A4").type).to.equal(Excel.ValueType.Number); - expect(ws.getCell("A4").border).to.deep.equal(utils.styles.borders.thin); - expect(ws.getCell("C4").numFmt).to.equal(utils.testValues.numFmt2); - expect(ws.getCell("C4").type).to.equal(Excel.ValueType.Number); - expect(ws.getCell("C4").border).to.deep.equal(utils.styles.borders.doubleRed); - expect(ws.getCell("E4").border).to.deep.equal(utils.styles.borders.thickRainbow); + expect(ws.getCell('A4').numFmt).to.equal(utils.testValues.numFmt1); + expect(ws.getCell('A4').type).to.equal(Excel.ValueType.Number); + expect(ws.getCell('A4').border).to.deep.equal(utils.styles.borders.thin); + expect(ws.getCell('C4').numFmt).to.equal(utils.testValues.numFmt2); + expect(ws.getCell('C4').type).to.equal(Excel.ValueType.Number); + expect(ws.getCell('C4').border).to.deep.equal(utils.styles.borders.doubleRed); + expect(ws.getCell('E4').border).to.deep.equal(utils.styles.borders.thickRainbow); // test fonts and formats - expect(ws.getCell("A5").value).to.equal(utils.testValues.str); - expect(ws.getCell("A5").type).to.equal(Excel.ValueType.String); - expect(ws.getCell("A5").font).to.deep.equal(utils.styles.fonts.arialBlackUI14); - expect(ws.getCell("B5").value).to.equal(utils.testValues.str); - expect(ws.getCell("B5").type).to.equal(Excel.ValueType.String); - expect(ws.getCell("B5").font).to.deep.equal(utils.styles.fonts.broadwayRedOutline20); - expect(ws.getCell("C5").value).to.equal(utils.testValues.str); - expect(ws.getCell("C5").type).to.equal(Excel.ValueType.String); - expect(ws.getCell("C5").font).to.deep.equal(utils.styles.fonts.comicSansUdB16); - - expect(Math.abs(ws.getCell("D5").value - 1.6)).to.be.below(0.00000001); - expect(ws.getCell("D5").type).to.equal(Excel.ValueType.Number); - expect(ws.getCell("D5").numFmt).to.equal(utils.testValues.numFmt1); - expect(ws.getCell("D5").font).to.deep.equal(utils.styles.fonts.arialBlackUI14); - - expect(Math.abs(ws.getCell("E5").value - 1.6)).to.be.below(0.00000001); - expect(ws.getCell("E5").type).to.equal(Excel.ValueType.Number); - expect(ws.getCell("E5").numFmt).to.equal(utils.testValues.numFmt2); - expect(ws.getCell("E5").font).to.deep.equal(utils.styles.fonts.broadwayRedOutline20); - - expect(Math.abs(ws.getCell("F5").value.getTime() - utils.testValues.date.getTime())).to.be.below(dateAccuracy); - expect(ws.getCell("F5").type).to.equal(Excel.ValueType.Date); - expect(ws.getCell("F5").numFmt).to.equal(utils.testValues.numFmtDate); - expect(ws.getCell("F5").font).to.deep.equal(utils.styles.fonts.comicSansUdB16); + expect(ws.getCell('A5').value).to.equal(utils.testValues.str); + expect(ws.getCell('A5').type).to.equal(Excel.ValueType.String); + expect(ws.getCell('A5').font).to.deep.equal(utils.styles.fonts.arialBlackUI14); + expect(ws.getCell('B5').value).to.equal(utils.testValues.str); + expect(ws.getCell('B5').type).to.equal(Excel.ValueType.String); + expect(ws.getCell('B5').font).to.deep.equal(utils.styles.fonts.broadwayRedOutline20); + expect(ws.getCell('C5').value).to.equal(utils.testValues.str); + expect(ws.getCell('C5').type).to.equal(Excel.ValueType.String); + expect(ws.getCell('C5').font).to.deep.equal(utils.styles.fonts.comicSansUdB16); + + expect(Math.abs(ws.getCell('D5').value - 1.6)).to.be.below(0.00000001); + expect(ws.getCell('D5').type).to.equal(Excel.ValueType.Number); + expect(ws.getCell('D5').numFmt).to.equal(utils.testValues.numFmt1); + expect(ws.getCell('D5').font).to.deep.equal(utils.styles.fonts.arialBlackUI14); + + expect(Math.abs(ws.getCell('E5').value - 1.6)).to.be.below(0.00000001); + expect(ws.getCell('E5').type).to.equal(Excel.ValueType.Number); + expect(ws.getCell('E5').numFmt).to.equal(utils.testValues.numFmt2); + expect(ws.getCell('E5').font).to.deep.equal(utils.styles.fonts.broadwayRedOutline20); + + expect(Math.abs(ws.getCell('F5').value.getTime() - utils.testValues.date.getTime())).to.be.below(dateAccuracy); + expect(ws.getCell('F5').type).to.equal(Excel.ValueType.Date); + expect(ws.getCell('F5').numFmt).to.equal(utils.testValues.numFmtDate); + expect(ws.getCell('F5').font).to.deep.equal(utils.styles.fonts.comicSansUdB16); expect(ws.getRow(5).height).to.be.undefined; expect(ws.getRow(6).height).to.equal(42); @@ -377,5 +380,153 @@ var utils = module.exports = { expect(row8.getCell(3).fill).to.deep.equal(utils.styles.fills.redGreenDarkTrellis); expect(row8.getCell(4).fill).to.deep.equal(utils.styles.fills.rgbPathGrad); } + }, + + checkTestBookReader: function(filename) { + var wb = new Excel.stream.xlsx.WorkbookReader(); + + // expectations + var dateAccuracy = 3; + + var deferred = Bluebird.defer(); + + wb.on('worksheet', function(ws) { + console.log('Worksheet', ws.name); + // Sheet name stored in workbook. Not guaranteed here + // expect(ws.name).to.equal('blort'); + ws.on('row', function(row) { + console.log('WB Reader row', row.number) + switch(row.number) { + case 1: + expect(row.getCell('A').value).to.equal(7); + expect(row.getCell('A').type).to.equal(Excel.ValueType.Number); + expect(row.getCell('B').value).to.equal(utils.testValues.str); + expect(row.getCell('B').type).to.equal(Excel.ValueType.String); + expect(Math.abs(row.getCell('C').value.getTime() - utils.testValues.date.getTime())).to.be.below(dateAccuracy); + expect(row.getCell('C').type).to.equal(Excel.ValueType.Date); + + expect(row.getCell('D').value).to.deep.equal(utils.testValues.formulas[0]); + expect(row.getCell('D').type).to.equal(Excel.ValueType.Formula); + expect(row.getCell('E').value).to.deep.equal(utils.testValues.formulas[1]); + expect(row.getCell('E').type).to.equal(Excel.ValueType.Formula); + expect(row.getCell('F').value).to.deep.equal(utils.testValues.hyperlink); + expect(row.getCell('F').type).to.equal(Excel.ValueType.Hyperlink); + expect(row.getCell('G').value).to.equal(utils.testValues.str2); + break; + + case 2: + // A2:B3 + expect(row.getCell('A').value).to.equal(5); + expect(row.getCell('A').type).to.equal(Excel.ValueType.Number); + //expect(row.getCell('A').master).to.equal(ws.getCell('A2')); + + expect(row.getCell('B').value).to.equal(5); + expect(row.getCell('B').type).to.equal(Excel.ValueType.Merge); + //expect(row.getCell('B').master).to.equal(ws.getCell('A2')); + + // C2:D3 + expect(row.getCell('C').value).to.be.null; + expect(row.getCell('C').type).to.equal(Excel.ValueType.Null); + //expect(row.getCell('C').master).to.equal(ws.getCell('C2')); + + expect(row.getCell('D').value).to.be.null; + expect(row.getCell('D').type).to.equal(Excel.ValueType.Merge); + //expect(row.getCell('D').master).to.equal(ws.getCell('C2')); + + break; + + case 3: + expect(row.getCell('A').value).to.equal(5); + expect(row.getCell('A').type).to.equal(Excel.ValueType.Merge); + //expect(row.getCell('A').master).to.equal(ws.getCell('A2')); + + expect(row.getCell('B').value).to.equal(5); + expect(row.getCell('B').type).to.equal(Excel.ValueType.Merge); + //expect(row.getCell('B').master).to.equal(ws.getCell('A2')); + + expect(row.getCell('C').value).to.be.null; + expect(row.getCell('C').type).to.equal(Excel.ValueType.Merge); + //expect(row.getCell('C').master).to.equal(ws.getCell('C2')); + + expect(row.getCell('D').value).to.be.null; + expect(row.getCell('D').type).to.equal(Excel.ValueType.Merge); + //expect(row.getCell('D').master).to.equal(ws.getCell('C2')); + break; + + case 4: + expect(row.getCell('A').numFmt).to.equal(utils.testValues.numFmt1); + expect(row.getCell('A').type).to.equal(Excel.ValueType.Number); + expect(row.getCell('A').border).to.deep.equal(utils.styles.borders.thin); + expect(row.getCell('C').numFmt).to.equal(utils.testValues.numFmt2); + expect(row.getCell('C').type).to.equal(Excel.ValueType.Number); + expect(row.getCell('C').border).to.deep.equal(utils.styles.borders.doubleRed); + expect(row.getCell('E').border).to.deep.equal(utils.styles.borders.thickRainbow); + break; + + case 5: + // test fonts and formats + expect(row.getCell('A').value).to.equal(utils.testValues.str); + expect(row.getCell('A').type).to.equal(Excel.ValueType.String); + expect(row.getCell('A').font).to.deep.equal(utils.styles.fonts.arialBlackUI14); + expect(row.getCell('B').value).to.equal(utils.testValues.str); + expect(row.getCell('B').type).to.equal(Excel.ValueType.String); + expect(row.getCell('B').font).to.deep.equal(utils.styles.fonts.broadwayRedOutline20); + expect(row.getCell('C').value).to.equal(utils.testValues.str); + expect(row.getCell('C').type).to.equal(Excel.ValueType.String); + expect(row.getCell('C').font).to.deep.equal(utils.styles.fonts.comicSansUdB16); + + expect(Math.abs(row.getCell('D').value - 1.6)).to.be.below(0.00000001); + expect(row.getCell('D').type).to.equal(Excel.ValueType.Number); + expect(row.getCell('D').numFmt).to.equal(utils.testValues.numFmt1); + expect(row.getCell('D').font).to.deep.equal(utils.styles.fonts.arialBlackUI14); + + expect(Math.abs(row.getCell('E').value - 1.6)).to.be.below(0.00000001); + expect(row.getCell('E').type).to.equal(Excel.ValueType.Number); + expect(row.getCell('E').numFmt).to.equal(utils.testValues.numFmt2); + expect(row.getCell('E').font).to.deep.equal(utils.styles.fonts.broadwayRedOutline20); + + expect(Math.abs(ws.getCell('F5').value.getTime() - utils.testValues.date.getTime())).to.be.below(dateAccuracy); + expect(ws.getCell('F5').type).to.equal(Excel.ValueType.Date); + expect(ws.getCell('F5').numFmt).to.equal(utils.testValues.numFmtDate); + expect(ws.getCell('F5').font).to.deep.equal(utils.styles.fonts.comicSansUdB16); + expect(row.height).to.be.undefined; + break; + + case 6: + expect(ws.getRow(6).height).to.equal(42); + _.each(utils.styles.alignments, function(alignment, index) { + var colNumber = index + 1; + var cell = row.getCell(colNumber); + expect(cell.value).to.equal(alignment.text); + expect(cell.alignment).to.deep.equal(alignment.alignment); + }); + break; + + case 7: + _.each(utils.styles.badAlignments, function(alignment, index) { + var colNumber = index + 1; + var cell = row.getCell(colNumber); + expect(cell.value).to.equal(alignment.text); + expect(cell.alignment).to.be.undefined; + }); + break; + + case 8: + expect(row.height).to.equal(40); + expect(row.getCell(1).fill).to.deep.equal(utils.styles.fills.blueWhiteHGrad); + expect(row.getCell(2).fill).to.deep.equal(utils.styles.fills.redDarkVertical); + expect(row.getCell(3).fill).to.deep.equal(utils.styles.fills.redGreenDarkTrellis); + expect(row.getCell(4).fill).to.deep.equal(utils.styles.fills.rgbPathGrad); + break; + } + }); + }); + wb.on('end', function() { + deferred.resolve(); + }); + + wb.read(filename, {entries: 'emit', worksheets: 'emit'}); + + return deferred.promise; } }; \ No newline at end of file diff --git a/spec/unit/doc/defined-names.spec.js b/spec/unit/doc/defined-names.spec.js index 3de482a28..201003259 100644 --- a/spec/unit/doc/defined-names.spec.js +++ b/spec/unit/doc/defined-names.spec.js @@ -12,6 +12,46 @@ describe('DefinedNames', function() { dn.add('blort!A1','foo'); expect(dn.getNames('blort!A1')).to.deep.equal(['foo']); + expect(dn.getNames('blort!$A$1')).to.deep.equal(['foo']); + + dn.add('blort!$B$4','bar'); + expect(dn.getNames('blort!B4')).to.deep.equal(['bar']); + expect(dn.getNames('blort!$B$4')).to.deep.equal(['bar']); + }); + + it('removes names for cells', function() { + var dn = new DefinedNames(); + + dn.add('blort!A1','foo'); + dn.add('blort!A1','bar'); + dn.remove('blort!A1','foo'); + + expect(dn.getNames('blort!A1')).to.deep.equal(['bar']); + }); + + // get ranges example + it('gets the right ranges for a name', function() { + var dn = new DefinedNames(); + + dn.add('blort!A1', 'vertical'); + dn.add('blort!A2', 'vertical'); + dn.add('blort!A3', 'vertical'); + + dn.add('blort!C1', 'horizontal'); + dn.add('blort!D1', 'horizontal'); + dn.add('blort!E1', 'horizontal'); + + dn.add('blort!C3', 'square'); + dn.add('blort!D3', 'square'); + dn.add('blort!C4', 'square'); + dn.add('blort!D4', 'square'); + + dn.add('other!A1', 'single'); + + expect(dn.getRanges('vertical')).to.deep.equal({name: 'vertical', ranges: ['blort!$A$1:$A$3']}); + expect(dn.getRanges('horizontal')).to.deep.equal({name: 'horizontal', ranges: ['blort!$C$1:$E$1']}); + expect(dn.getRanges('square')).to.deep.equal({name: 'square', ranges: ['blort!$C$3:$D$4']}); + expect(dn.getRanges('single')).to.deep.equal({name: 'single', ranges: ['other!$A$1']}); }); }); \ No newline at end of file diff --git a/test/testBigBookIn.js b/test/testBigBookIn.js index 31cb86bbe..3cb9c0940 100644 --- a/test/testBigBookIn.js +++ b/test/testBigBookIn.js @@ -1,3 +1,5 @@ +'use strict'; + var fs = require('fs'); var util = require('util'); var _ = require('underscore'); @@ -11,120 +13,120 @@ var Excel = require('../excel'); var Workbook = Excel.Workbook; var WorkbookReader = Excel.stream.xlsx.WorkbookReader; -if (process.argv[2] == 'help') { - console.log("Usage:"); - console.log(" node testBigBookIn filename reader plan"); - console.log("Where:"); - console.log(" reader is one of [stream, document]"); - console.log(" plan is one of [zero, one, two, hyperlinks]"); - process.exit(0); +if (process.argv[2] === 'help') { + console.log('Usage:'); + console.log(' node testBigBookIn filename reader plan'); + console.log('Where:'); + console.log(' reader is one of [stream, document]'); + console.log(' plan is one of [zero, one, two, hyperlinks]'); + process.exit(0); } var filename = process.argv[2]; -var reader = process.argv.length > 3 ? process.argv[3] : "stream"; -var plan = process.argv.length > 4 ? process.argv[4] : "one"; +var reader = process.argv.length > 3 ? process.argv[3] : 'stream'; +var plan = process.argv.length > 4 ? process.argv[4] : 'one'; -var useStream = (reader === "stream"); +var useStream = (reader === 'stream'); function getTimeout() { - var memory = process.memoryUsage(); - var heapSize = memory.heapTotal; - if (heapSize < 300000000) { - return 0; - } - if (heapSize < 600000000) { - return heapSize / 5000000; - } - if (heapSize < 1000000000) { - return heapSize / 2000000; - } - return heapSize / 1000000; + var memory = process.memoryUsage(); + var heapSize = memory.heapTotal; + if (heapSize < 300000000) { + return 0; + } + if (heapSize < 600000000) { + return heapSize / 5000000; + } + if (heapSize < 1000000000) { + return heapSize / 2000000; + } + return heapSize / 1000000; } var options = { - reader: (useStream ? "stream" : "document"), - filename: filename, - plan: plan, - gc: { - getTimeout: getTimeout - } + reader: (useStream ? 'stream' : 'document'), + filename: filename, + plan: plan, + gc: { + getTimeout: getTimeout + } }; -console.log(JSON.stringify(options, null, " ")); +console.log(JSON.stringify(options, null, ' ')); var stopwatch = new HrStopwatch(); stopwatch.start(); function logProgress(count) { - var memory = process.memoryUsage(); - var txtCount = utils.fmt.number(count); - var txtHeap = utils.fmt.number(memory.heapTotal); - process.stdout.write("Count: " + txtCount + ", Heap Size: " + txtHeap + "\u001b[0G"); + var memory = process.memoryUsage(); + var txtCount = utils.fmt.number(count); + var txtHeap = utils.fmt.number(memory.heapTotal); + process.stdout.write('Count: ' + txtCount + ', Heap Size: ' + txtHeap + '\u001b[0G'); } var colCount = new ColumnSum([3,6,7,8]); var hyperlinkCount = 0; function checkRow(row) { - if (row.number > 1) { - colCount.add(row); - - if (colCount.count % 1000 === 0) { - logProgress(colCount.count); - } + if (row.number > 1) { + colCount.add(row); + + if (colCount.count % 1000 === 0) { + logProgress(colCount.count); } - row.destroy(); + } + row.destroy(); } function report() { - console.log("Count: " + colCount.count); - console.log("Sums: " + colCount); - console.log("Hyperlinks: " + hyperlinkCount); - - stopwatch.stop(); - console.log("Time: " + stopwatch); + console.log('Count: ' + colCount.count); + console.log('Sums: ' + colCount); + console.log('Hyperlinks: ' + hyperlinkCount); + + stopwatch.stop(); + console.log('Time: ' + stopwatch); } if (useStream) { - var wb = new WorkbookReader(options); - wb.on("end", function() { console.log("reached end of stream");}); - wb.on("finished", report); - wb.on("worksheet", function(worksheet) { - worksheet.on("row", checkRow); - }); - wb.on("hyperlinks", function(hyperlinks) { - hyperlinks.on("hyperlink", function(hyperlink) { - hyperlinkCount++; - }); + var wb = new WorkbookReader(options); + wb.on('end', function() { console.log('reached end of stream');}); + wb.on('finished', report); + wb.on('worksheet', function(worksheet) { + worksheet.on('row', checkRow); + }); + wb.on('hyperlinks', function(hyperlinks) { + hyperlinks.on('hyperlink', function(hyperlink) { + hyperlinkCount++; }); - wb.on("entry", function(entry) { - console.log(JSON.stringify(entry)); - }); - switch (options.plan) { - case "zero": - wb.read(filename, { - entries: "emit" - }); - break; - case "one": - wb.read(filename, { - entries: "emit", - worksheets: "emit" - }); - break; - case "two": - break; - case "hyperlinks": - wb.read(filename, { - hyperlinks: "emit" - }); - break; - } + }); + wb.on('entry', function(entry) { + console.log(JSON.stringify(entry)); + }); + switch (options.plan) { + case 'zero': + wb.read(filename, { + entries: 'emit' + }); + break; + case 'one': + wb.read(filename, { + entries: 'emit', + worksheets: 'emit' + }); + break; + case 'two': + break; + case 'hyperlinks': + wb.read(filename, { + hyperlinks: 'emit' + }); + break; + } } else { - var wb = new Workbook(); - wb.xlsx.readFile(filename) - .then(function() { - var ws = wb.getWorksheet("blort"); - ws.eachRow(checkRow); - }) - .then(report); + var wb = new Workbook(); + wb.xlsx.readFile(filename) + .then(function() { + var ws = wb.getWorksheet('blort'); + ws.eachRow(checkRow); + }) + .then(report); }