exceljs
Version:
Excel Workbook Manager - Read and Write xlsx and csv Files.
316 lines (289 loc) • 11.1 kB
JavaScript
/**
* Copyright (c) 2016 Guyon Roche
* LICENCE: MIT - please refer to LICENCE file included with this module
* or https://github.com/guyonroche/exceljs/blob/master/LICENSE
*/
'use strict';
var _ = require('../../../utils/under-dash');
var utils = require('../../../utils/utils');
var XmlStream = require('../../../utils/xml-stream');
var RelType = require('../../rel-type');
var Merges = require('./merges');
var BaseXform = require('../base-xform');
var ListXform = require('../list-xform');
var RowXform = require('./row-xform');
var ColXform = require('./col-xform');
var DimensionXform = require('./dimension-xform');
var HyperlinkXform = require('./hyperlink-xform');
var MergeCellXform = require('./merge-cell-xform');
var DataValidationsXform = require('./data-validations-xform');
var SheetPropertiesXform = require('./sheet-properties-xform');
var SheetFormatPropertiesXform = require('./sheet-format-properties-xform');
var SheetViewXform = require('./sheet-view-xform');
var PageMarginsXform = require('./page-margins-xform');
var PageSetupXform = require('./page-setup-xform');
var PrintOptionsXform = require('./print-options-xform');
var AutoFilterXform = require('./auto-filter-xform');
var PictureXform = require('./picture-xform');
var DrawingXform = require('./drawing-xform');
var WorkSheetXform = module.exports = function () {
this.map = {
sheetPr: new SheetPropertiesXform(),
dimension: new DimensionXform(),
sheetViews: new ListXform({ tag: 'sheetViews', count: false, childXform: new SheetViewXform() }),
sheetFormatPr: new SheetFormatPropertiesXform(),
cols: new ListXform({ tag: 'cols', count: false, childXform: new ColXform() }),
sheetData: new ListXform({ tag: 'sheetData', count: false, empty: true, childXform: new RowXform() }),
autoFilter: new AutoFilterXform(),
mergeCells: new ListXform({ tag: 'mergeCells', count: true, childXform: new MergeCellXform() }),
hyperlinks: new ListXform({ tag: 'hyperlinks', count: false, childXform: new HyperlinkXform() }),
pageMargins: new PageMarginsXform(),
dataValidations: new DataValidationsXform(),
pageSetup: new PageSetupXform(),
printOptions: new PrintOptionsXform(),
picture: new PictureXform(),
drawing: new DrawingXform()
};
};
utils.inherits(WorkSheetXform, BaseXform, {
WORKSHEET_ATTRIBUTES: {
xmlns: 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
'xmlns:mc': 'http://schemas.openxmlformats.org/markup-compatibility/2006',
'mc:Ignorable': 'x14ac',
'xmlns:x14ac': 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac'
}
}, {
prepare: function prepare(model, options) {
options.merges = new Merges();
model.hyperlinks = options.hyperlinks = [];
options.formulae = {};
options.siFormulae = 0;
this.map.cols.prepare(model.cols, options);
this.map.sheetData.prepare(model.rows, options);
model.mergeCells = options.merges.mergeCells;
// prepare relationships
var rels = model.rels = [];
function nextRid(r) {
return 'rId' + (r.length + 1);
}
var rId;
model.hyperlinks.forEach(function (hyperlink) {
rId = nextRid(rels);
hyperlink.rId = rId;
rels.push({
Id: rId,
Type: RelType.Hyperlink,
Target: hyperlink.target,
TargetMode: 'External'
});
});
var drawingRelsHash = [];
var bookImage;
model.media.forEach(function (medium) {
if (medium.type === 'background') {
rId = nextRid(rels);
bookImage = options.media[medium.imageId];
rels.push({
Id: rId,
Type: RelType.Image,
Target: '../media/' + bookImage.name + '.' + bookImage.extension
});
model.background = {
rId: rId
};
model.image = options.media[medium.imageId];
} else if (medium.type === 'image') {
var drawing = model.drawing;
bookImage = options.media[medium.imageId];
if (!drawing) {
drawing = model.drawing = {
rId: nextRid(rels),
name: 'drawing' + ++options.drawingsCount,
anchors: [],
rels: []
};
options.drawings.push(drawing);
rels.push({
Id: drawing.rId,
Type: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing',
Target: '../drawings/' + drawing.name + '.xml'
});
}
var rIdImage = drawingRelsHash[medium.imageId];
if (!rIdImage) {
rIdImage = nextRid(drawing.rels);
drawingRelsHash[medium.imageId] = rIdImage;
drawing.rels.push({
Id: rIdImage,
Type: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
Target: '../media/' + bookImage.name + '.' + bookImage.extension
});
}
drawing.anchors.push({
picture: {
rId: rIdImage
},
range: medium.range
});
}
});
},
render: function render(xmlStream, model) {
xmlStream.openXml(XmlStream.StdDocAttributes);
xmlStream.openNode('worksheet', WorkSheetXform.WORKSHEET_ATTRIBUTES);
var sheetFormatPropertiesModel = model.properties ? {
defaultRowHeight: model.properties.defaultRowHeight,
dyDescent: model.properties.dyDescent,
outlineLevelCol: model.properties.outlineLevelCol,
outlineLevelRow: model.properties.outlineLevelRow
} : undefined;
var sheetPropertiesModel = {
tabColor: model.properties && model.properties.tabColor,
pageSetup: model.pageSetup && model.pageSetup.fitToPage ? {
fitToPage: model.pageSetup.fitToPage
} : undefined
};
var pageMarginsModel = model.pageSetup && model.pageSetup.margins;
var printOptionsModel = {
showRowColHeaders: model.showRowColHeaders,
showGridLines: model.showGridLines,
horizontalCentered: model.horizontalCentered,
verticalCentered: model.verticalCentered
};
this.map.sheetPr.render(xmlStream, sheetPropertiesModel);
this.map.dimension.render(xmlStream, model.dimensions);
this.map.sheetViews.render(xmlStream, model.views);
this.map.sheetFormatPr.render(xmlStream, sheetFormatPropertiesModel);
this.map.cols.render(xmlStream, model.cols);
this.map.sheetData.render(xmlStream, model.rows);
this.map.autoFilter.render(xmlStream, model.autoFilter);
this.map.mergeCells.render(xmlStream, model.mergeCells);
this.map.dataValidations.render(xmlStream, model.dataValidations);
// For some reason hyperlinks have to be after the data validations
this.map.hyperlinks.render(xmlStream, model.hyperlinks);
this.map.pageMargins.render(xmlStream, pageMarginsModel);
this.map.printOptions.render(xmlStream, printOptionsModel);
this.map.pageSetup.render(xmlStream, model.pageSetup);
this.map.drawing.render(xmlStream, model.drawing);
this.map.picture.render(xmlStream, model.background); // Note: must be after drawing
xmlStream.closeNode();
},
parseOpen: function parseOpen(node) {
if (this.parser) {
this.parser.parseOpen(node);
return true;
}
if (node.name === 'worksheet') {
_.each(this.map, function (xform) {
xform.reset();
});
return true;
}
this.parser = this.map[node.name];
if (this.parser) {
this.parser.parseOpen(node);
}
return true;
},
parseText: function parseText(text) {
if (this.parser) {
this.parser.parseText(text);
}
},
parseClose: function parseClose(name) {
if (this.parser) {
if (!this.parser.parseClose(name)) {
this.parser = undefined;
}
return true;
}
switch (name) {
case 'worksheet':
var properties = this.map.sheetFormatPr.model;
if (this.map.sheetPr.model && this.map.sheetPr.model.tabColor) {
properties.tabColor = this.map.sheetPr.model.tabColor;
}
var sheetProperties = {
fitToPage: this.map.sheetPr.model && this.map.sheetPr.model.pageSetup && this.map.sheetPr.model.pageSetup.fitToPage || false,
margins: this.map.pageMargins.model
};
var pageSetup = Object.assign(sheetProperties, this.map.pageSetup.model, this.map.printOptions.model);
this.model = {
dimensions: this.map.dimension.model,
cols: this.map.cols.model,
rows: this.map.sheetData.model,
mergeCells: this.map.mergeCells.model,
hyperlinks: this.map.hyperlinks.model,
dataValidations: this.map.dataValidations.model,
properties: properties,
views: this.map.sheetViews.model,
pageSetup: pageSetup,
background: this.map.picture.model,
drawing: this.map.drawing.model
};
if (this.map.autoFilter.model) {
this.model.autoFilter = this.map.autoFilter.model;
}
return false;
default:
// not quite sure how we get here!
return true;
}
},
reconcile: function reconcile(model, options) {
// options.merges = new Merges();
// options.merges.reconcile(model.mergeCells, model.rows);
var rels = (model.relationships || []).reduce(function (h, rel) {
h[rel.Id] = rel;
return h;
}, {});
options.hyperlinkMap = (model.hyperlinks || []).reduce(function (h, hyperlink) {
if (hyperlink.rId) {
h[hyperlink.address] = rels[hyperlink.rId].Target;
}
return h;
}, {});
options.formulae = {};
// compact the rows and cells
model.rows = model.rows && model.rows.filter(Boolean) || [];
model.rows.forEach(function (row) {
row.cells = row.cells && row.cells.filter(Boolean) || [];
});
this.map.cols.reconcile(model.cols, options);
this.map.sheetData.reconcile(model.rows, options);
model.media = [];
if (model.drawing) {
var drawingRel = rels[model.drawing.rId];
var match = drawingRel.Target.match(/\/drawings\/([a-zA-Z0-9]+)[.][a-zA-Z]{3,4}$/);
if (match) {
var drawingName = match[1];
var drawing = options.drawings[drawingName];
drawing.anchors.forEach(function (anchor) {
if (anchor.medium) {
var image = {
type: 'image',
imageId: anchor.medium.index,
range: anchor.range
};
model.media.push(image);
}
});
}
}
var backgroundRel = model.background && rels[model.background.rId];
if (backgroundRel) {
var target = backgroundRel.Target.split('/media/')[1];
var imageId = options.mediaIndex && options.mediaIndex[target];
if (imageId !== undefined) {
model.media.push({
type: 'background',
imageId: imageId
});
}
}
delete model.relationships;
delete model.hyperlinks;
}
});
//# sourceMappingURL=worksheet-xform.js.map