| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- /**
- * Created by zhuth on 2019/07/08.
- */
- ;exports = module.exports = (function () {
- // "use strict";
- let tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?>'
- + '<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
- + '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">'
- + '<Author>{author}</Author>'
- + '<Created>{created}</Created>'
- +'</DocumentProperties>'
- + '<Styles>{styles}</Styles>'
- + '{worksheets}'
- + '</Workbook>',
- tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table>{columnWidth}{rows}</Table></Worksheet>',
- tmplColumnWidthXML = '<Column ss:Width="{width}"/>',
- tmplTableHeaderXML = '<Row><Cell ss:StyleID="{styleID}" ss:MergeAcross="{columnCount}"><Data ss:Type="String">{header}</Data></Cell></Row>',
- tmplRowXML = '<Row>{cells}</Row>',
- tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>',
- _defaultStyleIDs = {
- DateTime: 'date',
- },
- tmplStyleXML = '<Style ss:ID="{styleID}">{styleNode}</Style>',
- tmplStyleNodeXML = '<{nodeName}{attributes}>{children}</{nodeName}>',
- tmplStyleNodeAttributeXML = 'ss:{attributeName}="{attributeValue}"',
- styleConfig = [{
- name: "date",
- tags: [{
- tag: "NumberFormat",
- attributes: {
- Format: "yyyy-mm-dd"
- }
- }]
- }, {
- name: "bold",
- tags: [{
- tag: "Font",
- attributes: {
- Bold: "1"
- }
- }]
- }, {
- name: "center",
- tags: [{
- tag: "Alignment",
- attributes: {
- Horizontal: "Center",
- Vertical: "Center",
- }
- }]
- }, {
- name: "header",
- tags: [{
- tag: "Font",
- attributes:{
- Color: "#FFFFFF"
- }
- }, {
- tag: "Interior",
- attributes: {
- Color: "#70AD47",
- Pattern: "Solid"
- }
- }]
- }, {
- name: "even",
- tags: [{
- tag: "Interior",
- attributes: {
- Color: "#C6E0B4",
- Pattern: "Solid"
- }
- }]
- }, {
- name: "odd",
- tags: [{
- tag: "Interior",
- attributes: {
- Color: "#A9D08E",
- Pattern: "Solid"
- }
- }]
- }, {
- name: "default",
- tags: [{
- tag: "Borders",
- tags: [{
- tag: "Border",
- attributes: {
- Position: "Right",
- LineStyle: "Continuous",
- Weight: "1",
- Color: "#EAEAEA"
- }
- }]
- }]
- }, {
- name: "border",
- tags: [{
- tag: "Borders",
- tags: [{
- tag: "Border",
- attributes: {
- Position: "Top",
- LineStyle: "Continuous",
- Weight: "1",
- Color: "#EAEAEA"
- }
- }, {
- tag: "Border",
- attributes: {
- Position: "Right",
- LineStyle: "Continuous",
- Weight: "1",
- Color: "#EAEAEA"
- }
- }, {
- tag: "Border",
- attributes: {
- Position: "Bottom",
- LineStyle: "Continuous",
- Weight: "1",
- Color: "#EAEAEA"
- }
- }, {
- tag: "Border",
- attributes: {
- Position: "Left",
- LineStyle: "Continuous",
- Weight: "1",
- Color: "#EAEAEA"
- }
- }]
- }]
- }],
- _format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) },
- _export = function(workbookXML, wbname) {
- var eleLink = document.createElement('a');
- eleLink.download = wbname || 'Workbook.xls';
- eleLink.style.display = 'none';
- var blob = new Blob([workbookXML]);
- eleLink.href = URL.createObjectURL(blob);
- document.body.appendChild(eleLink);
- eleLink.click();
- document.body.removeChild(eleLink);
- };
- function Exportor(json, wbname) {
- this.init(json, wbname);
- this.workbookXML = this.generateWorkbookXML();
- }
- Exportor.prototype.init = function (json, wbname) {
- this.json = json;
- this.wbname = wbname;
- this.workbookXML = '';
- this.styleID = 1;
- this.styles = [];
- };
- Exportor.prototype.generateWorkbookXML = function() {
- let ctx = {
- worksheets: this.generateWorksheetsXML(),
- styles: this.generateStylesXML(),
- author: 'usoftchina',
- created: new Date().getTime()
- };
- return _format(tmplWorkbookXML, ctx);
- };
- Exportor.prototype.generateStylesXML = function() {
- let str = '';
- for(let i = 0; i < this.styles.length; i++) {
- str += this.generateStyles(this.styles[i].styleID, this.styles[i].styleNames);
- }
- return str;
- };
- Exportor.prototype.generateWorksheetsXML = function() {
- let str = '',
- sheets = this.json.sheets;
- for(let i = 0; i < sheets.length; i++) {
- str += this.generateWorksheetXML(sheets[i]);
- }
- return str;
- };
- Exportor.prototype.generateWorksheetXML = function(sheet) {
- const { name, header, columns, rows } = sheet;
- let widths = columns.map(c => c.width);
- let ctx = {
- nameWS: name,
- columnWidth: this.generateColumnWidth(widths),
- rows: this.generateTableHeaderXML(header, columns.length) + this.generateHeaderRowsXML(columns) + this.generateRowsXML(columns, rows)
- };
- let str = _format(tmplWorksheetXML, ctx);
- return str;
- };
- Exportor.prototype.generateTableHeaderXML = function(header, columnCount) {
- let str = '';
- if(!!header) {
- let styleID = this.addStyle(['center', 'header', 'border']);
- let ctx = {
- styleID: styleID,
- columnCount: columnCount - 1,
- header
- }
- str = _format(tmplTableHeaderXML, ctx);
- }
- return str
- };
- Exportor.prototype.generateColumnWidth = function(widths) {
- let str = '';
- for(let i = 0; i < widths.length; i++) {
- let ctx = {
- width: widths[i] || 100
- };
- str += _format(tmplColumnWidthXML, ctx);
- }
- return str;
- };
- Exportor.prototype.generateHeaderRowsXML = function(columns) {
- let cells = columns.map(c => ({ type: 'String', value: c.name, styleNames: ['header', 'bold', 'default'] }));
- let ctx = {
- cells: this.generateCellsXML(cells)
- };
- let str = _format(tmplRowXML, ctx);
- return str;
- };
- Exportor.prototype.generateRowsXML = function(columns, rows) {
- let cols = columns.map(c => ({ type: c.type, name: c.name, styleNames: c.styleNames }));
- let str = '';
- for(let i = 0; i < rows.length; i++) {
- let r = rows[i];
- let cells = [];
- let s = (i&1) === 0 ? 'even' : 'odd';
- for(let j = 0; j < cols.length; j++) {
- cols[j].styleNames = cols[j].styleNames && cols[j].styleNames.length>0 ? cols[j].styleNames: [];
- cells.push({
- type: cols[j].type,
- value: r[j],
- styleNames: ['default', s].concat(cols[j].styleNames.concat(_defaultStyleIDs[cols[j].type] ? [_defaultStyleIDs[cols[j].type]] : []))
- });
- }
- let ctx = {
- cells: this.generateCellsXML(cells)
- };
- str += _format(tmplRowXML, ctx);
- }
- return str;
- };
- Exportor.prototype.generateCellsXML = function(cells) {
- let str = '';
- for(let i = 0; i < cells.length; i++) {
- let styleID = this.addStyle(cells[i].styleNames);
- let ctx = {
- attributeStyleID: cells[i].styleNames && cells[i].styleNames.length > 0 ? _format(' ss:StyleID="{styleID}"', {
- styleID: styleID
- }) : '',
- attributeFormula: '',
- nameType: cells[i].type || 'String',
- data: cells[i].value || ''
- };
- str += _format(tmplCellXML, ctx);
- }
- return str;
- };
- Exportor.prototype.addStyle = function(styleNames) {
- if(!styleNames || styleNames.length === 0) {
- return;
- }
- let s1 = styleNames.sort();
- let idx = -1; // 是否已存在
- outer:
- for(let i = 0; i < this.styles.length; i++) {
- let style = this.styles[i];
- let s2 = style.styleNames.sort();
- if(s1.length !== s2.length) {
- continue;
- }
- for(let j = 0; j < s1.length; j++) {
- if(s1[j] !== s2[j]) {
- continue outer;
- }
- }
- idx = i;
- }
- if(idx === -1) {
- let styleID = 's' + this.styleID++
- this.styles.push({
- styleID: styleID,
- styleNames: styleNames
- });
- return styleID;
- }else {
- return this.styles[idx].styleID;
- }
- };
- Exportor.prototype.generateStyles = function(styleID, styleNames) {
- let configs = styleNames.map(name => styleConfig.find(s => s.name === name)).filter(c => !!c);
- let arr = [];
- let str = '';
- for(let i = 0; i < configs.length; i++) {
- configs[i].tags.forEach(config => {
- arr.push(this.generateStyleNode(config));
- });
- }
- str = _format(tmplStyleXML, {
- styleID: styleID,
- styleNode: arr.join('')
- });
- return str;
- };
- Exportor.prototype.generateStyleNode = function(styleConfig) {
- let str = '';
- let attributes = [''];
- let children = [];
- let ctx = {};
- if(!!styleConfig.tags) {
- for(let i = 0; i < styleConfig.tags.length; i++) {
- let c = styleConfig.tags[i];
- children.push(this.generateStyleNode(c));
- }
- }
- styleConfig.attributes = styleConfig.attributes || [];
- for(let k in styleConfig.attributes) {
- attributes.push(_format(tmplStyleNodeAttributeXML, {
- attributeName: k,
- attributeValue: styleConfig.attributes[k]
- }));
- }
- ctx.nodeName = styleConfig.tag;
- ctx.attributes = attributes.join(' ');
- ctx.children = children.join('');
- str = _format(tmplStyleNodeXML, ctx);
- return str;
- };
- Exportor.prototype.generateStyleNodeAttribute = function(styleNodeConfig) {
- let str = '';
- for(let k in styleNodeConfig) {
- str += _format(tmplStyleNodeAttributeXML, {
- key: k,
- value: styleNodeConfig[k]
- })
- }
- return str;
- };
- Exportor.prototype.export = function() {
- _export(this.workbookXML, this.wbname);
- };
- return Exportor;
- })();
|