@elbstack/xlsx-populate
Version:
Excel XLSX parser/generator written in JavaScript with Node.js and browser support, jQuery/d3-style method chaining, and a focus on keeping existing workbook features and styles in tact.
1,367 lines (1,143 loc) • 4.94 MB
JavaScript
(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.XlsxPopulate = 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 _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _ = require("lodash");
var xmlq = require("./xmlq");
var ArgHandler = require("./ArgHandler");
/**
* App properties
* @ignore
*/
var AppProperties = function () {
/**
* Creates a new instance of AppProperties
* @param {{}} node - The node.
*/
function AppProperties(node) {
_classCallCheck(this, AppProperties);
this._node = node;
}
_createClass(AppProperties, [{
key: "isSecure",
value: function isSecure(value) {
var _this = this;
return new ArgHandler("Range.formula").case(function () {
var docSecurityNode = xmlq.findChild(_this._node, "DocSecurity");
if (!docSecurityNode) return false;
return docSecurityNode.children[0] === 1;
}).case('boolean', function (value) {
var docSecurityNode = xmlq.appendChildIfNotFound(_this._node, "DocSecurity");
docSecurityNode.children = [value ? 1 : 0];
return _this;
}).handle(arguments);
}
/**
* Convert the collection to an XML object.
* @returns {{}} The XML.
*/
}, {
key: "toXml",
value: function toXml() {
return this._node;
}
}]);
return AppProperties;
}();
module.exports = AppProperties;
/*
docProps/app.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
<Application>Microsoft Excel</Application>
<DocSecurity>1</DocSecurity>
<ScaleCrop>false</ScaleCrop>
<HeadingPairs>
<vt:vector size="2" baseType="variant">
<vt:variant>
<vt:lpstr>Worksheets</vt:lpstr>
</vt:variant>
<vt:variant>
<vt:i4>1</vt:i4>
</vt:variant>
</vt:vector>
</HeadingPairs>
<TitlesOfParts>
<vt:vector size="1" baseType="lpstr">
<vt:lpstr>Sheet1</vt:lpstr>
</vt:vector>
</TitlesOfParts>
<Company/>
<LinksUpToDate>false</LinksUpToDate>
<SharedDoc>false</SharedDoc>
<HyperlinksChanged>false</HyperlinksChanged>
<AppVersion>16.0300</AppVersion>
</Properties>
*/
},{"./ArgHandler":2,"./xmlq":26,"lodash":191}],2:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _ = require("lodash");
/**
* Method argument handler. Used for overloading methods.
* @private
*/
var ArgHandler = function () {
/**
* Creates a new instance of ArgHandler.
* @param {string} name - The method name to use in error messages.
*/
function ArgHandler(name) {
_classCallCheck(this, ArgHandler);
this._name = name;
this._cases = [];
}
/**
* Add a case.
* @param {string|Array.<string>} [types] - The type or types of arguments to match this case.
* @param {Function} handler - The function to call when this case is matched.
* @returns {ArgHandler} The handler for chaining.
*/
_createClass(ArgHandler, [{
key: "case",
value: function _case(types, handler) {
if (arguments.length === 1) {
handler = types;
types = [];
}
if (!Array.isArray(types)) types = [types];
this._cases.push({ types: types, handler: handler });
return this;
}
/**
* Handle the method arguments by checking each case in order until one matches and then call its handler.
* @param {Arguments|Array.<*>} args - The method arguments.
* @returns {*} The result of the handler.
* @throws {Error} Throws if no case matches.
*/
}, {
key: "handle",
value: function handle(args) {
for (var i = 0; i < this._cases.length; i++) {
var c = this._cases[i];
if (this._argsMatchTypes(args, c.types)) {
return c.handler.apply(null, args);
}
}
throw new Error(this._name + ": Invalid arguments.");
}
/**
* Check if the arguments match the given types.
* @param {Arguments} args - The arguments.
* @param {Array.<string>} types - The types.
* @returns {boolean} True if matches, false otherwise.
* @throws {Error} Throws if unknown type.
* @private
*/
}, {
key: "_argsMatchTypes",
value: function _argsMatchTypes(args, types) {
if (args.length !== types.length) return false;
return _.every(args, function (arg, i) {
var type = types[i];
if (type === '*') return true;
if (type === 'nil') return _.isNil(arg);
if (type === 'string') return typeof arg === "string";
if (type === 'boolean') return typeof arg === "boolean";
if (type === 'number') return typeof arg === "number";
if (type === 'integer') return typeof arg === "number" && _.isInteger(arg);
if (type === 'function') return typeof arg === "function";
if (type === 'array') return Array.isArray(arg);
if (type === 'date') return arg && arg.constructor === Date;
if (type === 'object') return arg && arg.constructor === Object;
if (arg && arg.constructor && arg.constructor.name === type) return true;
throw new Error("Unknown type: " + type);
});
}
}]);
return ArgHandler;
}();
module.exports = ArgHandler;
},{"lodash":191}],3:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _ = require("lodash");
var ArgHandler = require("./ArgHandler");
var addressConverter = require("./addressConverter");
var dateConverter = require("./dateConverter");
var regexify = require("./regexify");
var xmlq = require("./xmlq");
var FormulaError = require("./FormulaError");
var Style = require("./Style");
/**
* A cell
*/
var Cell = function () {
// /**
// * Creates a new instance of cell.
// * @param {Row} row - The parent row.
// * @param {{}} node - The cell node.
// */
function Cell(row, node, styleId) {
_classCallCheck(this, Cell);
this._row = row;
this._init(node, styleId);
}
/* PUBLIC */
/**
* Gets a value indicating whether the cell is the active cell in the sheet.
* @returns {boolean} True if active, false otherwise.
*/ /**
* Make the cell the active cell in the sheet.
* @param {boolean} active - Must be set to `true`. Deactivating directly is not supported. To deactivate, you should activate a different cell instead.
* @returns {Cell} The cell.
*/
_createClass(Cell, [{
key: "active",
value: function active() {
var _this = this;
return new ArgHandler('Cell.active').case(function () {
return _this.sheet().activeCell() === _this;
}).case('boolean', function (active) {
if (!active) throw new Error("Deactivating cell directly not supported. Activate a different cell instead.");
_this.sheet().activeCell(_this);
return _this;
}).handle(arguments);
}
/**
* Get the address of the column.
* @param {{}} [opts] - Options
* @param {boolean} [opts.includeSheetName] - Include the sheet name in the address.
* @param {boolean} [opts.rowAnchored] - Anchor the row.
* @param {boolean} [opts.columnAnchored] - Anchor the column.
* @param {boolean} [opts.anchored] - Anchor both the row and the column.
* @returns {string} The address
*/
}, {
key: "address",
value: function address(opts) {
return addressConverter.toAddress({
type: 'cell',
rowNumber: this.rowNumber(),
columnNumber: this.columnNumber(),
sheetName: opts && opts.includeSheetName && this.sheet().name(),
rowAnchored: opts && (opts.rowAnchored || opts.anchored),
columnAnchored: opts && (opts.columnAnchored || opts.anchored)
});
}
/**
* Gets the parent column of the cell.
* @returns {Column} The parent column.
*/
}, {
key: "column",
value: function column() {
return this.sheet().column(this.columnNumber());
}
/**
* Clears the contents from the cell.
* @returns {Cell} The cell.
*/
}, {
key: "clear",
value: function clear() {
var hostSharedFormulaId = this._formulaRef && this._sharedFormulaId;
delete this._value;
delete this._formulaType;
delete this._formula;
delete this._sharedFormulaId;
delete this._formulaRef;
// TODO in future version: Move shared formula to some other cell. This would require parsing the formula...
if (!_.isNil(hostSharedFormulaId)) this.sheet().clearCellsUsingSharedFormula(hostSharedFormulaId);
return this;
}
/**
* Gets the column name of the cell.
* @returns {number} The column name.
*/
}, {
key: "columnName",
value: function columnName() {
return addressConverter.columnNumberToName(this.columnNumber());
}
/**
* Gets the column number of the cell (1-based).
* @returns {number} The column number.
*/
}, {
key: "columnNumber",
value: function columnNumber() {
return this._columnNumber;
}
/**
* Find the given pattern in the cell and optionally replace it.
* @param {string|RegExp} pattern - The pattern to look for. Providing a string will result in a case-insensitive substring search. Use a RegExp for more sophisticated searches.
* @param {string|function} [replacement] - The text to replace or a String.replace callback function. If pattern is a string, all occurrences of the pattern in the cell will be replaced.
* @returns {boolean} A flag indicating if the pattern was found.
*/
}, {
key: "find",
value: function find(pattern, replacement) {
pattern = regexify(pattern);
var value = this.value();
if (typeof value !== 'string') return false;
if (_.isNil(replacement)) {
return pattern.test(value);
} else {
var replaced = value.replace(pattern, replacement);
if (replaced === value) return false;
this.value(replaced);
return true;
}
}
/**
* Gets the formula in the cell. Note that if a formula was set as part of a range, the getter will return 'SHARED'. This is a limitation that may be addressed in a future release.
* @returns {string} The formula in the cell.
*/ /**
* Sets the formula in the cell.
* @param {string} formula - The formula to set.
* @returns {Cell} The cell.
*/
}, {
key: "formula",
value: function formula() {
var _this2 = this;
return new ArgHandler('Cell.formula').case(function () {
// TODO in future: Return translated formula.
if (_this2._formulaType === "shared" && !_this2._formulaRef) return "SHARED";
return _this2._formula;
}).case('nil', function () {
_this2.clear();
return _this2;
}).case('string', function (formula) {
_this2.clear();
_this2._formulaType = "normal";
_this2._formula = formula;
return _this2;
}).handle(arguments);
}
/**
* Gets the hyperlink attached to the cell.
* @returns {string|undefined} The hyperlink or undefined if not set.
*/ /**
* Set or clear the hyperlink on the cell.
* @param {string|undefined} hyperlink - The hyperlink to set or undefined to clear.
* @returns {Cell} The cell.
*/
}, {
key: "hyperlink",
value: function hyperlink() {
var _this3 = this;
return new ArgHandler('Cell.hyperlink').case(function () {
return _this3.sheet().hyperlink(_this3.address());
}).case('*', function (hyperlink) {
_this3.sheet().hyperlink(_this3.address(), hyperlink);
return _this3;
}).handle(arguments);
}
/**
* Gets the data validation object attached to the cell.
* @returns {object|undefined} The data validation or undefined if not set.
*/ /**
* Set or clear the data validation object of the cell.
* @param {object|undefined} dataValidation - Object or null to clear.
* @returns {Cell} The cell.
*/
}, {
key: "dataValidation",
value: function dataValidation() {
var _this4 = this;
return new ArgHandler('Cell.dataValidation').case(function () {
return _this4.sheet().dataValidation(_this4.address());
}).case('boolean', function (obj) {
return _this4.sheet().dataValidation(_this4.address(), obj);
}).case('*', function (obj) {
_this4.sheet().dataValidation(_this4.address(), obj);
return _this4;
}).handle(arguments);
}
/**
* Callback used by tap.
* @callback Cell~tapCallback
* @param {Cell} cell - The cell
* @returns {undefined}
*/
/**
* Invoke a callback on the cell and return the cell. Useful for method chaining.
* @param {Cell~tapCallback} callback - The callback function.
* @returns {Cell} The cell.
*/
}, {
key: "tap",
value: function tap(callback) {
callback(this);
return this;
}
/**
* Callback used by thru.
* @callback Cell~thruCallback
* @param {Cell} cell - The cell
* @returns {*} The value to return from thru.
*/
/**
* Invoke a callback on the cell and return the value provided by the callback. Useful for method chaining.
* @param {Cell~thruCallback} callback - The callback function.
* @returns {*} The return value of the callback.
*/
}, {
key: "thru",
value: function thru(callback) {
return callback(this);
}
/**
* Create a range from this cell and another.
* @param {Cell|string} cell - The other cell or cell address to range to.
* @returns {Range} The range.
*/
}, {
key: "rangeTo",
value: function rangeTo(cell) {
return this.sheet().range(this, cell);
}
/**
* Returns a cell with a relative position given the offsets provided.
* @param {number} rowOffset - The row offset (0 for the current row).
* @param {number} columnOffset - The column offset (0 for the current column).
* @returns {Cell} The relative cell.
*/
}, {
key: "relativeCell",
value: function relativeCell(rowOffset, columnOffset) {
var row = rowOffset + this.rowNumber();
var column = columnOffset + this.columnNumber();
return this.sheet().cell(row, column);
}
/**
* Gets the parent row of the cell.
* @returns {Row} The parent row.
*/
}, {
key: "row",
value: function row() {
return this._row;
}
/**
* Gets the row number of the cell (1-based).
* @returns {number} The row number.
*/
}, {
key: "rowNumber",
value: function rowNumber() {
return this.row().rowNumber();
}
/**
* Gets the parent sheet.
* @returns {Sheet} The parent sheet.
*/
}, {
key: "sheet",
value: function sheet() {
return this.row().sheet();
}
/**
* Gets an individual style.
* @param {string} name - The name of the style.
* @returns {*} The style.
*/ /**
* Gets multiple styles.
* @param {Array.<string>} names - The names of the style.
* @returns {object.<string, *>} Object whose keys are the style names and values are the styles.
*/ /**
* Sets an individual style.
* @param {string} name - The name of the style.
* @param {*} value - The value to set.
* @returns {Cell} The cell.
*/ /**
* Sets the styles in the range starting with the cell.
* @param {string} name - The name of the style.
* @param {Array.<Array.<*>>} - 2D array of values to set.
* @returns {Range} The range that was set.
*/ /**
* Sets multiple styles.
* @param {object.<string, *>} styles - Object whose keys are the style names and values are the styles to set.
* @returns {Cell} The cell.
*/ /**
* Sets to a specific style
* @param {Style} style - Style object given from stylesheet.createStyle
* @returns {Cell} The cell.
*/
}, {
key: "style",
value: function style() {
var _this5 = this;
if (!this._style && !(arguments[0] instanceof Style)) {
this._style = this.workbook().styleSheet().createStyle(this._styleId);
}
return new ArgHandler("Cell.style").case('string', function (name) {
// Get single value
return _this5._style.style(name);
}).case('array', function (names) {
// Get list of values
var values = {};
names.forEach(function (name) {
values[name] = _this5.style(name);
});
return values;
}).case(["string", "array"], function (name, values) {
var numRows = values.length;
var numCols = values[0].length;
var range = _this5.rangeTo(_this5.relativeCell(numRows - 1, numCols - 1));
return range.style(name, values);
}).case(['string', '*'], function (name, value) {
// Set a single value for all cells to a single value
_this5._style.style(name, value);
return _this5;
}).case('object', function (nameValues) {
// Object of key value pairs to set
for (var name in nameValues) {
if (!nameValues.hasOwnProperty(name)) continue;
var value = nameValues[name];
_this5.style(name, value);
}
return _this5;
}).case('Style', function (style) {
_this5._style = style;
_this5._styleId = style.id();
return _this5;
}).handle(arguments);
}
/**
* Gets the value of the cell.
* @returns {string|boolean|number|Date|undefined} The value of the cell.
*/ /**
* Sets the value of the cell.
* @param {string|boolean|number|null|undefined} value - The value to set.
* @returns {Cell} The cell.
*/ /**
* Sets the values in the range starting with the cell.
* @param {Array.<Array.<string|boolean|number|null|undefined>>} - 2D array of values to set.
* @returns {Range} The range that was set.
*/
}, {
key: "value",
value: function value() {
var _this6 = this;
return new ArgHandler('Cell.value').case(function () {
return _this6._value;
}).case("array", function (values) {
var numRows = values.length;
var numCols = values[0].length;
var range = _this6.rangeTo(_this6.relativeCell(numRows - 1, numCols - 1));
return range.value(values);
}).case('*', function (value) {
_this6.clear();
_this6._value = value;
return _this6;
}).handle(arguments);
}
/**
* Gets the parent workbook.
* @returns {Workbook} The parent workbook.
*/
}, {
key: "workbook",
value: function workbook() {
return this.row().workbook();
}
/* INTERNAL */
/**
* Gets the formula if a shared formula ref cell.
* @returns {string|undefined} The formula.
* @ignore
*/
}, {
key: "getSharedRefFormula",
value: function getSharedRefFormula() {
return this._formulaType === "shared" ? this._formulaRef && this._formula : undefined;
}
/**
* Check if this cell uses a given shared a formula ID.
* @param {number} id - The shared formula ID.
* @returns {boolean} A flag indicating if shared.
* @ignore
*/
}, {
key: "sharesFormula",
value: function sharesFormula(id) {
return this._formulaType === "shared" && this._sharedFormulaId === id;
}
/**
* Set a shared formula on the cell.
* @param {number} id - The shared formula index.
* @param {string} [formula] - The formula (if the reference cell).
* @param {string} [sharedRef] - The address of the shared range (if the reference cell).
* @returns {undefined}
* @ignore
*/
}, {
key: "setSharedFormula",
value: function setSharedFormula(id, formula, sharedRef) {
this.clear();
this._formulaType = "shared";
this._sharedFormulaId = id;
this._formula = formula;
this._formulaRef = sharedRef;
}
/**
* Convert the cell to an XML object.
* @returns {{}} The XML form.
* @ignore
*/
}, {
key: "toXml",
value: function toXml() {
// Create a node.
var node = {
name: 'c',
attributes: this._remainingAttributes || {}, // Start with any remaining attributes we don't current handle.
children: []
};
// Set the address.
node.attributes.r = this.address();
if (!_.isNil(this._formulaType)) {
// Add the formula.
var fNode = {
name: 'f',
attributes: this._remainingFormulaAttributes || {}
};
if (this._formulaType !== "normal") fNode.attributes.t = this._formulaType;
if (!_.isNil(this._formulaRef)) fNode.attributes.ref = this._formulaRef;
if (!_.isNil(this._sharedFormulaId)) fNode.attributes.si = this._sharedFormulaId;
if (!_.isNil(this._formula)) fNode.children = [this._formula];
node.children.push(fNode);
} else if (!_.isNil(this._value)) {
// Add the value. Don't emit value if a formula is set as Excel will show this stale value.
var type = void 0,
text = void 0;
if (typeof this._value === "string" || _.isArray(this._value)) {
// TODO: Rich text is array for now
type = "s";
text = this.workbook().sharedStrings().getIndexForString(this._value);
} else if (typeof this._value === "boolean") {
type = "b";
text = this._value ? 1 : 0;
} else if (typeof this._value === "number") {
text = this._value;
} else if (this._value instanceof Date) {
text = dateConverter.dateToNumber(this._value);
}
if (type) node.attributes.t = type;
var vNode = { name: 'v', children: [text] };
node.children.push(vNode);
}
// If the style is set, set the style ID.
if (!_.isNil(this._style)) {
node.attributes.s = this._style.id();
} else if (!_.isNil(this._styleId)) {
node.attributes.s = this._styleId;
}
// Add any remaining children that we don't currently handle.
if (this._remainingChildren) {
node.children = node.children.concat(this._remainingChildren);
}
return node;
}
/* PRIVATE */
/**
* Initialize the cell node.
* @param {{}|number} nodeOrColumnNumber - The existing node or the column number of a new cell.
* @param {number} [styleId] - The style ID for the new cell.
* @returns {undefined}
* @private
*/
}, {
key: "_init",
value: function _init(nodeOrColumnNumber, styleId) {
if (_.isObject(nodeOrColumnNumber)) {
// Parse the existing node.
this._parseNode(nodeOrColumnNumber);
} else {
// This is a new cell.
this._columnNumber = nodeOrColumnNumber;
if (!_.isNil(styleId)) this._styleId = styleId;
}
}
/**
* Parse the existing node.
* @param {{}} node - The existing node.
* @returns {undefined}
* @private
*/
}, {
key: "_parseNode",
value: function _parseNode(node) {
// Parse the column numbr out of the address.
var ref = addressConverter.fromAddress(node.attributes.r);
this._columnNumber = ref.columnNumber;
// Store the style ID if present.
if (!_.isNil(node.attributes.s)) this._styleId = node.attributes.s;
// Parse the formula if present..
var fNode = xmlq.findChild(node, 'f');
if (fNode) {
this._formulaType = fNode.attributes.t || "normal";
this._formulaRef = fNode.attributes.ref;
this._formula = fNode.children[0];
this._sharedFormulaId = fNode.attributes.si;
if (!_.isNil(this._sharedFormulaId)) {
// Update the sheet's max shared formula ID so we can set future IDs an index beyond this.
this.sheet().updateMaxSharedFormulaId(this._sharedFormulaId);
}
// Delete the known attributes.
delete fNode.attributes.t;
delete fNode.attributes.ref;
delete fNode.attributes.si;
// If any unknown attributes are still present, store them for later output.
if (!_.isEmpty(fNode.attributes)) this._remainingFormulaAttributes = fNode.attributes;
}
// Parse the value.
var type = node.attributes.t;
if (type === "s") {
// String value.
var sharedIndex = xmlq.findChild(node, 'v').children[0];
this._value = this.workbook().sharedStrings().getStringByIndex(sharedIndex);
} else if (type === "str") {
// Simple string value.
var vNode = xmlq.findChild(node, 'v');
this._value = vNode && vNode.children[0];
} else if (type === "inlineStr") {
// Inline string value: can be simple text or rich text.
var isNode = xmlq.findChild(node, 'is');
if (isNode.children[0].name === "t") {
var tNode = isNode.children[0];
this._value = tNode.children[0];
} else {
this._value = isNode.children;
}
} else if (type === "b") {
// Boolean value.
this._value = xmlq.findChild(node, 'v').children[0] === 1;
} else if (type === "e") {
// Error value.
var error = xmlq.findChild(node, 'v').children[0];
this._value = FormulaError.getError(error);
} else {
// Number value.
var _vNode = xmlq.findChild(node, 'v');
this._value = _vNode && Number(_vNode.children[0]);
}
// Delete known attributes.
delete node.attributes.r;
delete node.attributes.s;
delete node.attributes.t;
// If any unknown attributes are still present, store them for later output.
if (!_.isEmpty(node.attributes)) this._remainingAttributes = node.attributes;
// Delete known children.
xmlq.removeChild(node, 'f');
xmlq.removeChild(node, 'v');
xmlq.removeChild(node, 'is');
// If any unknown children are still present, store them for later output.
if (!_.isEmpty(node.children)) this._remainingChildren = node.children;
}
}]);
return Cell;
}();
module.exports = Cell;
/*
<c r="A6" s="1" t="s">
<v>2</v>
</c>
*/
},{"./ArgHandler":2,"./FormulaError":8,"./Style":14,"./addressConverter":20,"./dateConverter":23,"./regexify":25,"./xmlq":26,"lodash":191}],4:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var ArgHandler = require("./ArgHandler");
var addressConverter = require('./addressConverter');
// Default column width.
var defaultColumnWidth = 9.140625;
/**
* A column.
*/
var Column = function () {
// /**
// * Creates a new Column.
// * @param {Sheet} sheet - The parent sheet.
// * @param {{}} node - The column node.
// * @constructor
// * @ignore
// * @private
// */
function Column(sheet, node) {
_classCallCheck(this, Column);
this._sheet = sheet;
this._node = node;
}
/* PUBLIC */
/**
* Get the address of the column.
* @param {{}} [opts] - Options
* @param {boolean} [opts.includeSheetName] - Include the sheet name in the address.
* @param {boolean} [opts.anchored] - Anchor the address.
* @returns {string} The address
*/
_createClass(Column, [{
key: "address",
value: function address(opts) {
return addressConverter.toAddress({
type: 'column',
columnName: this.columnName(),
sheetName: opts && opts.includeSheetName && this.sheet().name(),
columnAnchored: opts && opts.anchored
});
}
/**
* Get a cell within the column.
* @param {number} rowNumber - The row number.
* @returns {Cell} The cell in the column with the given row number.
*/
}, {
key: "cell",
value: function cell(rowNumber) {
return this.sheet().cell(rowNumber, this.columnNumber());
}
/**
* Get the name of the column.
* @returns {string} The column name.
*/
}, {
key: "columnName",
value: function columnName() {
return addressConverter.columnNumberToName(this.columnNumber());
}
/**
* Get the number of the column.
* @returns {number} The column number.
*/
}, {
key: "columnNumber",
value: function columnNumber() {
return this._node.attributes.min;
}
/**
* Gets a value indicating whether the column is hidden.
* @returns {boolean} A flag indicating whether the column is hidden.
*/ /**
* Sets whether the column is hidden.
* @param {boolean} hidden - A flag indicating whether to hide the column.
* @returns {Column} The column.
*/
}, {
key: "hidden",
value: function hidden() {
var _this = this;
return new ArgHandler("Column.hidden").case(function () {
return _this._node.attributes.hidden === 1;
}).case('boolean', function (hidden) {
if (hidden) _this._node.attributes.hidden = 1;else delete _this._node.attributes.hidden;
return _this;
}).handle(arguments);
}
/**
* Get the parent sheet.
* @returns {Sheet} The parent sheet.
*/
}, {
key: "sheet",
value: function sheet() {
return this._sheet;
}
/**
* Gets an individual style.
* @param {string} name - The name of the style.
* @returns {*} The style.
*/ /**
* Gets multiple styles.
* @param {Array.<string>} names - The names of the style.
* @returns {object.<string, *>} Object whose keys are the style names and values are the styles.
*/ /**
* Sets an individual style.
* @param {string} name - The name of the style.
* @param {*} value - The value to set.
* @returns {Cell} The cell.
*/ /**
* Sets multiple styles.
* @param {object.<string, *>} styles - Object whose keys are the style names and values are the styles to set.
* @returns {Cell} The cell.
*/ /**
* Sets to a specific style
* @param {Style} style - Style object given from stylesheet.createStyle
* @returns {Cell} The cell.
*/
}, {
key: "style",
value: function style() {
var _this2 = this;
return new ArgHandler("Column.style").case('string', function (name) {
// Get single value
_this2._createStyleIfNeeded();
return _this2._style.style(name);
}).case('array', function (names) {
// Get list of values
var values = {};
names.forEach(function (name) {
values[name] = _this2.style(name);
});
return values;
}).case(['string', '*'], function (name, value) {
// If a row node is already defined that intersects with this column and that row has a style set, we
// need to make sure that a cell node exists at the intersection so we can style it appropriately.
// Fetching the cell will force a new cell node to be created with a style matching the column. So we
// will fetch and style the cell at each row that intersects this column if it is already present or it
// has a style defined.
_this2.sheet().forEachExistingRow(function (row) {
if (row.hasStyle() || row.hasCell(_this2.columnNumber())) {
row.cell(_this2.columnNumber()).style(name, value);
}
});
// Set a single value for all cells to a single value
_this2._createStyleIfNeeded();
_this2._style.style(name, value);
return _this2;
}).case('object', function (nameValues) {
// Object of key value pairs to set
for (var name in nameValues) {
if (!nameValues.hasOwnProperty(name)) continue;
var value = nameValues[name];
_this2.style(name, value);
}
return _this2;
}).case('Style', function (style) {
// See Large Comment Above
_this2.sheet().forEachExistingRow(function (row) {
if (row.hasStyle() || row.hasCell(_this2.columnNumber())) {
row.cell(_this2.columnNumber()).style(style);
}
});
_this2._style = style;
_this2._node.attributes.style = style.id();
return _this2;
}).handle(arguments);
}
/**
* Gets the width.
* @returns {undefined|number} The width (or undefined).
*/ /**
* Sets the width.
* @param {number} width - The width of the column.
* @returns {Column} The column.
*/
}, {
key: "width",
value: function width(_width) {
var _this3 = this;
return new ArgHandler("Column.width").case(function () {
return _this3._node.attributes.customWidth ? _this3._node.attributes.width : undefined;
}).case('number', function (width) {
_this3._node.attributes.width = width;
_this3._node.attributes.customWidth = 1;
return _this3;
}).case('nil', function () {
delete _this3._node.attributes.width;
delete _this3._node.attributes.customWidth;
return _this3;
}).handle(arguments);
}
/**
* Get the parent workbook.
* @returns {Workbook} The parent workbook.
*/
}, {
key: "workbook",
value: function workbook() {
return this.sheet().workbook();
}
/* INTERNAL */
/**
* Convert the column to an XML object.
* @returns {{}} The XML form.
* @ignore
*/
}, {
key: "toXml",
value: function toXml() {
return this._node;
}
/* PRIVATE */
/**
* Create a style for this column if it doesn't already exist.
* @returns {undefined}
* @private
*/
}, {
key: "_createStyleIfNeeded",
value: function _createStyleIfNeeded() {
if (!this._style) {
var styleId = this._node.attributes.style;
this._style = this.workbook().styleSheet().createStyle(styleId);
this._node.attributes.style = this._style.id();
if (!this.width()) this.width(defaultColumnWidth);
}
}
}]);
return Column;
}();
module.exports = Column;
},{"./ArgHandler":2,"./addressConverter":20}],5:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _ = require("lodash");
/**
* A content type collection.
* @ignore
*/
var ContentTypes = function () {
/**
* Creates a new instance of ContentTypes
* @param {{}} node - The node.
*/
function ContentTypes(node) {
_classCallCheck(this, ContentTypes);
this._node = node;
}
/**
* Add a new content type.
* @param {string} partName - The part name.
* @param {string} contentType - The content type.
* @returns {{}} The new content type.
*/
_createClass(ContentTypes, [{
key: "add",
value: function add(partName, contentType) {
var node = {
name: "Override",
attributes: {
PartName: partName,
ContentType: contentType
}
};
this._node.children.push(node);
return node;
}
/**
* Find a content type by part name.
* @param {string} partName - The part name.
* @returns {{}|undefined} The matching content type or undefined if not found.
*/
}, {
key: "findByPartName",
value: function findByPartName(partName) {
return _.find(this._node.children, function (node) {
return node.attributes.PartName === partName;
});
}
/**
* Convert the collection to an XML object.
* @returns {{}} The XML.
*/
}, {
key: "toXml",
value: function toXml() {
return this._node;
}
}]);
return ContentTypes;
}();
module.exports = ContentTypes;
/*
[Content_Types].xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="bin" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings"/>
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
<Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
<Override PartName="/xl/calcChain.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml"/>
<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
</Types>
*/
},{"lodash":191}],6:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var allowedProperties = {
title: "dc:title",
subject: "dc:subject",
author: "dc:creator",
creator: "dc:creator",
description: "dc:description",
keywords: "cp:keywords",
category: "cp:category"
};
/**
* Core properties
* @ignore
*/
var CoreProperties = function () {
function CoreProperties(node) {
_classCallCheck(this, CoreProperties);
this._node = node;
this._properties = {};
}
/**
* Sets a specific property.
* @param {string} name - The name of the property.
* @param {*} value - The value of the property.
* @returns {CoreProperties} CoreProperties.
*/
_createClass(CoreProperties, [{
key: "set",
value: function set(name, value) {
var key = name.toLowerCase();
if (typeof allowedProperties[key] === "undefined") {
throw new Error("Unknown property name: \"" + name + "\"");
}
this._properties[key] = value;
return this;
}
/**
* Get a specific property.
* @param {string} name - The name of the property.
* @returns {*} The property value.
*/
}, {
key: "get",
value: function get(name) {
var key = name.toLowerCase();
if (typeof allowedProperties[key] === "undefined") {
throw new Error("Unknown property name: \"" + name + "\"");
}
return this._properties[key];
}
/**
* Convert the collection to an XML object.
* @returns {{}} The XML.
*/
}, {
key: "toXml",
value: function toXml() {
for (var key in this._properties) {
if (!this._properties.hasOwnProperty(key)) continue;
this._node.children.push({
name: allowedProperties[key],
children: [this._properties[key]]
});
}
return this._node;
}
}]);
return CoreProperties;
}();
module.exports = CoreProperties;
/*
docProps/core.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dc:title>Titl