excellentexport 3.7.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,335 +1,203 @@
1
- /**
2
- * ExcellentExport 3.7.0
3
- * A client side Javascript export to Excel.
4
- *
5
- * @author: Jordi Burgos (jordiburgos@gmail.com)
6
- * @url: https://github.com/jmaister/excellentexport
7
- *
8
- */
9
-
10
- import * as XLSX from 'xlsx';
11
-
12
- export interface ConvertOptions {
13
- anchor?: (string|HTMLAnchorElement),
14
- openAsDownload?: boolean,
15
- format: ('csv' | 'xls' | 'xlsx'),
16
- filename?: string,
17
- }
18
- export interface FromOptions {
19
- table?: (string|HTMLTableElement),
20
- array?: any[][],
21
- }
22
- export interface SheetOptions {
23
- name: string,
24
- from: FromOptions,
25
- removeColumns?: number[],
26
- filterRowFn?(row:any[]): boolean ,
27
- fixValue?(value:any, row:number, column:number): any,
28
- fixArray?(array:any[][]): any[][],
29
- }
30
-
31
-
32
- const ExcellentExport = function() {
33
-
34
- const b64toBlob = function (b64Data:string, contentType:string, sliceSize?:number): Blob {
35
- // function taken from http://stackoverflow.com/a/16245768/2591950
36
- // author Jeremy Banks http://stackoverflow.com/users/1114/jeremy-banks
37
- contentType = contentType || '';
38
- sliceSize = sliceSize || 512;
39
-
40
- const byteCharacters = atob(b64Data);
41
- const byteArrays = [];
42
-
43
- for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
44
- const slice = byteCharacters.slice(offset, offset + sliceSize);
45
-
46
- const byteNumbers = new Array(slice.length);
47
- for (let i = 0; i < slice.length; i = i + 1) {
48
- byteNumbers[i] = slice.charCodeAt(i);
49
- }
50
-
51
- const byteArray = new Uint8Array(byteNumbers);
52
-
53
- byteArrays.push(byteArray);
54
- }
55
-
56
- return new Blob(byteArrays, {
57
- type: contentType
58
- });
59
- };
60
-
61
- const version = "3.7.0";
62
- const template = {excel: '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta name=ProgId content=Excel.Sheet> <meta name=Generator content="Microsoft Excel 11"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>'};
63
- let csvDelimiter = ",";
64
- let csvNewLine = "\r\n";
65
-
66
- /**
67
- * Convert a string to Base64.
68
- */
69
- const base64 = function(s:string) : string {
70
- return btoa(unescape(encodeURIComponent(s)));
71
- };
72
-
73
- const format = function(s:string, context:any) : string {
74
- return s.replace(new RegExp("{(\\w+)}", "g"), function(m, p) {
75
- return context[p];
76
- });
77
- };
78
-
79
- /**
80
- * Get element by ID.
81
- * @param {*} element
82
- */
83
- const getTable = function(element :(HTMLTableElement|string)) : HTMLTableElement {
84
- if (typeof element === 'string') {
85
- return document.getElementById(element) as HTMLTableElement;
86
- }
87
- return element;
88
- };
89
-
90
- /**
91
- * Get element by ID.
92
- * @param {*} element
93
- */
94
- const getAnchor = function(element :(HTMLAnchorElement|string)) : HTMLAnchorElement {
95
- if (typeof element === 'string') {
96
- return document.getElementById(element) as HTMLAnchorElement;
97
- }
98
- return element;
99
- };
100
-
101
- /**
102
- * Encode a value for CSV.
103
- * @param {*} value
104
- */
105
- const fixCSVField = function(value) {
106
- let fixedValue = value;
107
- const addQuotes = (value.indexOf(csvDelimiter) !== -1) || (value.indexOf('\r') !== -1) || (value.indexOf('\n') !== -1);
108
- const replaceDoubleQuotes = (value.indexOf('"') !== -1);
109
-
110
- if (replaceDoubleQuotes) {
111
- fixedValue = fixedValue.replace(/"/g, '""');
112
- }
113
- if (addQuotes || replaceDoubleQuotes) {
114
- fixedValue = '"' + fixedValue + '"';
115
- }
116
-
117
- return fixedValue;
118
- };
119
-
120
- const tableToArray = function(table:HTMLTableElement) : any[][] {
121
- let tableInfo = Array.prototype.map.call(table.querySelectorAll('tr'), function(tr) {
122
- return Array.prototype.map.call(tr.querySelectorAll('th,td'), function(td) {
123
- return td.innerHTML;
124
- });
125
- });
126
- return tableInfo;
127
- };
128
-
129
- const tableToCSV = function(table:HTMLTableElement) : string {
130
- let data = "";
131
- for (let i = 0; i < table.rows.length; i=i+1) {
132
- const row = table.rows[i];
133
- for (let j = 0; j < row.cells.length; j=j+1) {
134
- const col = row.cells[j];
135
- data = data + (j ? csvDelimiter : '') + fixCSVField(col.textContent.trim());
136
- }
137
- data = data + csvNewLine;
138
- }
139
- return data;
140
- };
141
-
142
- const createDownloadLink = function(anchor:HTMLAnchorElement, base64data:string, exporttype:string, filename:string) : boolean {
143
- if (window.navigator.msSaveBlob) {
144
- const blob = b64toBlob(base64data, exporttype);
145
- window.navigator.msSaveBlob(blob, filename);
146
- return false;
147
- } else if (window.URL.createObjectURL) {
148
- const blob = b64toBlob(base64data, exporttype);
149
- anchor.href = window.URL.createObjectURL(blob);
150
- } else {
151
- anchor.download = filename;
152
- anchor.href = "data:" + exporttype + ";base64," + base64data;
153
- }
154
-
155
- // Return true to allow the link to work
156
- return true;
157
- };
158
-
159
- // String to ArrayBuffer
160
- const s2ab = function (s:string): ArrayBuffer {
161
- let buf = new ArrayBuffer(s.length);
162
- let view = new Uint8Array(buf);
163
- for (let i=0; i !== s.length; ++i) {
164
- view[i] = s.charCodeAt(i) & 0xFF;
165
- }
166
- return buf;
167
- };
168
-
169
- const removeColumn = function(arr2d:any[][], colIndex:number) {
170
- for (let i = 0; i < arr2d.length; i++) {
171
- const row = arr2d[i];
172
- row.splice(colIndex, 1);
173
- }
174
- };
175
-
176
- /*
177
- ExcellentExport.convert(options, sheets);
178
-
179
- Options:
180
- {
181
- anchor: String or HTML Element,
182
- openAsDownload: boolean, // Use this options if not using an anchor tag
183
- format: 'xlsx' or 'xls' or 'csv',
184
- filename: String
185
- }
186
-
187
- Sheets must be an array of sheet configuration objects. Sheet description:
188
- [
189
- {
190
- name: 'Sheet 1', // Sheet name
191
- from: {
192
- table: String/Element, // Table ID or table element
193
- array: [...] // Array with the data. Array where each element is a row. Every row is an array of the cells.
194
- },
195
- removeColumns: [...], // Array of column indexes (from 0)
196
- filterRowFn: function(row) {return true}, // Function to decide which rows are returned
197
- fixValue: function(value, row, column) {return fixedValue} // Function to fix values, receiving value, row num, column num
198
- fixArray: function(array) {return array} // Function to manipulate the whole data array
199
- ...
200
- },
201
- {
202
- ...
203
- }, ...
204
- ]
205
- */
206
- const convert = function(options:ConvertOptions, sheets:SheetOptions[]) {
207
- const workbook = {
208
- SheetNames: [],
209
- Sheets: {}
210
- };
211
-
212
- if (!options.format) {
213
- throw new Error("'format' option must be defined");
214
- }
215
- if (options.format === 'csv' && sheets.length > 1) {
216
- throw new Error("'csv' format only supports one sheet");
217
- }
218
-
219
- sheets.forEach(function(sheetConf:SheetOptions, index:number) {
220
- const name = sheetConf.name;
221
- if (!name) {
222
- throw new Error('Sheet ' + index + ' must have the property "name".');
223
- }
224
-
225
- // Select data source
226
- let dataArray;
227
- if (sheetConf.from && sheetConf.from.table) {
228
- dataArray = tableToArray(getTable(sheetConf.from.table));
229
- } else if(sheetConf.from && sheetConf.from.array) {
230
- dataArray = sheetConf.from.array
231
- } else {
232
- throw new Error('No data for sheet: [' + name + ']');
233
- }
234
-
235
- // Filter rows
236
- if (sheetConf.filterRowFn) {
237
- if (sheetConf.filterRowFn instanceof Function) {
238
- dataArray = dataArray.filter(sheetConf.filterRowFn);
239
- } else {
240
- throw new Error('Parameter "filterRowFn" must be a function.');
241
- }
242
- }
243
- // Filter columns
244
- if (sheetConf.removeColumns) {
245
- const toRemove = sheetConf.removeColumns.sort().reverse();
246
- toRemove.forEach(function(columnIndex) {
247
- removeColumn(dataArray, columnIndex);
248
- });
249
- }
250
-
251
- // Convert data, by value
252
- if (sheetConf.fixValue && typeof sheetConf.fixValue === 'function') {
253
- const fn = sheetConf.fixValue;
254
- dataArray.map((r, rownum) => {
255
- r.map((value, colnum) => {
256
- dataArray[rownum][colnum] = fn(value, rownum, colnum);
257
- });
258
- });
259
- }
260
-
261
- // Convert data, whole array
262
- if (sheetConf.fixArray && typeof sheetConf.fixArray === 'function') {
263
- const fn = sheetConf.fixArray;
264
- dataArray = fn(dataArray);
265
- }
266
-
267
- // Create sheet
268
- workbook.SheetNames.push(name);
269
- const worksheet = XLSX.utils.aoa_to_sheet(dataArray, {sheet: name} as XLSX.AOA2SheetOpts);
270
- workbook.Sheets[name] = worksheet;
271
- });
272
-
273
- const wbOut:string = XLSX.write(workbook, {bookType: options.format, bookSST:true, type: 'binary'});
274
- try {
275
- const blob = new Blob([s2ab(wbOut)], { type: "application/octet-stream" });
276
- const filename = (options.filename || 'download') + '.' + options.format;
277
- // Support for IE.
278
- if (window.navigator.msSaveBlob) {
279
- window.navigator.msSaveBlob(blob, filename);
280
- return false;
281
- }
282
- if (options.anchor) {
283
- const anchor = getAnchor(options.anchor);
284
- anchor.href = window.URL.createObjectURL(blob);
285
- anchor.download = filename;
286
- } else if (options.openAsDownload) {
287
- const a = document.createElement("a");
288
- a.href = URL.createObjectURL(blob);
289
- a.download = filename;
290
- document.body.appendChild(a);
291
- a.click();
292
- document.body.removeChild(a);
293
- } else {
294
- throw new Error('Options should specify an anchor or openAsDownload=true.')
295
- }
296
-
297
- } catch(e) {
298
- throw new Error('Error converting to '+ options.format + '. ' + e);
299
- }
300
- return wbOut;
301
-
302
- };
303
-
304
- return {
305
- version: function(): string {
306
- return version;
307
- },
308
- excel: function(anchor:(HTMLAnchorElement|string), table:HTMLTableElement, name:string) {
309
- table = getTable(table);
310
- anchor = getAnchor(anchor);
311
- const ctx = {worksheet: name || 'Worksheet', table: table.innerHTML};
312
- const b64 = base64(format(template.excel, ctx));
313
- return createDownloadLink(anchor, b64, 'application/vnd.ms-excel','export.xls');
314
- },
315
- csv: function(anchor:(HTMLAnchorElement|string), table:HTMLTableElement, delimiter?:string, newLine?:string) {
316
- if (delimiter !== undefined && delimiter) {
317
- csvDelimiter = delimiter;
318
- }
319
- if (newLine !== undefined && newLine) {
320
- csvNewLine = newLine;
321
- }
322
-
323
- table = getTable(table);
324
- anchor = getAnchor(anchor);
325
- const csvData = "\uFEFF" + tableToCSV(table);
326
- const b64 = base64(csvData);
327
- return createDownloadLink(anchor, b64, 'application/csv', 'export.csv');
328
- },
329
- convert: function(options:ConvertOptions, sheets:SheetOptions[]) {
330
- return convert(options, sheets);
331
- }
332
- };
333
- }();
334
-
335
- export default ExcellentExport;
1
+ /**
2
+ * ExcellentExport 3.7.2
3
+ * A client side Javascript export to Excel.
4
+ *
5
+ * @author: Jordi Burgos (jordiburgos@gmail.com)
6
+ * @url: https://github.com/jmaister/excellentexport
7
+ *
8
+ */
9
+
10
+ import * as XLSX from 'xlsx';
11
+
12
+ import * as utils from './utils';
13
+
14
+ export interface ConvertOptions {
15
+ anchor?: (string|HTMLAnchorElement),
16
+ openAsDownload?: boolean,
17
+ format: ('csv' | 'xls' | 'xlsx'),
18
+ filename?: string,
19
+ rtl?: boolean,
20
+ }
21
+ export interface FromOptions {
22
+ table?: (string|HTMLTableElement),
23
+ array?: any[][],
24
+ }
25
+ export interface SheetOptions {
26
+ name: string,
27
+ from: FromOptions,
28
+ removeColumns?: number[],
29
+ filterRowFn?(row:any[]): boolean ,
30
+ fixValue?(value:any, row:number, column:number): any,
31
+ fixArray?(array:any[][]): any[][],
32
+ rtl?: boolean
33
+ }
34
+
35
+
36
+ const ExcellentExport = function() {
37
+
38
+ const version = "3.8.0";
39
+
40
+ /*
41
+ ExcellentExport.convert(options, sheets);
42
+
43
+ Options:
44
+ {
45
+ anchor: String or HTML Element,
46
+ openAsDownload: boolean, // Use this options if not using an anchor tag
47
+ format: 'xlsx' or 'xls' or 'csv',
48
+ filename: String,
49
+ rtl: boolean (optional), specify if all the workbook has text in RTL mode
50
+ }
51
+
52
+ Sheets must be an array of sheet configuration objects. Sheet description:
53
+ [
54
+ {
55
+ name: 'Sheet 1', // Sheet name
56
+ from: {
57
+ table: String/Element, // Table ID or table element
58
+ array: [...] // Array with the data. Array where each element is a row. Every row is an array of the cells.
59
+ },
60
+ removeColumns: [...], // Array of column indexes (from 0)
61
+ filterRowFn: function(row) {return true}, // Function to decide which rows are returned
62
+ fixValue: function(value, row, column) {return fixedValue} // Function to fix values, receiving value, row num, column num
63
+ fixArray: function(array) {return array} // Function to manipulate the whole data array
64
+ rtl: boolean // optional: specify if the sheet has text in RTL mode
65
+ ...
66
+ },
67
+ {
68
+ ...
69
+ }, ...
70
+ ]
71
+ */
72
+ const convert = function(options:ConvertOptions, sheets:SheetOptions[]) {
73
+ const workbook = {
74
+ SheetNames: [],
75
+ Sheets: {},
76
+ Views: []
77
+ };
78
+
79
+ if (!options.format) {
80
+ throw new Error("'format' option must be defined");
81
+ }
82
+ if (options.format === 'csv' && sheets.length > 1) {
83
+ throw new Error("'csv' format only supports one sheet");
84
+ }
85
+
86
+ sheets.forEach(function(sheetConf:SheetOptions, index:number) {
87
+ const name = sheetConf.name;
88
+ if (!name) {
89
+ throw new Error('Sheet ' + index + ' must have the property "name".');
90
+ }
91
+
92
+ // Select data source
93
+ let dataArray: any[][];
94
+ if (sheetConf.from && sheetConf.from.table) {
95
+ dataArray = utils.tableToArray(utils.getTable(sheetConf.from.table));
96
+ } else if(sheetConf.from && sheetConf.from.array) {
97
+ dataArray = sheetConf.from.array
98
+ } else {
99
+ throw new Error('No data for sheet: [' + name + ']');
100
+ }
101
+
102
+ // Filter rows
103
+ if (sheetConf.filterRowFn) {
104
+ if (sheetConf.filterRowFn instanceof Function) {
105
+ dataArray = dataArray.filter(sheetConf.filterRowFn);
106
+ } else {
107
+ throw new Error('Parameter "filterRowFn" must be a function.');
108
+ }
109
+ }
110
+ // Filter columns
111
+ if (sheetConf.removeColumns) {
112
+ utils.removeColumns(dataArray, sheetConf.removeColumns);
113
+ }
114
+
115
+ // Convert data. Function applied to each value independently, receiving (value, rownum, colnum)
116
+ if (sheetConf.fixValue && typeof sheetConf.fixValue === 'function') {
117
+ const fn = sheetConf.fixValue;
118
+ dataArray.map((r, rownum) => {
119
+ r.map((value, colnum) => {
120
+ dataArray[rownum][colnum] = fn(value, rownum, colnum);
121
+ });
122
+ });
123
+ }
124
+
125
+ // Convert data, whole array
126
+ if (sheetConf.fixArray && typeof sheetConf.fixArray === 'function') {
127
+ const fn = sheetConf.fixArray;
128
+ dataArray = fn(dataArray);
129
+ }
130
+
131
+ // Create sheet
132
+ workbook.SheetNames.push(name);
133
+ const worksheet = XLSX.utils.aoa_to_sheet(dataArray, {sheet: name} as XLSX.AOA2SheetOpts);
134
+ workbook.Sheets[name] = worksheet;
135
+ workbook.Views.push({RTL: options.rtl || sheetConf.rtl || false});
136
+ });
137
+
138
+ const wbOut:string = XLSX.write(workbook, {bookType: options.format, bookSST:true, type: 'binary'});
139
+ try {
140
+ const blob = new Blob([utils.string2ArrayBuffer(wbOut)], { type: "application/octet-stream" });
141
+ const filename = (options.filename || 'download') + '.' + options.format;
142
+ // Support for IE.
143
+ if (window.navigator.msSaveBlob) {
144
+ window.navigator.msSaveBlob(blob, filename);
145
+ return false;
146
+ }
147
+ if (options.anchor) {
148
+ const anchor = utils.getAnchor(options.anchor);
149
+ anchor.href = window.URL.createObjectURL(blob);
150
+ anchor.download = filename;
151
+ } else if (options.openAsDownload) {
152
+ const a = document.createElement("a");
153
+ a.href = URL.createObjectURL(blob);
154
+ a.download = filename;
155
+ document.body.appendChild(a);
156
+ a.click();
157
+ document.body.removeChild(a);
158
+ } else {
159
+ throw new Error('Options should specify an anchor or openAsDownload=true.')
160
+ }
161
+
162
+ } catch(e) {
163
+ throw new Error('Error converting to '+ options.format + '. ' + e);
164
+ }
165
+ return wbOut;
166
+
167
+ };
168
+
169
+ return {
170
+ version: function(): string {
171
+ return version;
172
+ },
173
+ excel: function(anchor:(HTMLAnchorElement|string), table:HTMLTableElement, name:string) {
174
+ table = utils.getTable(table);
175
+ anchor = utils.getAnchor(anchor);
176
+ const ctx = {worksheet: name || 'Worksheet', table: table.innerHTML};
177
+ const b64 = utils.base64(utils.format(utils.templates.excel, ctx));
178
+ return utils.createDownloadLink(anchor, b64, 'application/vnd.ms-excel','export.xls');
179
+ },
180
+ csv: function(anchor:(HTMLAnchorElement|string), table:HTMLTableElement, delimiter?:string, newLine?:string) {
181
+ let csvDelimiter = ",";
182
+ let csvNewLine = "\r\n";
183
+
184
+ if (delimiter !== undefined && delimiter) {
185
+ csvDelimiter = delimiter;
186
+ }
187
+ if (newLine !== undefined && newLine) {
188
+ csvNewLine = newLine;
189
+ }
190
+
191
+ table = utils.getTable(table);
192
+ anchor = utils.getAnchor(anchor);
193
+ const csvData = "\uFEFF" + utils.tableToCSV(table, csvDelimiter, csvNewLine);
194
+ const b64 = utils.base64(csvData);
195
+ return utils.createDownloadLink(anchor, b64, 'application/csv', 'export.csv');
196
+ },
197
+ convert: function(options:ConvertOptions, sheets:SheetOptions[]) {
198
+ return convert(options, sheets);
199
+ }
200
+ };
201
+ }();
202
+
203
+ export default ExcellentExport;