excellentexport 3.9.11 → 3.9.15

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,254 +1,264 @@
1
- /**
2
- * ExcellentExport 3.9.11
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
- import { CellTypes, FormatDefinition, PredefinedFormat, CellFormats, CellPatterns } from './format';
12
-
13
- import * as utils from './utils';
14
-
15
- // Fix for IE11: https://stackoverflow.com/questions/69485778/new-typescript-version-does-not-include-window-navigator-mssaveblob
16
- declare global {
17
- interface Navigator {
18
- msSaveBlob?: (blob: any, defaultName?: string) => boolean
19
- }
20
- }
21
-
22
- export interface ConvertOptions {
23
- anchor?: (string|HTMLAnchorElement),
24
- openAsDownload?: boolean,
25
- format: ('csv' | 'xls' | 'xlsx'),
26
- filename?: string,
27
- rtl?: boolean,
28
- }
29
- export interface FromOptions {
30
- table?: (string|HTMLTableElement),
31
- array?: any[][],
32
- }
33
-
34
- export interface SheetOptions {
35
- name: string,
36
- from: FromOptions,
37
- removeColumns?: number[],
38
- filterRowFn?(row:any[]): boolean ,
39
- fixValue?(value:any, row:number, column:number): any,
40
- fixArray?(array:any[][]): any[][],
41
- rtl?: boolean,
42
- formats?: (FormatDefinition | null)[],
43
- }
44
-
45
- /*
46
- export type ExcellentExportType = {
47
- version: () => string,
48
- formats: CellFormats,
49
- excel: (anchor:(HTMLAnchorElement|string), table:HTMLTableElement, name:string) => void,
50
- csv: (anchor:(HTMLAnchorElement|string), table:HTMLTableElement, delimiter?:string, newLine?:string) => void,
51
- convert: (options:ConvertOptions, sheets:SheetOptions[]) => void,
52
- }
53
- */
54
-
55
- const ExcellentExport = function() {
56
-
57
- const version = "3.9.11";
58
-
59
- /*
60
- ExcellentExport.convert(options, sheets);
61
-
62
- Options:
63
- {
64
- anchor: String or HTML Element,
65
- openAsDownload: boolean, // Use this options if not using an anchor tag
66
- format: 'xlsx' or 'xls' or 'csv',
67
- filename: String,
68
- rtl: boolean (optional), specify if all the workbook has text in RTL mode
69
- }
70
-
71
- Sheets must be an array of sheet configuration objects. Sheet description:
72
- [
73
- {
74
- name: 'Sheet 1', // Sheet name
75
- from: {
76
- table: String/Element, // Table ID or table element
77
- array: [...] // Array with the data. Array where each element is a row. Every row is an array of the cells.
78
- },
79
- removeColumns: [...], // Array of column indexes (from 0)
80
- filterRowFn: function(row) {return true}, // Function to decide which rows are returned
81
- fixValue: function(value, row, column) {return fixedValue} // Function to fix values, receiving value, row num, column num
82
- fixArray: function(array) {return array} // Function to manipulate the whole data array
83
- rtl: boolean // optional: specify if the sheet has text in RTL mode
84
- ...
85
- },
86
- {
87
- ...
88
- }, ...
89
- ]
90
- */
91
- const convert = function(options:ConvertOptions, sheets:SheetOptions[]) {
92
- const workbook = {
93
- SheetNames: [],
94
- Sheets: {},
95
- Views: []
96
- };
97
-
98
- if (!options.format) {
99
- throw new Error("'format' option must be defined");
100
- }
101
- if (options.format === 'csv' && sheets.length > 1) {
102
- throw new Error("'csv' format only supports one sheet");
103
- }
104
-
105
- sheets.forEach(function(sheetConf:SheetOptions, index:number) {
106
- const name = sheetConf.name;
107
- if (!name) {
108
- throw new Error('Sheet ' + index + ' must have the property "name".');
109
- }
110
-
111
- // Select data source
112
- let dataArray: any[][];
113
- if (sheetConf.from && sheetConf.from.table) {
114
- dataArray = utils.tableToArray(utils.getTable(sheetConf.from.table));
115
- } else if(sheetConf.from && sheetConf.from.array) {
116
- dataArray = sheetConf.from.array
117
- } else {
118
- throw new Error('No data for sheet: [' + name + ']');
119
- }
120
-
121
- // Filter rows
122
- if (sheetConf.filterRowFn) {
123
- if (sheetConf.filterRowFn instanceof Function) {
124
- dataArray = dataArray.filter(sheetConf.filterRowFn);
125
- } else {
126
- throw new Error('Parameter "filterRowFn" must be a function.');
127
- }
128
- }
129
- // Filter columns
130
- if (sheetConf.removeColumns) {
131
- utils.removeColumns(dataArray, sheetConf.removeColumns);
132
- }
133
-
134
- // Convert data. Function applied to each value independently, receiving (value, rownum, colnum)
135
- if (sheetConf.fixValue && typeof sheetConf.fixValue === 'function') {
136
- const fn = sheetConf.fixValue;
137
- dataArray.map((r, rownum) => {
138
- r.map((value, colnum) => {
139
- dataArray[rownum][colnum] = fn(value, rownum, colnum);
140
- });
141
- });
142
- }
143
-
144
- // Convert data, whole array
145
- if (sheetConf.fixArray && typeof sheetConf.fixArray === 'function') {
146
- const fn = sheetConf.fixArray;
147
- dataArray = fn(dataArray);
148
- }
149
-
150
- // Create sheet
151
- workbook.SheetNames.push(name);
152
- const worksheet = XLSX.utils.aoa_to_sheet(dataArray, {sheet: name} as XLSX.AOA2SheetOpts);
153
-
154
- // Apply format
155
- if (sheetConf.formats) {
156
- sheetConf.formats.forEach(f => {
157
- const range = XLSX.utils.decode_range(f.range);
158
- for (let R = range.s.r; R <= range.e.r; ++R) {
159
- for (let C = range.s.c; C <= range.e.c; ++C) {
160
- const cell = worksheet[XLSX.utils.encode_cell({r: R, c: C})];
161
- if (cell && utils.hasContent(cell.v)) {
162
- // type
163
- cell.t = f.format.type;
164
-
165
- // type fix
166
- if (f.format?.type == CellTypes.BOOLEAN) {
167
- const v = cell.v.toString().toLowerCase();
168
- if (v == 'true' || v == '1') cell.v = true;
169
- if (v == 'false' || v == '0') cell.v = false;
170
- }
171
- // pattern
172
- if (f.format?.pattern) {
173
- cell.z = f.format.pattern;
174
- }
175
- }
176
- }
177
- }
178
- });
179
- }
180
-
181
-
182
- workbook.Sheets[name] = worksheet;
183
- workbook.Views.push({RTL: options.rtl || sheetConf.rtl || false});
184
- });
185
-
186
- const wbOut:string = XLSX.write(workbook, {bookType: options.format, bookSST:true, type: 'binary', compression: true});
187
- try {
188
- const blob = new Blob([utils.string2ArrayBuffer(wbOut)], { type: "application/octet-stream" });
189
- const filename = (options.filename || 'download') + '.' + options.format;
190
- // Support for IE.
191
- if (window.navigator.msSaveBlob) {
192
- window.navigator.msSaveBlob(blob, filename);
193
- return false;
194
- }
195
- if (options.anchor) {
196
- const anchor = utils.getAnchor(options.anchor);
197
- anchor.href = window.URL.createObjectURL(blob);
198
- anchor.download = filename;
199
- } else if (options.openAsDownload) {
200
- const a = document.createElement("a");
201
- a.href = URL.createObjectURL(blob);
202
- a.download = filename;
203
- document.body.appendChild(a);
204
- a.click();
205
- document.body.removeChild(a);
206
- } else {
207
- throw new Error('Options should specify an anchor or openAsDownload=true.')
208
- }
209
-
210
- } catch(e) {
211
- throw new Error('Error converting to '+ options.format + '. ' + e);
212
- }
213
- return wbOut;
214
-
215
- };
216
-
217
- return {
218
- version: function(): string {
219
- return version;
220
- },
221
- excel: function(anchor:(HTMLAnchorElement|string), table:HTMLTableElement, name:string) {
222
- table = utils.getTable(table);
223
- anchor = utils.getAnchor(anchor);
224
- const ctx = {worksheet: name || 'Worksheet', table: table.innerHTML};
225
- const b64 = utils.base64(utils.format(utils.templates.excel, ctx));
226
- return utils.createDownloadLink(anchor, b64, 'application/vnd.ms-excel','export.xls');
227
- },
228
- csv: function(anchor:(HTMLAnchorElement|string), table:HTMLTableElement, delimiter?:string, newLine?:string) {
229
- let csvDelimiter = ",";
230
- let csvNewLine = "\r\n";
231
-
232
- if (delimiter !== undefined && delimiter) {
233
- csvDelimiter = delimiter;
234
- }
235
- if (newLine !== undefined && newLine) {
236
- csvNewLine = newLine;
237
- }
238
-
239
- table = utils.getTable(table);
240
- anchor = utils.getAnchor(anchor);
241
- const csvData = "\uFEFF" + utils.tableToCSV(table, csvDelimiter, csvNewLine);
242
- const b64 = utils.base64(csvData);
243
- return utils.createDownloadLink(anchor, b64, 'application/csv', 'export.csv');
244
- },
245
- convert: function(options:ConvertOptions, sheets:SheetOptions[]) {
246
- return convert(options, sheets);
247
- },
248
- formats: PredefinedFormat,
249
- cellTypes: CellTypes,
250
- cellPatterns: CellPatterns,
251
- };
252
- }();
253
-
254
- export default ExcellentExport;
1
+ /**
2
+ * ExcellentExport 3.9.15
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
+ import { CellTypes, PredefinedFormat, CellPatterns } from './format';
12
+ import type {CellFormats, FormatDefinition} from './format';
13
+
14
+ import * as utils from './utils';
15
+
16
+ // Fix for IE11: https://stackoverflow.com/questions/69485778/new-typescript-version-does-not-include-window-navigator-mssaveblob
17
+ declare global {
18
+ interface Navigator {
19
+ msSaveBlob?: (blob: any, defaultName?: string) => boolean
20
+ }
21
+ }
22
+
23
+ export interface ConvertOptions {
24
+ anchor?: (string|HTMLAnchorElement),
25
+ openAsDownload?: boolean,
26
+ format: ('csv' | 'xls' | 'xlsx'),
27
+ filename?: string,
28
+ rtl?: boolean,
29
+ }
30
+ export interface FromOptions {
31
+ table?: (string|HTMLTableElement),
32
+ array?: any[][],
33
+ }
34
+
35
+ export interface SheetOptions {
36
+ name: string,
37
+ from: FromOptions,
38
+ removeColumns?: number[],
39
+ filterRowFn?(row:any[]): boolean ,
40
+ fixValue?(value:any, row:number, column:number): any,
41
+ fixArray?(array:any[][]): any[][],
42
+ rtl?: boolean,
43
+ formats?: (FormatDefinition | null)[],
44
+ }
45
+
46
+ /*
47
+ export type ExcellentExportType = {
48
+ version: () => string,
49
+ formats: CellFormats,
50
+ excel: (anchor:(HTMLAnchorElement|string), table:HTMLTableElement, name:string) => void,
51
+ csv: (anchor:(HTMLAnchorElement|string), table:HTMLTableElement, delimiter?:string, newLine?:string) => void,
52
+ convert: (options:ConvertOptions, sheets:SheetOptions[]) => void,
53
+ }
54
+ */
55
+
56
+ const ExcellentExport = function() {
57
+
58
+ const version = "3.9.15";
59
+
60
+ /*
61
+ ExcellentExport.convert(options, sheets);
62
+
63
+ Options:
64
+ {
65
+ anchor: String or HTML Element,
66
+ openAsDownload: boolean, // Use this options if not using an anchor tag
67
+ format: 'xlsx' or 'xls' or 'csv',
68
+ filename: String,
69
+ rtl: boolean (optional), specify if all the workbook has text in RTL mode
70
+ }
71
+
72
+ Sheets must be an array of sheet configuration objects. Sheet description:
73
+ [
74
+ {
75
+ name: 'Sheet 1', // Sheet name
76
+ from: {
77
+ table: String/Element, // Table ID or table element
78
+ array: [...] // Array with the data. Array where each element is a row. Every row is an array of the cells.
79
+ },
80
+ removeColumns: [...], // Array of column indexes (from 0)
81
+ filterRowFn: function(row) {return true}, // Function to decide which rows are returned
82
+ fixValue: function(value, row, column) {return fixedValue} // Function to fix values, receiving value, row num, column num
83
+ fixArray: function(array) {return array} // Function to manipulate the whole data array
84
+ rtl: boolean // optional: specify if the sheet has text in RTL mode
85
+ ...
86
+ },
87
+ {
88
+ ...
89
+ }, ...
90
+ ]
91
+ */
92
+ const convert = function(options:ConvertOptions, sheets:SheetOptions[]) {
93
+ const workbook = {
94
+ SheetNames: [] as string[],
95
+ Sheets: {} as {[key: string]: XLSX.WorkSheet},
96
+ Views: [] as {RTL: boolean}[]
97
+ };
98
+
99
+ if (!options.format) {
100
+ throw new Error("'format' option must be defined");
101
+ }
102
+ if (options.format === 'csv' && sheets.length > 1) {
103
+ throw new Error("'csv' format only supports one sheet");
104
+ }
105
+
106
+ sheets.forEach(function(sheetConf:SheetOptions, index:number) {
107
+ const name = sheetConf.name;
108
+ if (!name) {
109
+ throw new Error('Sheet ' + index + ' must have the property "name".');
110
+ }
111
+
112
+ // Select data source
113
+ let dataArray: any[][];
114
+ let tableMerges: {s: {r: number, c: number}, e: {r: number, c: number}}[] | null = null;
115
+ if (sheetConf.from && sheetConf.from.table) {
116
+ const tableEl = utils.getTable(sheetConf.from.table);
117
+ const parsed = utils.parseTable(tableEl);
118
+ dataArray = parsed.data;
119
+ tableMerges = parsed.merges;
120
+ } else if(sheetConf.from && sheetConf.from.array) {
121
+ dataArray = sheetConf.from.array
122
+ } else {
123
+ throw new Error('No data for sheet: [' + name + ']');
124
+ }
125
+
126
+ // Filter rows
127
+ if (sheetConf.filterRowFn) {
128
+ if (sheetConf.filterRowFn instanceof Function) {
129
+ dataArray = dataArray.filter(sheetConf.filterRowFn);
130
+ } else {
131
+ throw new Error('Parameter "filterRowFn" must be a function.');
132
+ }
133
+ }
134
+ // Filter columns
135
+ if (sheetConf.removeColumns) {
136
+ utils.removeColumns(dataArray, sheetConf.removeColumns);
137
+ }
138
+
139
+ // Convert data. Function applied to each value independently, receiving (value, rownum, colnum)
140
+ if (sheetConf.fixValue && typeof sheetConf.fixValue === 'function') {
141
+ const fn = sheetConf.fixValue;
142
+ dataArray.map((r, rownum) => {
143
+ r.map((value, colnum) => {
144
+ dataArray[rownum][colnum] = fn(value, rownum, colnum);
145
+ });
146
+ });
147
+ }
148
+
149
+ // Convert data, whole array
150
+ if (sheetConf.fixArray && typeof sheetConf.fixArray === 'function') {
151
+ const fn = sheetConf.fixArray;
152
+ dataArray = fn(dataArray);
153
+ }
154
+
155
+ // Create sheet
156
+ workbook.SheetNames.push(name);
157
+ const worksheet = XLSX.utils.aoa_to_sheet(dataArray, {sheet: name} as XLSX.AOA2SheetOpts);
158
+
159
+ // Apply merged cells from table colspan/rowspan
160
+ if (tableMerges && tableMerges.length > 0) {
161
+ worksheet['!merges'] = tableMerges;
162
+ }
163
+
164
+ // Apply format
165
+ if (sheetConf.formats) {
166
+ sheetConf.formats.forEach(f => {
167
+ if (!f) return;
168
+ const range = XLSX.utils.decode_range(f.range);
169
+ for (let R = range.s.r; R <= range.e.r; ++R) {
170
+ for (let C = range.s.c; C <= range.e.c; ++C) {
171
+ const cell = worksheet[XLSX.utils.encode_cell({r: R, c: C})];
172
+ if (cell && utils.hasContent(cell.v) && f.format) {
173
+ // type
174
+ cell.t = f.format.type;
175
+
176
+ // type fix
177
+ if (f.format.type == CellTypes.BOOLEAN) {
178
+ const v = cell.v.toString().toLowerCase();
179
+ if (v == 'true' || v == '1') cell.v = true;
180
+ if (v == 'false' || v == '0') cell.v = false;
181
+ }
182
+ // pattern
183
+ if (f.format.pattern) {
184
+ cell.z = f.format.pattern;
185
+ }
186
+ }
187
+ }
188
+ }
189
+ });
190
+ }
191
+
192
+ workbook.Sheets[name] = worksheet;
193
+ workbook.Views.push({RTL: options.rtl || sheetConf.rtl || false});
194
+ });
195
+
196
+ const wbOut:string = XLSX.write(workbook, {bookType: options.format, bookSST:true, type: 'binary', compression: true});
197
+ try {
198
+ const blob = new Blob([utils.string2ArrayBuffer(wbOut)], { type: "application/octet-stream" });
199
+ const filename = (options.filename || 'download') + '.' + options.format;
200
+ // Support for IE.
201
+ if (window.navigator.msSaveBlob) {
202
+ window.navigator.msSaveBlob(blob, filename);
203
+ return false;
204
+ }
205
+ if (options.anchor) {
206
+ const anchor = utils.getAnchor(options.anchor);
207
+ anchor.href = window.URL.createObjectURL(blob);
208
+ anchor.download = filename;
209
+ } else if (options.openAsDownload) {
210
+ const a = document.createElement("a");
211
+ a.href = URL.createObjectURL(blob);
212
+ a.download = filename;
213
+ document.body.appendChild(a);
214
+ a.click();
215
+ document.body.removeChild(a);
216
+ } else {
217
+ throw new Error('Options should specify an anchor or openAsDownload=true.')
218
+ }
219
+
220
+ } catch(e) {
221
+ throw new Error('Error converting to '+ options.format + '. ' + e);
222
+ }
223
+ return wbOut;
224
+
225
+ };
226
+
227
+ return {
228
+ version: function(): string {
229
+ return version;
230
+ },
231
+ excel: function(anchor:(HTMLAnchorElement|string), table:HTMLTableElement, name:string) {
232
+ table = utils.getTable(table);
233
+ anchor = utils.getAnchor(anchor);
234
+ const ctx = {worksheet: name || 'Worksheet', table: table.innerHTML};
235
+ const b64 = utils.base64(utils.format(utils.templates.excel, ctx));
236
+ return utils.createDownloadLink(anchor, b64, 'application/vnd.ms-excel','export.xls');
237
+ },
238
+ csv: function(anchor:(HTMLAnchorElement|string), table:HTMLTableElement, delimiter?:string, newLine?:string) {
239
+ let csvDelimiter = ",";
240
+ let csvNewLine = "\r\n";
241
+
242
+ if (delimiter !== undefined && delimiter) {
243
+ csvDelimiter = delimiter;
244
+ }
245
+ if (newLine !== undefined && newLine) {
246
+ csvNewLine = newLine;
247
+ }
248
+
249
+ table = utils.getTable(table);
250
+ anchor = utils.getAnchor(anchor);
251
+ const csvData = "\uFEFF" + utils.tableToCSV(table, csvDelimiter, csvNewLine);
252
+ const b64 = utils.base64(csvData);
253
+ return utils.createDownloadLink(anchor, b64, 'application/csv', 'export.csv');
254
+ },
255
+ convert: function(options:ConvertOptions, sheets:SheetOptions[]) {
256
+ return convert(options, sheets);
257
+ },
258
+ formats: PredefinedFormat,
259
+ cellTypes: CellTypes,
260
+ cellPatterns: CellPatterns,
261
+ };
262
+ }();
263
+
264
+ export default ExcellentExport;