exportor.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /**
  2. * Created by zhuth on 2019/07/08.
  3. */
  4. let Base64 = require('./base64.js');
  5. ;exports = module.exports = (function () {
  6. // "use strict";
  7. let uri = 'data:application/vnd.ms-excel;base64,',
  8. tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?>'
  9. + '<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
  10. + '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">'
  11. + '<Author>{author}</Author>'
  12. + '<Created>{created}</Created>'
  13. +'</DocumentProperties>'
  14. + '{styles}'
  15. + '{worksheets}'
  16. + '</Workbook>',
  17. tmpStyleXML = '<Styles>'
  18. + '<Style ss:ID="Bold"><Font ss:Bold="1"/></Style>'
  19. + '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
  20. + '<Style ss:ID="Date"><NumberFormat ss:Format="yyyy-mm-dd"></NumberFormat></Style>'
  21. + '<Style ss:ID="Center"><Alignment ss:Horizontal="Center" ss:Vertical="Center"/></Style>'
  22. + '</Styles>',
  23. tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table>{columnWidth}{rows}</Table></Worksheet>',
  24. tmplColumnWidthXML = '<Column ss:Width="{width}"/>',
  25. tmplTableHeaderXML = '<Row><Cell ss:StyleID="Center" ss:MergeAcross="{columnCount}"><Data ss:Type="String">{header}</Data></Cell></Row>',
  26. tmplRowXML = '<Row>{cells}</Row>',
  27. tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>',
  28. _defaultStyleIDs = {
  29. DateTime: 'Date',
  30. },
  31. _format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) },
  32. _export = function(workbookXML, wbname) {
  33. let link = document.createElement("A");
  34. link.href = uri + Base64.encode(workbookXML);
  35. link.download = wbname || 'Workbook.xls';
  36. link.target = '_blank';
  37. document.body.appendChild(link);
  38. link.click();
  39. document.body.removeChild(link);
  40. };
  41. function Exportor(json, wbname) {
  42. this.init(json, wbname);
  43. this.workbookXML = this.generateWorkbookXML();
  44. }
  45. Exportor.prototype.init = function (json, wbname) {
  46. this.json = json;
  47. this.wbname = wbname;
  48. this.workbookXML = '';
  49. };
  50. Exportor.prototype.generateWorkbookXML = function() {
  51. let ctx = {
  52. worksheets: this.generateWorksheetsXML(),
  53. styles: tmpStyleXML,
  54. author: 'zhuth',
  55. created: 'zhuth'
  56. };
  57. return _format(tmplWorkbookXML, ctx);
  58. };
  59. Exportor.prototype.generateWorksheetsXML = function() {
  60. let str = '',
  61. sheets = this.json.sheets;
  62. for(let i = 0; i < sheets.length; i++) {
  63. str += this.generateWorksheetXML(sheets[i]);
  64. }
  65. return str;
  66. };
  67. Exportor.prototype.generateWorksheetXML = function(sheet) {
  68. const { name, header, columns, rows } = sheet;
  69. let widths = columns.map(c => c.width);
  70. let ctx = {
  71. nameWS: name,
  72. columnWidth: this.generateColumnWidth(widths),
  73. rows: this.generateTableHeaderXML(header, columns.length) + this.generateHeaderRowsXML(columns) + this.generateRowsXML(columns, rows)
  74. };
  75. let str = _format(tmplWorksheetXML, ctx);
  76. return str;
  77. };
  78. Exportor.prototype.generateTableHeaderXML = function(header, columnCount) {
  79. let str = '';
  80. if(!!header) {
  81. let ctx = {
  82. columnCount: columnCount - 1,
  83. header
  84. }
  85. str = _format(tmplTableHeaderXML, ctx);
  86. }
  87. return str
  88. };
  89. Exportor.prototype.generateColumnWidth = function(widths) {
  90. let str = '';
  91. for(let i = 0; i < widths.length; i++) {
  92. let ctx = {
  93. width: widths[i] || 100
  94. };
  95. str += _format(tmplColumnWidthXML, ctx);
  96. }
  97. return str;
  98. };
  99. Exportor.prototype.generateHeaderRowsXML = function(columns) {
  100. let cells = columns.map(c => ({ type: 'String', value: c.name, styleID: 'Bold' }));
  101. let ctx = {
  102. cells: this.generateCellsXML(cells)
  103. };
  104. let str = _format(tmplRowXML, ctx);
  105. return str;
  106. };
  107. Exportor.prototype.generateRowsXML = function(columns, rows) {
  108. let cols = columns.map(c => ({ type: c.type, name: c.name, styleID: c.styleID }));
  109. let str = '';
  110. for(let i = 0; i < rows.length; i++) {
  111. let r = rows[i];
  112. let cells = [];
  113. for(let j = 0; j < cols.length; j++) {
  114. cells.push({
  115. type: cols[j].type,
  116. value: r[j],
  117. styleID: cols[j].styleID || _defaultStyleIDs[cols[j].type]
  118. });
  119. }
  120. let ctx = {
  121. cells: this.generateCellsXML(cells)
  122. };
  123. str += _format(tmplRowXML, ctx);
  124. }
  125. return str;
  126. };
  127. Exportor.prototype.generateCellsXML = function(cells) {
  128. let str = '';
  129. for(let i = 0; i < cells.length; i++) {
  130. let ctx = {
  131. attributeStyleID: cells[i].styleID ? _format(' ss:StyleID="{styleID}"', {
  132. styleID: cells[i].styleID
  133. }) : '',
  134. attributeFormula: '',
  135. nameType: cells[i].type || 'String',
  136. data: cells[i].value || ''
  137. };
  138. str += _format(tmplCellXML, ctx);
  139. }
  140. return str;
  141. };
  142. Exportor.prototype.export = function() {
  143. _export(this.workbookXML, this.wbname);
  144. }
  145. return Exportor;
  146. })();