1
- import { utils as XlsxUtils , writeFile } from 'xlsx/xlsx.js' ;
1
+ import { utils as XlsxUtils , writeFile } from 'xlsx/xlsx.js' ;
2
2
import { saveAs } from 'file-saver' ;
3
3
4
4
/**
@@ -120,6 +120,7 @@ export function createWorkbookFromJSON(jsonData) {
120
120
return workbook ;
121
121
}
122
122
123
+ /*
123
124
function writeWorkbook(workbook, baseName, ext, opt = {}) {
124
125
if (ext === 'xlsx' || ext === 'xls') {
125
126
// can support multiple sheets in one file
@@ -144,122 +145,141 @@ function writeWorkbook(workbook, baseName, ext, opt = {}) {
144
145
});
145
146
}
146
147
}
148
+ */
147
149
148
150
/**
149
151
* Download matrix to file.
150
152
* Note that BOM and UTF-8 can create problems on some systems when importing
151
153
* file. See "Supported Output Formats" and "UTF-16 Unicode Text" sections of
152
- * https://reactian.com/sheetjs-community-edition-spreadsheet-data-toolkit/
153
154
* and https://github.com/SheetJS/sheetjs
154
155
* Solution at bottom of: https://github.com/SheetJS/sheetjs/issues/943
155
156
* The "Comma Separated Values" format is actually UTF-8 with BOM prefix.
157
+ * A “U+” designation refers to a character, and in this case that would be
158
+ * U+FEFF; the start of the file is the three-byte sequence EF BB BF which is
159
+ * how U+FEFF is represented in UTF-8.
156
160
* @param {Workbook } workbook workboox to download.
157
161
* @param {String } baseName Basename of downloaded file.
158
162
* @param {String } ext Extension of downloaded file.
159
163
*/
160
164
export function exportWorkbook ( workbook , baseName , ext ) {
161
- switch ( ext ) {
162
- case 'xlsx' :
163
- case 'xls' :
164
- writeWorkbook ( workbook , baseName , ext ) ;
165
- break ;
166
- case 'csv' :
167
- processAndSave (
168
- workbook ,
169
- baseName ,
170
- 'csv' ,
171
- ',' ,
172
- 'text/plain;charset=UTF-8'
173
- ) ;
174
- break ;
175
-
176
- case 'csv (UTF-16)' :
177
- processAndSave (
178
- workbook ,
179
- baseName ,
180
- 'csv' ,
181
- ',' ,
182
- 'text/plain;charset=UTF-16LE'
183
- ) ;
184
- break ;
185
-
186
- case 'tsv' :
187
- processAndSave (
188
- workbook ,
189
- baseName ,
190
- 'tsv' ,
191
- '\t' ,
192
- 'text/plain;charset=UTF-8'
193
- ) ;
194
- break ;
195
-
196
- case 'tsv (UTF-16)' :
197
- processAndSave (
198
- workbook ,
199
- baseName ,
200
- 'tsv' ,
201
- '\t' ,
202
- 'text/plain;charset=UTF-16LE'
203
- ) ;
204
- break ;
205
-
206
- case 'csv (UTF-8, no BOM)' :
207
- processAndSave (
208
- workbook ,
209
- baseName ,
210
- 'csv' ,
211
- ',' ,
212
- 'text/plain;charset=UTF-8' ,
213
- false
214
- ) ;
215
- break ;
216
-
217
- case 'csv (ASCII)' :
218
- processAndSave (
219
- workbook ,
220
- baseName ,
221
- 'csv' ,
222
- ',' ,
223
- 'text/plain;charset=us-ascii' ,
224
- false
225
- ) ;
226
- break ;
227
- }
228
- }
229
165
230
- function processAndSave (
231
- workbook ,
232
- baseName ,
233
- ext ,
234
- delimiter ,
235
- mimeType ,
236
- includeBOM = true
237
- ) {
166
+ // Often just one sheet, but if multiple, then each gets file name + _ + template (class) name
238
167
const sheets = workbook . SheetNames ;
239
168
sheets . forEach ( ( sheetName ) => {
240
- let data = '' ;
241
-
242
169
const worksheet = workbook . Sheets [ sheetName ] ;
170
+ const fileName = `${ baseName } ${ sheets . length > 1 ? `_${ sheetName } ` : '' } .${ ext . split ( ' ' ) [ 0 ] } ` ;
171
+ var data = '' ;
172
+ switch ( ext ) {
173
+ case 'xlsx' :
174
+ case 'xls' :
175
+ // Note, mimeType always set to application/zip in these cases.
176
+ writeFile ( workbook , `${ baseName } .${ ext } ` ) ; //, opt
177
+ break ;
178
+
179
+ /* Notes:
180
+ See
181
+ - https://docs.sheetjs.com/docs/api/write-options/
182
+ - https://docs.sheetjs.com/docs/api/utilities/csv#csv-output
183
+ saveBlob() enables more accurate mimeTypes?
184
+ * writeFile(bookType: 'csv'...) output includes the UTF-8 byte order
185
+ * mark ("BOM").
186
+ * sheet_to_csv() will return JavaScript strings without the UTF-8 BOM.
187
+
188
+ */
189
+
190
+ /* Phasing this out. UTF-8 doesn't need a BOM
191
+ case 'csv': // UTF-8
192
+ // writeFile(workbook, fileName, {bookType: 'csv', FS: ','});
193
+ data = XlsxUtils.sheet_to_csv(worksheet, {FS: ','});
194
+ data = '\uFEFF' + data; //BOM
195
+ saveBlob(data, fileName, 'text/plain;charset=UTF-8');
196
+ break;
197
+ */
198
+
199
+ /* This case won't work until we convert data to UTF-16
200
+ case 'csv (UTF-16)':
201
+ //writeFile(workbook, fileName, {bookType: 'txt', FS: ','});
202
+ data = XlsxUtils.sheet_to_csv(worksheet, {FS: ','});
203
+ data = '\uFEFF' + data; //BOM
204
+ saveBlob(data, fileName, 'text/plain;charset=UTF-16LE');
205
+ break;
206
+ */
207
+
208
+ case 'csv' :
209
+ case 'csv (UTF-8, no BOM)' :
210
+ data = XlsxUtils . sheet_to_csv ( worksheet , { FS : ',' } ) ;
211
+ saveBlob ( data , fileName , 'text/plain;charset=UTF-8' ) ;
212
+ break ;
213
+
214
+ /* This case won't work until we convert data to ASCII
215
+ case 'csv (ASCII)': // no BOM
216
+ data = XlsxUtils.sheet_to_csv(worksheet, {FS: ','});
217
+ saveBlob(data, fileName, 'text/plain;charset=us-ascii');
218
+ break;
219
+ */
220
+
221
+ /*
222
+ * https://stackoverflow.com/questions/8336355/what-exactly-is-unicode-codepage-1200
223
+ * sheet_to_txt(): sheetjs notes: "If encoding support is available, the
224
+ * output will be encoded in CP1200 and the UTF-16 BOM will be added. If
225
+ * encoding support is not available, the output will be encoded as a
226
+ * standard string." In DH tests it seems "encoding support" is not
227
+ * available, and resulting file is UTF-8 +BOM anyways.
228
+ */
229
+ case 'tsv' : // UTF-8 BOM version
230
+ // SheetJS note: For compatibility with Excel, writeFile() csv output
231
+ // will always include the UTF-8 byte order mark ("BOM").
232
+ //writeFile(workbook, fileName, {bookType: 'csv', FS: '\t'});
233
+ data = XlsxUtils . sheet_to_csv ( worksheet , { FS : '\t' } ) ;
234
+ //data = '\uFEFF' + data; //BOM
235
+ saveBlob ( data , fileName , 'text/plain;charset=UTF-8' ) ;
236
+ break ;
237
+
238
+ /* Not working, produces hexidecimal file - is charset="UTF-16LE" recognized?
239
+ * See Table 2-4: unicode.org/versions/Unicode6.0.0/ch02.pdf"
240
+ * UTF-16 little endian, aka code page 1200, is not permitted to have a BOM,
241
+ * according to the Unicode standard.
242
+ * DATA NEEDS TO BE CONVERTED TO UTF-16
243
+ *
244
+ case 'tsv (UTF-16)': // no BOM
245
+ // See: https://localizely.com/character-encodings/utf16le/
246
+ //writeFile(workbook, fileName, {bookType: 'tsv', FS: '\t'});
247
+ data = XlsxUtils.sheet_to_txt(worksheet, {FS: '\t'});
248
+ saveBlob(data, fileName, 'text/plain;charset=UTF-16LE');
249
+ break;
250
+ */
251
+ }
252
+ } )
253
+ } ;
254
+
255
+ // Saves workbook which may have multiple sheets into one or more files.
256
+ // ext: csv, csv (UTF-16), tsv, tsv (UTF-16)
257
+ // ext no BOM: csv (UTF-8, no BOM), csv (ASCII)
258
+ // This script can enhance file type with mimeType - but is that something sheetJS can't do?
259
+ function saveBlob (
260
+ data ,
261
+ fileName ,
262
+ mimeType
263
+ ) {
264
+
265
+ /*
243
266
const sheetData = XlsxUtils.sheet_to_json(worksheet, { header: 1 });
244
267
245
268
const formattedData = sheetData
246
269
.map((row) => row.join(delimiter))
247
270
.join('\n');
248
271
data += formattedData + '\n';
249
272
273
+ // Insert BOM character.
250
274
if (includeBOM && mimeType.includes('UTF-8')) {
251
275
data = '\uFEFF' + data;
252
276
}
277
+ */
253
278
279
+ // Enhancing with mimeType
254
280
const blob = new Blob ( [ data ] , { type : mimeType } ) ;
255
- saveAs (
256
- blob ,
257
- `${ baseName } ${ sheets . length > 1 ? `_${ sheetName } ` : '' } .${
258
- ext . split ( ' ' ) [ 0 ]
259
- } `
260
- ) ;
261
- } ) ;
262
- }
281
+ saveAs ( blob , fileName ) ;
282
+ } ;
263
283
264
284
// TODO: refactor to export matrix
265
285
export function exportFile ( matrix , baseName , ext ) {
0 commit comments