• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16export class ExcelFormater {
17  static tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>';
18  static base64 = function (s: any) {
19    return window.btoa(unescape(encodeURIComponent(s)));
20  };
21
22  static format(s: any, c: any): string {
23    return s.replace(/{(\w+)}/g, function (m: any, p: any) {
24      return c[p];
25    });
26  }
27
28  static createExcelRow(columns: any[], data: any): string {
29    let rowsXML = '';
30    rowsXML += '<Row>';
31    for (let k = 0; k < columns.length; k++) {
32      let dataIndex = columns[k].getAttribute('data-index');
33      let columnName = columns[k].getAttribute('title');
34      if (columnName == '') {
35        columnName = dataIndex;
36      }
37      let ctx = {
38        attributeStyleID: '',
39        nameType: 'String',
40        data: data ? data[dataIndex] || '' : columnName,
41        attributeFormula: '',
42      };
43      rowsXML += this.format(this.tmplCellXML, ctx);
44    }
45    rowsXML += '</Row>';
46    if (data && data.children != undefined && data.children.length > 0) {
47      data.children.forEach((child: any) => {
48        rowsXML += this.createExcelRow(columns, child);
49      });
50    }
51    return rowsXML;
52  }
53
54  static addImage(baseStr: string) {
55    return `<Row>${this.format(this.tmplCellXML, {
56      attributeStyleID: '',
57      nameType: 'String',
58      data: `<div><img src="${baseStr}"></img></div>`,
59      attributeFormula: '',
60    })}</Row>`;
61  }
62
63  static testExport(dataSource: { columns: any[]; tables: any[]; sheetName: string }[], fileName: string) {
64    this.tablesToHtmlExcelMultipleSheet(dataSource, fileName);
65  }
66
67  static tablesToHtmlExcelMultipleSheet(
68    dataSource: { columns: any[]; tables: any[]; sheetName: string }[],
69    fileName: string,
70    image?: string
71  ) {
72    let sheets: any[] = [];
73    dataSource.forEach((data) => {
74      sheets.push(this.createTableData(data.columns, data.tables, image));
75    });
76    this.tablesToExcelTestSheet(sheets, fileName, dataSource);
77  }
78
79  static createTableData(columns: any[], dataSource: any[], image?: string) {
80    let tableData = '';
81    let columnDatas = columns.map((column) => {
82      let dataIndex = column.getAttribute('data-index');
83      let columnName = column.getAttribute('title');
84      if (columnName == '') {
85        columnName = dataIndex;
86      }
87      return {
88        columnName: columnName,
89        dataIndex: dataIndex,
90      };
91    });
92    tableData += this.createTHead(
93      columnDatas.map((item) => {
94        return item.columnName;
95      })
96    );
97    let columnDataIndexes = columnDatas.map((item) => item.dataIndex);
98    dataSource.forEach((data, index) => {
99      if (index == 0 && image) {
100        tableData += this.createTableRow(columnDataIndexes, data, image);
101      } else {
102        tableData += this.createTableRow(columnDataIndexes, data);
103      }
104    });
105    return tableData;
106  }
107
108  static createTHead(columns: any[]) {
109    let header = '<thead>';
110    columns.forEach((column) => {
111      header += `<td>${column}</td>`;
112    });
113    header += '</thrad>';
114    return header;
115  }
116
117  static createTableRow(columns: any[], data: any, image?: any) {
118    let childrenData = '';
119    if (data.children !== undefined) {
120      data.children.forEach((child: any) => {
121        if (child) {
122          childrenData += this.createTableRow(columns, child);
123        }
124      });
125    }
126    return `<tr>${columns
127      .map((column) => {
128        return `<td>${(data[column] + '').replace('μ', 'u')}</td>` || '';
129      })
130      .join('')}${image ? `<td><div><img src="${image}"></img></div></td>` : ''}</tr>${childrenData}`;
131  }
132
133  static tablesToExcelTestSheet(
134    tables: any[],
135    filename: string,
136    dataSource: { columns: any[]; tables: any[]; sheetName: string }[]
137  ) {
138    let uri = 'data:application/vnd.ms-excel;base64,',
139      html_start = `<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">`,
140      template_ExcelWorksheet = `<x:ExcelWorksheet><x:Name>{SheetName}</x:Name><x:WorksheetSource HRef="sheet{SheetIndex}.htm"/><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>`,
141      template_ListWorksheet = `<o:File HRef="sheet{SheetIndex}.htm"/>`,
142      template_HTMLWorksheet =
143        `
144------=_NextPart_dummy
145Content-Location: sheet{SheetIndex}.htm
146Content-Type: text/html; charset=windows-1252
147
148` +
149        html_start +
150        `
151<head>
152    <meta http-equiv="Content-Type" charset="UTF-8" content="text/html; charset=windows-1252">
153    <link id="Main-File" rel="Main-File" href="../WorkBook.htm">
154    <link rel="File-List" href="filelist.xml">
155</head>
156<body><table>{SheetContent}</table></body>
157</html>`,
158      template_WorkBook =
159        `MIME-Version: 1.0
160X-Document-Type: Workbook
161Content-Type: multipart/related; boundary="----=_NextPart_dummy"
162
163------=_NextPart_dummy
164Content-Location: WorkBook.htm
165Content-Type: text/html; charset=windows-1252
166
167` +
168        html_start +
169        `
170<head>
171<meta name="Excel Workbook Frameset">
172<meta http-equiv="Content-Type" charset="UTF-8" content="text/html; charset=windows-1252">
173<link rel="File-List" href="filelist.xml">
174<!--[if gte mso 9]><xml>
175 <x:ExcelWorkbook>
176    <x:ExcelWorksheets>{ExcelWorksheets}</x:ExcelWorksheets>
177    <x:ActiveSheet>0</x:ActiveSheet>
178 </x:ExcelWorkbook>
179</xml><![endif]-->
180</head>
181<frameset>
182    <frame src="sheet0.htm" name="frSheet">
183    <noframes><body><p>This page uses frames, but your browser does not support them.</p></body></noframes>
184</frameset>
185</html>
186{HTMLWorksheets}
187Content-Location: filelist.xml
188Content-Type: text/xml; charset="utf-8"
189
190<xml xmlns:o="urn:schemas-microsoft-com:office:office">
191    <o:MainFile HRef="../WorkBook.htm"/>
192    {ListWorksheets}
193    <o:File HRef="filelist.xml"/>
194</xml>
195------=_NextPart_dummy--
196`;
197    let context_WorkBook = {
198      ExcelWorksheets: '',
199      HTMLWorksheets: '',
200      ListWorksheets: '',
201    };
202    tables.forEach((item, sheetIndex) => {
203      context_WorkBook.ExcelWorksheets += this.format(template_ExcelWorksheet, {
204        SheetIndex: sheetIndex,
205        SheetName: dataSource[sheetIndex].sheetName,
206      });
207      context_WorkBook.HTMLWorksheets += this.format(template_HTMLWorksheet, {
208        SheetIndex: sheetIndex,
209        SheetContent: item,
210      });
211      context_WorkBook.ListWorksheets += this.format(template_ListWorksheet, {
212        SheetIndex: sheetIndex,
213      });
214    });
215    let link = document.createElement('a');
216    link.href = uri + this.base64(this.format(template_WorkBook, context_WorkBook));
217    link.download = filename + '.xls';
218    link.target = '_blank';
219    link.click();
220  }
221}
222