UNPKG

datainout

Version:

Import and reports data

588 lines (578 loc) 22.6 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw Error('Dynamic require of "' + x + '" is not supported'); }); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/helpers/parse-type.ts var TypeParser = class { constructor(opts) { var _a; this.dateFormat = (_a = opts == null ? void 0 : opts.dateFormat) != null ? _a : "DD-MM-YYYY"; } boolean(val) { return val === "true"; } date(val) { return new Date(val); } number(val) { return +val; } object(val) { return JSON.parse(val); } string(val) { return val + ""; } }; // src/helpers/excel.helper.ts import * as exceljs from "exceljs"; var SYNTAX = { VARIABLE_TABLE_SYNTAX: "$$", VARIABLE_SYNTAX: "$", INDEX_COLUMN_TABLE_SYNTAX: "$$**", END_TABLE_SYNYAX: "$$br" }; var DEFAULT_BEGIN_TABLE = -1; var DEFAULT_END_TABLE = -1; var DEFAULT_COLUMN_INDEX = 1; var ReaderExceljsHelper = class _ReaderExceljsHelper { constructor(opts) { this.isSampleExcel = true; this.isStop = false; var _a; this.onCell = opts == null ? void 0 : opts.onCell; this.onRow = opts == null ? void 0 : opts.onRow; this.onSheet = opts == null ? void 0 : opts.onSheet; this.isSampleExcel = (_a = opts == null ? void 0 : opts.isSampleExcel) != null ? _a : true; this.templateManager = opts.templateManager; } load(arg) { return __async(this, null, function* () { const workBook = new exceljs.Workbook(); if (arg instanceof Buffer) yield workBook.xlsx.load(arg); else yield workBook.xlsx.readFile(arg); for (let i = 0; !this.isStop && i < workBook.worksheets.length; i++) { const workSheet = workBook.getWorksheet(i + 1); if (workSheet) yield this.eachSheet(workSheet, i + 1); } }); } eachSheet(sheet, sheetIndex) { return __async(this, null, function* () { var _a, _b, _c, _d; this.templateManager.SheetIndex = sheetIndex - 1; const sheetDesc = this.templateManager.SheetTemplate; const trackingRows = []; let columnIndex = DEFAULT_COLUMN_INDEX; let beginTable = DEFAULT_BEGIN_TABLE; let endTable = DEFAULT_END_TABLE; for (let i = 1; !this.isStop && i <= sheet.rowCount; i++) { const row = sheet.getRow(i); this.templateManager.defineActualTableStartRow(_ReaderExceljsHelper.beginTableAt(row, sheetDesc, this.isSampleExcel)); this.templateManager.defineActualTableStartRow(_ReaderExceljsHelper.endTableAt(row, sheetDesc, this.isSampleExcel)); columnIndex = (_a = _ReaderExceljsHelper.columnTableIndex(row, sheetDesc, this.isSampleExcel)) != null ? _a : columnIndex; endTable = (_b = this.templateManager.ActualTableEndRow) != null ? _b : DEFAULT_END_TABLE; beginTable = (_c = this.templateManager.ActualTableStartRow) != null ? _c : DEFAULT_BEGIN_TABLE; const section = _ReaderExceljsHelper.getSection(row, beginTable, endTable); const cells = []; for (let j = 0; j < row.cellCount; j++) { if (!((_d = row.getCell(j + 1)) == null ? void 0 : _d.value)) continue; const cell = this.convertCell(row.getCell(j + 1), section, beginTable, endTable); cells.push(cell); if (this.onCell) yield this.onCell(cell); } if (this.onRow) { const rowDataHelper = this.convertRow(row, section, cells); if (i === 1) trackingRows.push(rowDataHelper); if (i === sheet.rowCount) trackingRows.push(rowDataHelper); yield this.onRow(rowDataHelper); } } if (this.onSheet) yield this.onSheet({ beginTableAt: beginTable != null ? beginTable : 1, columnIndex, endTableAt: endTable, sheetIndex, name: sheet.name, detail: sheet, rowCount: sheet.rowCount, lastestRow: trackingRows[1], firstRow: trackingRows[0] }); }); } convertCell(cell, section, beginTableAt, endTableAt) { var _a; const isVariable = _ReaderExceljsHelper.isVariable(cell.value); return { address: _ReaderExceljsHelper.getAddress(cell.address, section, isVariable), detail: cell, isVariable, rowIndex: +cell.fullAddress.row, section, label: _ReaderExceljsHelper.getLabel(cell.value + "", isVariable), variableValue: isVariable ? _ReaderExceljsHelper.getVariableValue(cell) : void 0, beginTableAt, endTableAt, formula: (_a = cell.formula) != null ? _a : void 0 }; } convertRow(row, section, cells) { var _a, _b, _c, _d; return { detail: row, rowIndex: row.number, section, cells, beginTableAt: (_b = (_a = cells[0]) == null ? void 0 : _a.beginTableAt) != null ? _b : DEFAULT_BEGIN_TABLE, endTableAt: (_d = (_c = cells[0]) == null ? void 0 : _c.endTableAt) != null ? _d : DEFAULT_END_TABLE }; } static getSection(row, beginTable, endTable) { const rowIndex = typeof row === "number" ? row : row.number; let section = "header"; if (beginTable === DEFAULT_BEGIN_TABLE) section = "header"; else if (beginTable !== DEFAULT_BEGIN_TABLE && rowIndex < beginTable) section = "header"; else if (rowIndex > endTable && endTable !== DEFAULT_END_TABLE) section = "footer"; else if (rowIndex > beginTable) section = "table"; return section; } /** Get begin table at by row */ static beginTableAt(row, sheetOpts, isSampleExcel = true) { if (isSampleExcel) for (let i = 0; i < row.cellCount; i++) { const cellValue = row.getCell(i + 1).value; if (cellValue === void 0 || typeof cellValue !== "string") continue; if (cellValue.includes(SYNTAX.INDEX_COLUMN_TABLE_SYNTAX)) return row.number; if (cellValue.includes(SYNTAX.VARIABLE_TABLE_SYNTAX)) return row.number - 1; } else if (sheetOpts) return sheetOpts.beginTableAt; return void 0; } /** Get end table at by row */ static endTableAt(row, sheetOpts, isSampleExcel = true) { var _a; if (isSampleExcel) for (let i = 0; i < row.cellCount; i++) { const cellValue = row.getCell(i + 1).value; if (cellValue === void 0 || typeof cellValue !== "string") continue; if (cellValue.includes(SYNTAX.END_TABLE_SYNYAX)) return row.number - 1; if (!cellValue.includes(SYNTAX.INDEX_COLUMN_TABLE_SYNTAX) && cellValue.includes(SYNTAX.VARIABLE_TABLE_SYNTAX)) return row.number; } else if (sheetOpts) { const cellvalues = (_a = row == null ? void 0 : row.values) != null ? _a : []; if (cellvalues && !cellvalues[sheetOpts.keyTableAt] && row.number > sheetOpts.beginTableAt) return row.number - 1; } return void 0; } static isNullableRow(row) { var _a, _b; return (_b = (_a = row == null ? void 0 : row.values) == null ? void 0 : _a.reduce((acc, val) => acc && !!!val, true)) != null ? _b : false; } /** Get key of table by row */ static columnTableIndex(row, sheetOpts, isSampleExcel = true) { if (isSampleExcel) for (let i = 0; i < row.cellCount; i++) { const cellValue = row.getCell(i + 1).value; if (cellValue === void 0 || typeof cellValue !== "string") continue; if ((cellValue + "").includes(SYNTAX.INDEX_COLUMN_TABLE_SYNTAX)) return row.number + 1; } else if (sheetOpts) return sheetOpts.keyTableAt; return void 0; } static isVariable(cellValue) { cellValue = cellValue + ""; if (cellValue.includes(SYNTAX.INDEX_COLUMN_TABLE_SYNTAX)) return false; return cellValue.includes(SYNTAX.VARIABLE_SYNTAX); } static getLabel(label, isVariable) { if (isVariable) return void 0; if (label.includes(SYNTAX.INDEX_COLUMN_TABLE_SYNTAX)) return label.split("->").pop(); return label; } static getAddress(address, section, isVariable) { return !isVariable ? address : section !== "header" ? address.split(/\d+/)[0] : address; } static getVariableValue(cell) { const cellValue = (cell.value + "").replace("$$", "$"); let fieldName = ""; let type = "string"; fieldName = cellValue.split("$")[1]; if (fieldName.includes("->")) { const args = fieldName.split("->"); fieldName = args[0]; type = args[1].toLowerCase(); } return { fieldName, type }; } static splitAddress(address) { const col = address.split(/\d+/)[0]; const row = address.split(/[a-zA-Z]/)[1]; return { col, row }; } }; // src/common/core/error-message-default.ts var ERROR_MESSAGE = { MESSAGE_REQUIRED_CELL: "must be required", MESSAGE_INVALID_CELL: "validate failed" }; // src/common/error/ValidateError.ts var ValidateImportError = class extends Error { constructor(opts) { super(opts.message); this.address = opts == null ? void 0 : opts.address; this.keyField = opts.keyField; this.value = opts.value; } }; // src/helpers/validate-cell-importer.ts function validateCellImport(value, cellDes, address, keyField) { const isNullValue = value === void 0 || value === null; const ValidateImportErrorOpts = { keyField, address, value }; if (isNullValue && cellDes.required === true) { const message = `${ERROR_MESSAGE.MESSAGE_REQUIRED_CELL}`; throw new ValidateImportError(__spreadProps(__spreadValues({}, ValidateImportErrorOpts), { message })); } if (cellDes.validate) { const result = cellDes.validate(value); if (result instanceof Error) throw result; const { isValid, message } = result; if (isValid) { const defaultMessage = `${ERROR_MESSAGE.MESSAGE_INVALID_CELL}`; throw new ValidateImportError(__spreadProps(__spreadValues({}, ValidateImportErrorOpts), { message: message != null ? message : defaultMessage })); } } } // src/helpers/get-file-extension.ts function getFileExtension(path) { const fileName = path.replace("\\", "/").split("/").pop(); if (!fileName) throw new Error(`Path [${path}] invalid`); const extension = fileName.split(".").pop(); if (!extension) throw new Error(`Path [${path}] invalid`); if (extension === "js") return "js"; else if (extension === "ts") return "ts"; else throw new Error(`Path [${path}] invalid`); } // src/helpers/sort-by-address.ts function reverseString(str) { return str.split("").reverse().join(""); } function sortByAddress(arr, mode = "ASC") { return arr.sort((a, b) => { if (!a.address) return 1; if (!b.address) return -1; if (a.address === b.address) return 0; const result = reverseString(a.address).localeCompare(reverseString(b.address)); return result * (mode === "DESC" ? -1 : 1); }); } // src/common/core/Template.ts var ExcelTemplateManager = class { constructor(templatePath) { this.sheets = []; this.currentSheetIndex = 0; this.groupCells = {}; this.isNullTemplate = false; this.isNullTemplate = !templatePath; this.sheets = templatePath ? this.getTemplate(templatePath) : []; } get ActualTableStartRow() { return this.actualTableStartRow; } get ActualTableEndRow() { return this.actualTableEndRow; } defineActualTableStartRow(actualTableStartRow) { if (!actualTableStartRow || actualTableStartRow <= 0) return; if (this.ActualTableStartRow) return; this.actualTableStartRow = actualTableStartRow; } defineActualTableEndRow(actualTableEndRow) { if (!actualTableEndRow || actualTableEndRow <= 0) return; if (this.ActualTableEndRow) return; this.actualTableEndRow = actualTableEndRow; } set SheetIndex(sheetIndex) { if (sheetIndex < 0) return; this.currentSheetIndex = sheetIndex; this.groupCells = this.formatSheet(); } get SheetInformation() { return this.SheetTemplate; } get SheetTemplate() { return this.sheets[this.currentSheetIndex]; } get Sheets() { return this.sheets; } get GroupCells() { return this.groupCells; } get(arg) { if (this.isNullTemplate) throw new Error("Template is null. Please check template path"); let index = 0; if (typeof arg === "string") index = this.findIndexByKeyName(arg); else if (typeof arg === "number") index = arg; return this.SheetTemplate.cells[index]; } add(cell) { if (this.isNullTemplate) throw new Error("Template is null. Please check template path"); if (!Array.isArray(cell)) cell = [cell]; this.SheetTemplate.cells.push(...cell); } update(key, cell) { if (this.isNullTemplate) throw new Error("Template is null. Please check template path"); let index = 0; if (typeof key === "string") index = this.findIndexByKeyName(key); else if (typeof key === "number") index = key; this.SheetTemplate.cells[index] = cell; } remove(key) { if (this.isNullTemplate) throw new Error("Template is null. Please check template path"); let index = 0; if (typeof key === "string") index = this.findIndexByKeyName(key); else if (typeof key === "number") index = key; this.SheetTemplate.cells.splice(index, 1); } findIndexByKeyName(key) { const index = this.SheetTemplate.cells.findIndex((e) => e.keyName === key); if (index < 0) throw new Error("Not found template with key: " + key); return index; } getTemplate(templatePath) { const template = getFileExtension(templatePath) === "js" ? __require(templatePath) : __require(templatePath).default; return template.sheets; } formatSheet() { var _a; const defaultGroup = {}; if (this.isNullTemplate) return defaultGroup; const excel = (_a = this.SheetTemplate) == null ? void 0 : _a.cells.reduce((acc, cell) => { var _a2; if (!acc[cell.section]) acc[cell.section] = [cell]; else (_a2 = acc[cell.section]) == null ? void 0 : _a2.push(cell); return acc; }, {}); const keys = Object.keys(excel); for (let i = 0; i < keys.length; i++) excel[keys[i]] = sortByAddress(excel[keys[i]]); return excel; } }; // src/helpers/convert-row-to-table-data.ts var ConvertorRows2TableData = class { constructor(opts) { this.container = { header: {}, footer: {}, table: [] }; this.beginTable = DEFAULT_BEGIN_TABLE; this.endTable = DEFAULT_END_TABLE; this.tableCols = []; var _a, _b, _c; this.chunkSize = (_a = opts == null ? void 0 : opts.chunkSize) != null ? _a : 10; this.typeParser = (_b = opts == null ? void 0 : opts.typeParser) != null ? _b : new TypeParser(); this.templateManager = (_c = opts == null ? void 0 : opts.templateManager) != null ? _c : new ExcelTemplateManager(); } push(arg, template) { var _a, _b, _c, _d, _e; if (this.tableCols.length === 0) this.tableCols = this.templateManager.GroupCells.table.map((e) => e.keyName); const addresses = {}; const groupValues = {}; if (arg === null) return { isTrigger: true, triggerSection: (_a = this.section) != null ? _a : "header" }; if (ReaderExceljsHelper.isNullableRow((_b = arg == null ? void 0 : arg.detail) != null ? _b : arg)) return { isTrigger: false, triggerSection: (_c = this.section) != null ? _c : "header", errors: [], hasError: false }; const { endTable, row, section } = this.getRowInformation(arg, template); const isTrigger = this.isTrigger(section); const triggerSection = this.triggerSection(section); if (!row) return { isTrigger: false, triggerSection: (_d = this.section) != null ? _d : "header", errors: [], hasError: false }; for (let i = 0; i < row.cellCount; i++) { const cell = row.getCell(i + 1); if ((cell == null ? void 0 : cell.value) === void 0) continue; const keyName = this.tableCols[i]; groupValues[keyName] = cell.value; addresses[keyName] = cell.address; } if (section === "table" && Object.keys(groupValues).length > 0) (_e = this.container.table) == null ? void 0 : _e.push(groupValues); else if (Object.keys(groupValues).length > 0) this.container[section] = __spreadValues(__spreadValues({}, this.container[section]), groupValues); const { errors, hasError } = this.triggerGroupData(triggerSection, section, template, addresses, row); this.section = section; return { isTrigger, triggerSection, errors, hasError }; } pushBySection(section, template, rowIndex) { var _a; const result = this.formatValue( template.cells.filter((e) => e.section === section), {}, this.typeParser, rowIndex ); if (section === "table") (_a = this.container.table) == null ? void 0 : _a.push(result.groupValues); else this.container[section] = result.groupValues; return { isTrigger: true, triggerSection: section, errors: result.errors, hasError: result.errors.length !== 0 }; } pop(section) { const result = this.container[section]; if (section === "table") this.container.table = []; else this.container[section] = {}; return result; } isTrigger(section) { var _a, _b; if (this.section) { if (section !== this.section) return true; const chunkSize = (_b = (_a = this.container) == null ? void 0 : _a.table) == null ? void 0 : _b.length; if (this.chunkSize - 1 === chunkSize && section === this.section && section === "table") return true; } return false; } triggerSection(section) { let triggerSection = section; if (!this.isTrigger(section)) return section; if (this.section && this.section !== section) { if (section === "header") triggerSection = "header"; if (section === "table") triggerSection = "header"; if (section === "footer") triggerSection = "table"; } if (this.section && section === this.section && this.section === "table") triggerSection = "table"; return triggerSection; } getRowInformation(arg, template) { var _a, _b; let row, section = "header"; if (arg.detail) { row = arg.detail; section = arg.section; } else row = arg; const beginTable = (_a = this.templateManager.ActualTableStartRow) != null ? _a : DEFAULT_BEGIN_TABLE; const endTable = (_b = this.templateManager.ActualTableEndRow) != null ? _b : DEFAULT_END_TABLE; if (!arg.detail) section = ReaderExceljsHelper.getSection(row, beginTable, endTable); return { row, section, beginTable, endTable }; } triggerGroupData(triggerSection, section, template, addresses, row) { var _a, _b; const errors = []; if (triggerSection !== section) { const resultFormat = this.formatValue( template.cells.filter((e) => e.section === triggerSection), this.container[triggerSection], this.typeParser, row.number, addresses ); errors.push(...resultFormat.errors); this.container[triggerSection] = resultFormat.groupValues; } if (section === "table") { const groupValue = (_a = this.container.table) == null ? void 0 : _a.pop(); const resultFormat = this.formatValue( template.cells.filter((e) => e.section === section), groupValue, this.typeParser, row.number, addresses ); errors.push(...resultFormat.errors); (_b = this.container.table) == null ? void 0 : _b.push(groupValue); } const hasError = errors.length !== 0; return { hasError, errors }; } formatValue(formattedCellImport, groupValues, typeParser, rowIndex, addresses) { formattedCellImport = formattedCellImport.sort((a, b) => { const aType = a.type === "virtual" ? 2 : 1; const bType = b.type === "virtual" ? 2 : 1; return bType - aType; }); const row = __spreadValues({}, groupValues); const errors = []; formattedCellImport.forEach((cell) => { var _a, _b; let value = groupValues[cell.keyName]; if (cell.setValue) value = cell.setValue(value, row); if (cell.type && cell.type !== "virtual") value = typeParser[cell.type](value); let address = (_a = addresses == null ? void 0 : addresses[cell.keyName]) != null ? _a : void 0; if (!address) { if (cell.section === "header") address = cell.address; else { const { col } = ReaderExceljsHelper.splitAddress((_b = cell.address) != null ? _b : ""); address = `${col}${rowIndex}`; } } try { validateCellImport(value, cell, address, cell.keyName); groupValues[cell.keyName] = value; } catch (error) { errors.push(error); } }); return { groupValues, errors }; } compareByAddress(cellDes, section, cell, rowNumber, endTableAt) { var _a, _b; if (cellDes.section === section) { if (cellDes.section === "header") return cellDes.address === cell.address; else if (cellDes.section === "table") return cell.address === `${cellDes.address}${rowNumber}`; else { return rowNumber === endTableAt + ((_b = (_a = cellDes == null ? void 0 : cellDes.fullAddress) == null ? void 0 : _a.row) != null ? _b : 0); } } return false; } }; export { ConvertorRows2TableData };