| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- const fs = require('fs');
- const fastCsv = require('fast-csv');
- const customParseFormat = require('dayjs/plugin/customParseFormat');
- const utc = require('dayjs/plugin/utc');
- const dayjs = require('dayjs').extend(customParseFormat).extend(utc);
- const StreamBuf = require('../utils/stream-buf');
- const {
- fs: {exists},
- } = require('../utils/utils');
- /* eslint-disable quote-props */
- const SpecialValues = {
- true: true,
- false: false,
- '#N/A': {error: '#N/A'},
- '#REF!': {error: '#REF!'},
- '#NAME?': {error: '#NAME?'},
- '#DIV/0!': {error: '#DIV/0!'},
- '#NULL!': {error: '#NULL!'},
- '#VALUE!': {error: '#VALUE!'},
- '#NUM!': {error: '#NUM!'},
- };
- /* eslint-ensable quote-props */
- class CSV {
- constructor(workbook) {
- this.workbook = workbook;
- this.worksheet = null;
- }
- async readFile(filename, options) {
- options = options || {};
- if (!(await exists(filename))) {
- throw new Error(`File not found: ${filename}`);
- }
- const stream = fs.createReadStream(filename);
- const worksheet = await this.read(stream, options);
- stream.close();
- return worksheet;
- }
- read(stream, options) {
- options = options || {};
- return new Promise((resolve, reject) => {
- const worksheet = this.workbook.addWorksheet(options.sheetName);
- const dateFormats = options.dateFormats || [
- 'YYYY-MM-DD[T]HH:mm:ssZ',
- 'YYYY-MM-DD[T]HH:mm:ss',
- 'MM-DD-YYYY',
- 'YYYY-MM-DD',
- ];
- const map =
- options.map ||
- function(datum) {
- if (datum === '') {
- return null;
- }
- const datumNumber = Number(datum);
- if (!Number.isNaN(datumNumber) && datumNumber !== Infinity) {
- return datumNumber;
- }
- const dt = dateFormats.reduce((matchingDate, currentDateFormat) => {
- if (matchingDate) {
- return matchingDate;
- }
- const dayjsObj = dayjs(datum, currentDateFormat, true);
- if (dayjsObj.isValid()) {
- return dayjsObj;
- }
- return null;
- }, null);
- if (dt) {
- return new Date(dt.valueOf());
- }
- const special = SpecialValues[datum];
- if (special !== undefined) {
- return special;
- }
- return datum;
- };
- const csvStream = fastCsv
- .parse(options.parserOptions)
- .on('data', data => {
- worksheet.addRow(data.map(map));
- })
- .on('end', () => {
- csvStream.emit('worksheet', worksheet);
- });
- csvStream.on('worksheet', resolve).on('error', reject);
- stream.pipe(csvStream);
- });
- }
- /**
- * @deprecated since version 4.0. You should use `CSV#read` instead. Please follow upgrade instruction: https://github.com/exceljs/exceljs/blob/master/UPGRADE-4.0.md
- */
- createInputStream() {
- throw new Error(
- '`CSV#createInputStream` is deprecated. You should use `CSV#read` instead. This method will be removed in version 5.0. Please follow upgrade instruction: https://github.com/exceljs/exceljs/blob/master/UPGRADE-4.0.md'
- );
- }
- write(stream, options) {
- return new Promise((resolve, reject) => {
- options = options || {};
- // const encoding = options.encoding || 'utf8';
- // const separator = options.separator || ',';
- // const quoteChar = options.quoteChar || '\'';
- const worksheet = this.workbook.getWorksheet(options.sheetName || options.sheetId);
- const csvStream = fastCsv.format(options.formatterOptions);
- stream.on('finish', () => {
- resolve();
- });
- csvStream.on('error', reject);
- csvStream.pipe(stream);
- const {dateFormat, dateUTC} = options;
- const map =
- options.map ||
- (value => {
- if (value) {
- if (value.text || value.hyperlink) {
- return value.hyperlink || value.text || '';
- }
- if (value.formula || value.result) {
- return value.result || '';
- }
- if (value instanceof Date) {
- if (dateFormat) {
- return dateUTC
- ? dayjs.utc(value).format(dateFormat)
- : dayjs(value).format(dateFormat);
- }
- return dateUTC ? dayjs.utc(value).format() : dayjs(value).format();
- }
- if (value.error) {
- return value.error;
- }
- if (typeof value === 'object') {
- return JSON.stringify(value);
- }
- }
- return value;
- });
- const includeEmptyRows = options.includeEmptyRows === undefined || options.includeEmptyRows;
- let lastRow = 1;
- if (worksheet) {
- worksheet.eachRow((row, rowNumber) => {
- if (includeEmptyRows) {
- while (lastRow++ < rowNumber - 1) {
- csvStream.write([]);
- }
- }
- const {values} = row;
- values.shift();
- csvStream.write(values.map(map));
- lastRow = rowNumber;
- });
- }
- csvStream.end();
- });
- }
- writeFile(filename, options) {
- options = options || {};
- const streamOptions = {
- encoding: options.encoding || 'utf8',
- };
- const stream = fs.createWriteStream(filename, streamOptions);
- return this.write(stream, options);
- }
- async writeBuffer(options) {
- const stream = new StreamBuf();
- await this.write(stream, options);
- return stream.read();
- }
- }
- module.exports = CSV;
|