@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,272 lines (1,159 loc) • 54.2 kB
JavaScript
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ({
/***/ 0:
/***/ (function(module, exports, __webpack_require__) {
__webpack_require__(1504);
module.exports = __webpack_require__(1504);
/***/ }),
/***/ 3:
/***/ (function(module, exports) {
module.exports = function() { throw new Error("define cannot be used indirect"); };
/***/ }),
/***/ 19:
/***/ (function(module, exports) {
module.exports = require("../kendo.core");
/***/ }),
/***/ 923:
/***/ (function(module, exports) {
module.exports = require("../kendo.color");
/***/ }),
/***/ 1504:
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(19), __webpack_require__(923), __webpack_require__(1505), __webpack_require__(1506) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
})(function(){
"use strict";
if (kendo.support.browser.msie && kendo.support.browser.version < 9) {
return;
}
/* global JSZip */
// WARNING: removing the following jshint declaration and turning
// == into === to make JSHint happy will break functionality.
/* jshint eqnull:true, laxbreak:true */
/* jshint latedef: nofunc */
var $ = kendo.jQuery;
var parseXML = kendo.util.parseXML;
var parseReference = kendo.spreadsheet.calc.parseReference;
var MAP_EXCEL_OPERATOR = {
// includes only what differs; key is Excel's operator, value
// is our operator.
greaterThanOrEqual : "greaterThanOrEqualTo",
lessThanOrEqual : "lessThanOrEqualTo"
};
var ERROR_LOG = null;
function readExcel(file, workbook, deferred) {
var reader = new FileReader();
reader.onload = function(e) {
var zip = new JSZip(e.target.result);
readWorkbook(zip, workbook, deferred);
};
reader.readAsArrayBuffer(file);
}
var SEL_CELL = ["sheetData", "row", "c"];
var SEL_COL = ["cols", "col"];
var SEL_DEFINED_NAME = ["definedNames", "definedName"];
var SEL_FORMULA = ["sheetData", "row", "c", "f"];
var SEL_MERGE = ["mergeCells", "mergeCell"];
var SEL_PANE = ["sheetViews", "sheetView", "pane"];
var SEL_ROW = ["sheetData", "row"];
var SEL_SELECTION = ["sheetViews", "sheetView", "selection"];
var SEL_SHEET = ["sheets", "sheet"];
var SEL_STRING = ["sheetData", "row", "c", "is"];
var SEL_TEXT = ["t"];
var SEL_SHARED_STRING = ["si"];
var SEL_VALUE = ["sheetData", "row", "c", "v"];
var SEL_VIEW = ["bookViews", "workbookView"];
var SEL_SHEET_VIEW = ["sheetViews", "sheetView"];
var SEL_HYPERLINK = ["hyperlinks", "hyperlink"];
/* A validation section looks like this:
*
* <dataValidations count="1">
* <dataValidation type="list" allowBlank="1" showInputMessage="1" showErrorMessage="1" sqref="B2">
* <formula1>$E$2:$E$5</formula1>
* </dataValidation>
* </dataValidations>
*/
var SEL_VALIDATION = ["dataValidations", "dataValidation"];
var SEL_VALIDATION_FORMULA1 = ["dataValidations", "dataValidation", "formula1"];
var SEL_VALIDATION_FORMULA2 = ["dataValidations", "dataValidation", "formula2"];
/* However, when a validation formula in one sheet references
* cells from another sheet, Excel produces this version instead:
*
* <extLst>
* <ext xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" uri="{CCE6A557-97BC-4b89-ADB6-D9C93CAAB3DF}">
* <x14:dataValidations xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main" count="1">
* <x14:dataValidation type="list" allowBlank="1" showInputMessage="1" showErrorMessage="1">
* <x14:formula1>
* <xm:f>Sheet2!$B$3:$B$6</xm:f>
* </x14:formula1>
* <xm:sqref>B1</xm:sqref>
* </x14:dataValidation>
* </x14:dataValidations>
* </ext>
* </extLst>
*
* I call it the "insane version", because that's what it is.
* Barring the case that the engineers who produced this horror
* were on LSD, the only plausible reason for it is that Microsoft
* does not want third party software to be compatible with Excel
* (sentiment I've had over and over while working on the
* Spreadsheet widget).
*/
// XXX: technically, the aliases `x14` and `xm` below could be
// different, but Excel seems to be hard-coded on these; our
// parser does not support proper namespaces for now anyway, so
// hard-coded they are.
var SEL_VALIDATION_INSANE = ["x14:dataValidations", "x14:dataValidation"];
var SEL_VALIDATION_SQREF_INSANE = ["x14:dataValidations", "x14:dataValidation", "xm:sqref"];
var SEL_VALIDATION_FORMULA1_INSANE = ["x14:dataValidations", "x14:dataValidation", "x14:formula1", "xm:f"];
var SEL_VALIDATION_FORMULA2_INSANE = ["x14:dataValidations", "x14:dataValidation", "x14:formula2", "xm:f"];
// comment selectors (in files like comments1.xml)
var SEL_COMMENT = ["commentList", "comment"];
var SEL_AUTHOR = ["authors", "author"];
var SEL_COMMENT_TEXT = ["t"];
function xl(file) {
if (!/^\//.test(file)) {
if (!/^xl\//.test(file)) {
file = "xl/" + file;
}
} else {
file = file.substr(1);
}
return file;
}
function readWorkbook(zip, workbook, progress) {
ERROR_LOG = workbook.excelImportErrors = [];
var strings = readStrings(zip);
var relationships = readRelationships(zip, "_rels/workbook.xml");
var theme = readTheme(zip, relationships.byType.theme[0]);
var styles = readStyles(zip, theme);
var items = [];
var activeSheet = 0;
parse(zip, "xl/workbook.xml", {
enter: function(tag, attrs) {
if (this.is(SEL_SHEET)) {
var relId = attrs["r:id"];
var file = relationships.byId[relId];
var name = attrs.name;
var dim = sheetDimensions(zip, file);
workbook.options.columnWidth = dim.columnWidth || workbook.options.columnWidth;
workbook.options.rowHeight = dim.rowHeight || workbook.options.rowHeight;
items.push({
workbook: workbook,
zip: zip,
strings: strings,
styles: styles,
file: file,
options: {
name: name,
rows: Math.max(workbook.options.rows || 0, dim.rows),
columns: Math.max(workbook.options.columns || 0, dim.cols),
columnWidth: dim.columnWidth,
rowHeight: dim.rowHeight
}
});
} else if (this.is(SEL_VIEW)) {
if (attrs.activeTab) {
activeSheet = integer(attrs.activeTab);
}
}
},
text: function(text) {
var attrs = this.is(SEL_DEFINED_NAME);
if (attrs && !(bool(attrs["function"]) || bool(attrs.vbProcedure))) {
var localSheetId = attrs.localSheetId;
var sheet = null;
if (localSheetId != null) {
sheet = items[localSheetId].options.name;
}
var name = attrs.name;
if (name != "_xlnm._FilterDatabase") {
if (sheet) {
name = "'" + sheet.replace(/\'/g, "\\'") + "'!" + name;
}
withErrorLog(sheet, null, function(){
workbook.defineName(name, text, bool(attrs.hidden));
}, "reading user-defined name: " + name);
}
}
}
});
var loading = new $.Deferred();
loading.progress(function(args) {
if (progress) {
progress.notify(args);
}
})
.then(function() {
var sheets = workbook.sheets();
recalcSheets(sheets);
workbook.activeSheet(sheets[activeSheet]);
if (progress) {
progress.resolve();
}
});
loadSheets(items, workbook, loading);
}
function loadSheets(items, workbook, progress) {
var ready = (new $.Deferred()).resolve();
for (var i = 0; i < items.length; i++) {
/*jshint -W083 */
(function(entry, i) {
ready = ready.then(function() {
var sheet = workbook.insertSheet(entry.options);
sheet.suspendChanges(true);
var promise = queueSheet(sheet, entry);
var args = {
sheet: sheet,
progress: i / (items.length - 1)
};
promise.then(function() {
progress.notify(args);
});
return promise;
});
})(items[i], i);
}
ready.then(function() {
progress.resolve();
});
}
function queueSheet(sheet, ctx) {
var deferred = new $.Deferred();
setTimeout(function() {
readSheet(ctx.zip, ctx.file, sheet, ctx.strings, ctx.styles);
deferred.resolve();
}, 0);
return deferred;
}
function recalcSheets(sheets) {
for (var i = 0; i < sheets.length; i++) {
sheets[i]
.suspendChanges(false)
.triggerChange({ recalc: true });
}
}
function sheetDimensions(zip, file) {
var dim = {
rows: 0,
cols: 0
};
parse(zip, xl(file), {
enter: function(tag, attrs) {
if (tag == "dimension") {
var ref = parseReference(attrs.ref);
if (ref.bottomRight) {
dim.cols = ref.bottomRight.col + 1;
dim.rows = ref.bottomRight.row + 1;
}
} else if (tag === "sheetFormatPr") {
if (attrs.defaultColWidth) {
dim.columnWidth = toColWidth(parseFloat(attrs.defaultColWidth));
}
if (attrs.defaultRowHeight) {
dim.rowHeight = toRowHeight(parseFloat(attrs.defaultRowHeight));
}
} else if (this.is(SEL_ROW)) {
// Don't process actual rows
this.exit();
}
}
});
return dim;
}
function toColWidth(size) {
// No font to compute agains, hence the magic number
var maximumDigitWidth = 7;
// The formula below is taken from the OOXML spec
var fraction = (256 * size + Math.floor(128 / maximumDigitWidth)) / 256;
return fraction * maximumDigitWidth;
}
function toRowHeight(pts) {
return pts * (4 / 3);
}
function readSheet(zip, file, sheet, strings, styles) {
var sharedFormulas = {};
var ref, type, value, formula, formulaRange, isArrayFormula;
var nCols = sheet._columns._count;
var prevCellRef = null;
var relsFile = file.replace(/worksheets\//, "worksheets/_rels/");
var relationships = readRelationships(zip, relsFile);
var formula1, formula2;
var filterRef;
var filterColumn;
var customFilterLogic;
var customFilterCriteria;
var valueFilterBlanks;
var valueFilterValues;
var filters = [];
ERROR_LOG = sheet._workbook.excelImportErrors;
file = xl(file);
parse(zip, file, {
enter: function(tag, attrs, closed) {
var tmp;
if (this.is(SEL_FORMULA)) {
if (closed) {
if (attrs.t == "shared" && attrs.si != null) {
formula = sheet.range(sharedFormulas[attrs.si])._get("formula");
}
}
}
else if (this.is(SEL_CELL)) {
value = null;
formula = null;
ref = attrs.r;
formulaRange = null;
if (ref == null) {
// apparently some tools omit the `r` for
// consecutive cells in a row, so we'll figure
// it out from the previous cell's reference.
// XXX: this could be slightly optimized by
// keeping it parsed instead of stringifying
// it to parse it again later.
ref = parseReference(prevCellRef);
ref.col++;
ref = ref.toString();
}
prevCellRef = ref;
// XXX: can't find no type actually, so everything is
// interpreted as string. Additionally, cells having
// a formula will contain both <f> and <v> nodes,
// which makes the value take precedence because it's
// the second node; hence, the hack is to keep note of
// them in the `text` handler, and apply the
// appropriate one in the `leave` handler below.
type = attrs.t;
var styleIndex = attrs.s;
if (styleIndex != null) {
applyStyle(sheet, ref, styles, styleIndex);
}
}
else if (this.is(SEL_MERGE)) {
sheet.range(attrs.ref).merge();
}
else if (this.is(SEL_COL)) {
var start = integer(attrs.min) - 1;
var stop = Math.min(nCols, integer(attrs.max)) - 1;
var width;
if (attrs.width) {
width = toColWidth(parseFloat(attrs.width));
if (width !== 0) {
sheet._columns.values.value(start, stop, width);
}
}
if (attrs.hidden === "1" || width === 0) {
for (var ci = start; ci <= stop; ci++) {
sheet.hideColumn(ci);
}
}
if (attrs.style != null) {
// apply style on a whole range of columns
applyStyle(sheet, new kendo.spreadsheet.RangeRef(
new kendo.spreadsheet.CellRef(-Infinity, start),
new kendo.spreadsheet.CellRef(+Infinity, stop)
), styles, attrs.style);
}
}
else if (this.is(SEL_ROW)) {
var row = integer(attrs.r) - 1;
var height;
if (attrs.ht) {
height = toRowHeight(parseFloat(attrs.ht));
if (height !== 0) {
sheet._rows.values.value(row, row, height);
}
}
if (attrs.hidden === "1" || height === 0) {
sheet.hideRow(row);
}
}
else if (this.is(SEL_SELECTION)) {
if (attrs.activeCell) {
var acRef = parseReference(attrs.activeCell);
sheet.select(acRef, true);
}
}
else if (this.is(SEL_PANE)) {
if (attrs.state == "frozen") {
if (attrs.xSplit) {
sheet.frozenColumns(integer(attrs.xSplit));
}
if (attrs.ySplit) {
sheet.frozenRows(integer(attrs.ySplit));
}
}
}
else if (this.is(SEL_SHEET_VIEW)) {
sheet.showGridLines(bool(attrs.showGridLines, true));
}
else if (this.is(SEL_HYPERLINK)) {
var relId = attrs["r:id"];
var target = relationships.byId[relId];
if (target) {
sheet.range(attrs.ref).link(target);
}
}
else if (this.is(["autoFilter"])) {
filterRef = attrs.ref;
if (closed) {
addAutoFilter();
}
}
else if (filterRef) {
if (this.is(["filterColumn"])) {
filterColumn = parseInt(attrs.colId, 10);
}
else if (this.is(["customFilters"])) {
customFilterLogic = bool(attrs.and) ? "and" : "or";
customFilterCriteria = [];
}
else if (this.is(["customFilter"])) {
tmp = getCustomFilter(attrs.operator, attrs.val);
if (tmp) {
customFilterCriteria.push({
operator: tmp.operator,
value: tmp.value
});
}
}
else if (this.is(["dynamicFilter"])) {
filters.push({
column: filterColumn,
filter: new kendo.spreadsheet.DynamicFilter({
type: dynamicFilterType(attrs.type)
})
});
}
else if (this.is(["top10"])) {
filters.push({
column: filterColumn,
filter: new kendo.spreadsheet.TopFilter({
value: getFilterVal(attrs.val),
type: (function(percent, top){
return percent && top ? "topPercent"
: top ? "topNumber"
: percent ? "bottomPercent"
: "bottomNumber";
})(bool(attrs.percent), bool(attrs.top))
})
});
}
else if (this.is(["filters"])) {
valueFilterBlanks = bool(attrs.blank);
valueFilterValues = [];
}
else if (this.is(["filter"])) {
valueFilterValues.push(getFilterVal(attrs.val));
}
}
},
leave: function(tag, attrs) {
if (this.is(SEL_FORMULA)) {
if (!formula && attrs.t == "shared" && attrs.si != null) {
formula = sheet.range(sharedFormulas[attrs.si])._get("formula");
}
}
else if (this.is(SEL_CELL)) {
if (formula != null) {
var failed = withErrorLog(sheet, formulaRange || ref, function(){
sheet.range(formulaRange || ref).formula(formula, isArrayFormula);
}, "parsing formula");
if (failed) {
sheet.range(formulaRange || ref).value(formula)
.background("#ffaaaa");
}
} else if (value != null) {
var range = sheet.range(ref);
if (!range._get("formula")) {
// Check for "shared" formulas before applying a value.
if (!type || type == "n") {
value = parseFloat(value);
} else if (type == "s") {
value = strings[integer(value)];
} else if (type == "b") {
value = value === "1";
} else if (type == "d") {
value = kendo.parseDate(value);
}
if (value != null) {
range.value(value);
}
}
}
} else if (this.is(SEL_VALIDATION) ||
this.is(SEL_VALIDATION_INSANE)) {
(function(){
var refs = kendo.spreadsheet.calc.parseSqref(attrs.sqref);
var type = attrs.type.toLowerCase();
var operator = attrs.operator;
if (/^(?:whole|decimal)$/.test(type)) {
// we only support "number"
type = "number";
} else if (type == "list") {
// there'll be no operator from Excel for lists
operator = "list";
}
if (!operator && /^(?:number|date)$/.test(type)) {
// Excel skips setting the operator for
// "between", because why not.
operator = "between";
}
refs.forEach(function(ref){
withErrorLog(sheet, ref, function(){
sheet.range(ref).validation({
type : bool(attrs.showErrorMessage, true) ? "reject" : "warning",
from : formula1,
to : formula2,
dataType : type,
comparerType : MAP_EXCEL_OPERATOR[operator] || operator,
allowNulls : bool(attrs.allowBlank),
showButton : bool(attrs.showDropDown) || type == "date" || type == "list",
messageTemplate : attrs.error,
titleTemplate : attrs.errorTitle
});
}, "parsing validation");
});
})();
} else if (tag == "cols") {
sheet._columns._refresh();
} else if (tag == "sheetData") {
sheet._rows._refresh();
} else if (tag == "autoFilter") {
addAutoFilter();
} else if (filterRef) {
if (tag == "customFilters") {
filters.push({
column: filterColumn,
filter: new kendo.spreadsheet.CustomFilter({
logic: customFilterLogic,
criteria: customFilterCriteria
})
});
} else if (tag == "filters") {
filters.push({
column: filterColumn,
filter: new kendo.spreadsheet.ValueFilter({
values: valueFilterValues,
blanks: valueFilterBlanks
})
});
}
}
},
text: function(text) {
var attrs;
if (this.is(SEL_VALUE) || this.is(SEL_STRING)) {
value = text;
} else if ((attrs = this.is(SEL_FORMULA))) {
formula = text;
isArrayFormula = attrs.t == "array";
if (isArrayFormula) {
formulaRange = attrs.ref;
} else if (attrs.t == "shared") {
sharedFormulas[attrs.si] = ref;
}
} else if (this.is(SEL_VALIDATION_FORMULA1) ||
this.is(SEL_VALIDATION_FORMULA1_INSANE)) {
formula1 = text;
} else if (this.is(SEL_VALIDATION_FORMULA2) ||
this.is(SEL_VALIDATION_FORMULA2_INSANE)) {
formula2 = text;
} else if (this.is(SEL_VALIDATION_SQREF_INSANE)) {
// put it in <dataValidation>'s attributes where it should be
this.stack[this.stack.length - 2].sqref = text;
}
}
});
if (relationships.byType.comments) {
var commentFile = relative_file(file, relationships.byType.comments[0]);
readComments(zip, commentFile, sheet);
}
if (relationships.byType.drawing) {
var drawingFile = relative_file(file, relationships.byType.drawing[0]);
readDrawings(zip, drawingFile, sheet);
}
function addAutoFilter() {
sheet.range(filterRef).filter(filters);
filterRef = null;
}
}
function getContentType(filename) {
var m = /\.([^.]+)$/.exec(filename);
if (m && m[1]) {
return {
jpg : "image/jpeg",
jpeg : "image/jpeg",
png : "image/png",
gif : "image/gif"
}[m[1].toLowerCase()];
}
}
function getFileName(filename) {
var m = /[^/]+$/.exec(filename);
return m && m[0];
}
function readDrawings(zip, file, sheet) {
var sel_two_cell_anchor = [ "xdr:twoCellAnchor" ];
var sel_ext = [ "xdr:ext" ];
var sel_one_cell_anchor = [ "xdr:oneCellAnchor" ];
var sel_from = [ "xdr:from" ];
var sel_to = [ "xdr:to" ];
var sel_row = [ "xdr:row" ];
var sel_col = [ "xdr:col" ];
var sel_row_offset = [ "xdr:rowOff" ];
var sel_col_offset = [ "xdr:colOff" ];
var sel_blip = [ "xdr:blipFill", "a:blip" ];
var relsFile = file.replace(/drawings\//, "drawings/_rels/");
var relationships = readRelationships(zip, relsFile);
if (relationships.byType.image) {
Object.keys(relationships.byId).forEach(function(id){
var img = relative_file(file, relationships.byId[id]);
var type = getContentType(img);
if (type) {
// XXX: file.asArrayBuffer() is deprecated in JSZip 3
var data = zip.files[img].asArrayBuffer();
var name = getFileName(img);
var blob = name && !(kendo.support.browser.msie || kendo.support.browser.edge)
? new window.File([ data ], name, { type: type })
: new window.Blob([ data ], { type: type });
relationships.byId[id] = sheet._workbook.addImage(blob);
}
});
}
var cdr, ref, width, height;
parse(zip, file, {
enter: function(tag, attrs) {
if (this.is(sel_two_cell_anchor) || this.is(sel_one_cell_anchor)) {
cdr = {};
}
else if (this.is(sel_from) || this.is(sel_to)) {
ref = {};
}
else if (this.is(sel_blip)) {
var id = attrs["r:embed"];
cdr.image = relationships.byId[id];
}
else if (this.is(sel_ext)) {
width = excelToPixels(parseFloat(attrs.cx));
height = excelToPixels(parseFloat(attrs.cy));
}
},
leave: function() {
if (this.is(sel_from)) {
cdr.topLeftCell = new kendo.spreadsheet.CellRef(ref.row, ref.col);
cdr.offsetX = excelToPixels(ref.colOffset);
cdr.offsetY = excelToPixels(ref.rowOffset);
}
else if (this.is(sel_to)) {
cdr.brCell = new kendo.spreadsheet.CellRef(ref.row, ref.col);
cdr.brX = excelToPixels(ref.colOffset);
cdr.brY = excelToPixels(ref.rowOffset);
}
else if (this.is(sel_two_cell_anchor)) {
var left = sheet._columns.sum(0, cdr.topLeftCell.col - 1) + cdr.offsetX;
var top = sheet._rows.sum(0, cdr.topLeftCell.row - 1) + cdr.offsetY;
var right = sheet._columns.sum(0, cdr.brCell.col - 1) + cdr.brX;
var bottom = sheet._rows.sum(0, cdr.brCell.row - 1) + cdr.brY;
sheet.addDrawing({
topLeftCell : cdr.topLeftCell,
offsetX : cdr.offsetX,
offsetY : cdr.offsetY,
width : width != null ? width : right - left,
height : height != null ? height : bottom - top,
image : cdr.image,
opacity : 1
});
}
else if (this.is(sel_one_cell_anchor)) {
sheet.addDrawing({
topLeftCell : cdr.topLeftCell,
offsetX : cdr.offsetX,
offsetY : cdr.offsetY,
width : width,
height : height,
image : cdr.image,
opacity : 1
});
}
},
text: function(text) {
if (this.is(sel_row)) {
ref.row = parseFloat(text);
}
else if (this.is(sel_col)) {
ref.col = parseFloat(text);
}
else if (this.is(sel_row_offset)) {
ref.rowOffset = parseFloat(text);
}
else if (this.is(sel_col_offset)) {
ref.colOffset = parseFloat(text);
}
}
});
}
function readComments(zip, file, sheet) {
var authors = [];
var author;
var comment;
parse(zip, file, {
enter: function(tag, attrs) {
if (this.is(SEL_COMMENT)) {
comment = {
author: authors[attrs.authorId],
ref: attrs.ref,
text: ""
};
} else if (this.is(SEL_AUTHOR)) {
author = "";
}
},
leave: function() {
if (this.is(SEL_COMMENT)) {
sheet.range(comment.ref).comment(comment.text);
} else if (this.is(SEL_AUTHOR)) {
authors.push(author);
}
},
text: function(text) {
if (this.is(SEL_COMMENT_TEXT)) {
comment.text += text;
} else if (this.is(SEL_AUTHOR)) {
author += text;
}
}
});
}
function getCustomFilter(op, value) {
var ourOp = {
equal : "eq",
notEqual : "ne",
greaterThan : "gt",
greaterThanOrEqual : "gte",
lessThan : "lt",
lessThanOrEqual : "lte"
}[op];
value = getFilterVal(value);
if (ourOp && typeof value == "number") {
return { operator: ourOp, value: value };
}
if ((op == "notEqual" || !op) && typeof value == "string") {
// Excel text operators support * and ? wildcards. Since
// our startswith/endswith/contains filters do not, we
// can't really use them here, so we'll apply the more
// generic "matches" and "doesnotmatch" filters.
return {
operator: op ? "doesnotmatch" : "matches",
value: value
};
}
}
function dynamicFilterType(type) {
return {
Q1 : "quarter1",
Q2 : "quarter2",
Q3 : "quarter3",
Q4 : "quarter4",
M1 : "january",
M2 : "february",
M3 : "march",
M4 : "april",
M5 : "may",
M6 : "june",
M7 : "july",
M8 : "august",
M9 : "september",
M10 : "october",
M11 : "november",
M12 : "december"
}[type.toUpperCase()] || type;
}
function getFilterVal(val) {
var tmp = parseFloat(val);
if (!isNaN(tmp) && tmp == val) {
return tmp;
}
return val;
}
function withErrorLog(sheet, ref, func, context) {
try {
func();
return false;
} catch(ex) {
var err = { context: context, error: String(ex) };
if (sheet) {
err.sheet = sheet.name();
}
if (ref) {
err.location = String(ref);
}
ERROR_LOG.push(err);
return true;
}
}
var BORDER_WIDTHS = {
"none" : 0,
"thin" : 1,
"medium" : 2,
"dashed" : 1,
"dotted" : 1,
"thick" : 3,
"double" : 3,
"hair" : 1,
"mediumDashed" : 2,
"dashDot" : 1,
"mediumDashDot" : 2,
"dashDotDot" : 1,
"mediumDashDotDot": 2,
"slantDashDot" : 1
};
var DEFAULT_FORMATS = {
0 : "General",
1 : "0",
2 : "0.00",
3 : "#,##0",
4 : "#,##0.00",
9 : "0%",
10 : "0.00%",
11 : "0.00E+00",
12 : "# ?/?",
13 : "# ??/??",
14 : "mm-dd-yy",
15 : "d-mmm-yy",
16 : "d-mmm",
17 : "mmm-yy",
18 : "h:mm AM/PM",
19 : "h:mm:ss AM/PM",
20 : "h:mm",
21 : "h:mm:ss",
22 : "m/d/yy h:mm",
37 : "#,##0 ;(#,##0)",
38 : "#,##0 ;[Red](#,##0)",
39 : "#,##0.00;(#,##0.00)",
40 : "#,##0.00;[Red](#,##0.00)",
45 : "mm:ss",
46 : "[h]:mm:ss",
47 : "mmss.0",
48 : "##0.0E+0",
49 : "@"
};
function applyStyle(sheet, ref, styles, styleIndex) {
var range = sheet.range(ref);
var xf = styles.inlineStyles[styleIndex], base, value;
if (xf.xfId) {
base = styles.namedStyles[xf.xfId];
}
if (shouldSet("applyBorder", "borderId")) {
setBorder(styles.borders[value]);
}
if (shouldSet("applyFont", "fontId")) {
setFont(styles.fonts[value]);
}
if (shouldSet("applyAlignment", "textAlign")) {
range.textAlign(value);
}
if (shouldSet("applyAlignment", "verticalAlign")) {
range.verticalAlign(value);
}
if (shouldSet("applyAlignment", "indent")) {
range.indent(value);
}
if (shouldSet("applyAlignment", "wrapText")) {
// don't use range.wrap to avoid recomputing row height
range._property("wrap", value);
}
if (shouldSet("applyFill", "fillId")) {
setFill(styles.fills[value]);
}
if (shouldSet("applyNumberFormat", "numFmtId")) {
setFormat(styles.numFmts[value] || DEFAULT_FORMATS[value]);
}
function setFormat(f) {
var format = typeof f == "string" ? f : f.formatCode;
if (format != null && !/^general$/i.test(format)) {
// XXX: drop locale info.
// http://stackoverflow.com/questions/894805/excel-number-format-what-is-409
// not supported by the formatting library.
format = format.replace(/^\[\$-[0-9]+\]/, "");
range.format(format);
}
}
function setFill(f) {
if (f.type == "solid") {
range.background(f.color);
}
}
function setFont(f) {
range.fontFamily(f.name);
//range.fontSize(f.size); //XXX: will recalc row height.
// converting from points to pixels
if (f.size) {
range._property("fontSize", f.size * 4 / 3);
}
if (f.bold) {
range.bold(true);
}
if (f.italic) {
range.italic(true);
}
if (f.underline) {
range.underline(true);
}
if (f.color) {
range.color(f.color);
}
}
function setBorder(b) {
function set(side, prop) {
var border = b[side];
if (!border) {
return;
}
var width = BORDER_WIDTHS[border.style];
if (width === 0) {
return;
}
var color = border.color;
if (color == null) {
color = "#000";
}
range._property(prop, { size: width, color: color });
}
set("left", "borderLeft");
set("top", "borderTop");
set("right", "borderRight");
set("bottom", "borderBottom");
}
function shouldSet(applyName, propName) {
var t = xf[applyName];
if (t != null && !t) {
return false;
}
value = xf[propName];
if (base && value == null) {
t = base[applyName];
if (t != null && !t) {
return false;
}
value = base[propName];
}
return value != null;
}
}
function parse(zip, file, callbacks) {
var part = zip.files[file];
if (part) {
parseXML(part.asUint8Array(), callbacks);
}
}
function readStrings(zip) {
var strings = [];
var current = null;
parse(zip, "xl/sharedStrings.xml", {
leave: function() {
if (this.is(SEL_SHARED_STRING)) {
strings.push(current);
current = null;
}
},
text: function(text) {
if (this.is(SEL_TEXT)) {
if (current == null) {
current = "";
}
current += text;
}
}
});
return strings;
}
function readRelationships(zip, file) {
var map = { byId: {}, byType: { theme: [] } };
parse(zip, xl(file) + ".rels", {
enter: function(tag, attrs) {
if (tag == "Relationship") {
map.byId[attrs.Id] = attrs.Target;
var type = attrs.Type.match(/\w+$/)[0];
var entries = map.byType[type] || [];
entries.push(attrs.Target);
map.byType[type] = entries;
}
}
});
return map;
}
var SEL_BORDER = ["borders", "border"];
var SEL_FILL = ["fills", "fill"];
var SEL_FONT = ["fonts", "font"];
var SEL_INLINE_STYLE = ["cellXfs", "xf"];
var SEL_NAMED_STYLE = ["cellStyleXfs", "xf"];
var SEL_NUM_FMT = ["numFmts", "numFmt"];
var INDEXED_COLORS = [
toCSSColor("FF000000"), toCSSColor("FFFFFFFF"), toCSSColor("FFFF0000"),
toCSSColor("FF00FF00"), toCSSColor("FF0000FF"), toCSSColor("FFFFFF00"),
toCSSColor("FFFF00FF"), toCSSColor("FF00FFFF"), toCSSColor("FF000000"),
toCSSColor("FFFFFFFF"), toCSSColor("FFFF0000"), toCSSColor("FF00FF00"),
toCSSColor("FF0000FF"), toCSSColor("FFFFFF00"), toCSSColor("FFFF00FF"),
toCSSColor("FF00FFFF"), toCSSColor("FF800000"), toCSSColor("FF008000"),
toCSSColor("FF000080"), toCSSColor("FF808000"), toCSSColor("FF800080"),
toCSSColor("FF008080"), toCSSColor("FFC0C0C0"), toCSSColor("FF808080"),
toCSSColor("FF9999FF"), toCSSColor("FF993366"), toCSSColor("FFFFFFCC"),
toCSSColor("FFCCFFFF"), toCSSColor("FF660066"), toCSSColor("FFFF8080"),
toCSSColor("FF0066CC"), toCSSColor("FFCCCCFF"), toCSSColor("FF000080"),
toCSSColor("FFFF00FF"), toCSSColor("FFFFFF00"), toCSSColor("FF00FFFF"),
toCSSColor("FF800080"), toCSSColor("FF800000"), toCSSColor("FF008080"),
toCSSColor("FF0000FF"), toCSSColor("FF00CCFF"), toCSSColor("FFCCFFFF"),
toCSSColor("FFCCFFCC"), toCSSColor("FFFFFF99"), toCSSColor("FF99CCFF"),
toCSSColor("FFFF99CC"), toCSSColor("FFCC99FF"), toCSSColor("FFFFCC99"),
toCSSColor("FF3366FF"), toCSSColor("FF33CCCC"), toCSSColor("FF99CC00"),
toCSSColor("FFFFCC00"), toCSSColor("FFFF9900"), toCSSColor("FFFF6600"),
toCSSColor("FF666699"), toCSSColor("FF969696"), toCSSColor("FF003366"),
toCSSColor("FF339966"), toCSSColor("FF003300"), toCSSColor("FF333300"),
toCSSColor("FF993300"), toCSSColor("FF993366"), toCSSColor("FF333399"),
toCSSColor("FF333333"),
toCSSColor("FF000000"), // System Foreground
toCSSColor("FFFFFFFF") // System Background
];
function readStyles(zip, theme) {
var styles = {
fonts : [],
numFmts : {},
fills : [],
borders : [],
namedStyles : [],
inlineStyles : []
};
var font = null;
var fill = null;
var border = null;
var xf = null;
parse(zip, "xl/styles.xml", {
enter: function(tag, attrs, closed) {
if (this.is(SEL_NUM_FMT)) {
styles.numFmts[attrs.numFmtId] = attrs;
}
else if (this.is(SEL_FONT)) {
styles.fonts.push(font = {});
} else if (font) {
if (tag == "sz") {
font.size = parseFloat(attrs.val);
} else if (tag == "name") {
font.name = attrs.val;
} else if (tag == "b") {
font.bold = bool(attrs.val, true);
} else if (tag == "i") {
font.italic = bool(attrs.val, true);
} else if (tag == "u") {
font.underline = (attrs.val == null || attrs.val == "single");
} else if (tag == "color") {
font.color = getColor(attrs);
}
}
else if (this.is(SEL_FILL)) {
styles.fills.push(fill = {});
} else if (fill) {
if (tag == "patternFill") {
fill.type = attrs.patternType;
} else if (tag == "fgColor" && fill.type === "solid") {
fill.color = getColor(attrs);
} else if (tag == "bgColor" && fill.type !== "solid") {
fill.color = getColor(attrs);
}
}
else if (this.is(SEL_BORDER)) {
styles.borders.push(border = {});
} else if (border) {
if (/^(?:left|top|right|bottom)$/.test(tag)) {
border[tag] = { style: attrs.style || "none" };
}
if (tag == "color") {
var side = this.stack[this.stack.length - 2].$tag;
border[side].color = getColor(attrs);
}
}
else if (this.is(SEL_NAMED_STYLE)) {
xf = getXf(attrs);
styles.namedStyles.push(xf);
if (closed) {
xf = null;
}
} else if (this.is(SEL_INLINE_STYLE)) {
xf = getXf(attrs);
styles.inlineStyles.push(xf);
if (closed) {
xf = null;
}
} else if (xf) {
if (tag == "alignment") {
if (/^(?:left|center|right|justify)$/.test(attrs.horizontal)) {
xf.textAlign = attrs.horizontal;
}
if (/^(?:top|center|bottom)$/.test(attrs.vertical)) {
xf.verticalAlign = attrs.vertical;
}
if (attrs.wrapText != null) {
xf.wrapText = bool(attrs.wrapText);
}
if (attrs.indent != null) {
xf.indent = integer(attrs.indent);
}
}
}
},
leave: function(tag) {
if (this.is(SEL_FONT)) {
font = null;
} else if (this.is(SEL_FILL)) {
fill = null;
} else if (this.is(SEL_BORDER)) {
border = null;
} else if (tag == "xf") {
xf = null;
}
}
});
function getXf(attrs) {
var xf = {
borderId : integer(attrs.borderId),
fillId : integer(attrs.fillId),
fontId : integer(attrs.fontId),
numFmtId : integer(attrs.numFmtId),
pivotButton : bool(attrs.pivotButton),
quotePrefix : bool(attrs.quotePrefix),
xfId : integer(attrs.xfId)
};
addBool("applyAlignment");
addBool("applyBorder");
addBool("applyFill");
addBool("applyFont");