UNPKG

@sd-angular/core

Version:

Sd Angular Core Lib

505 lines (500 loc) 24.1 kB
import { FIREBASE_CONFIG } from '@sd-angular/core/common'; import { __classPrivateFieldGet, __awaiter } from 'tslib'; import { ɵɵdefineInjectable, ɵɵinject, Injectable, Inject, Optional } from '@angular/core'; import { SdApiService } from '@sd-angular/core/api'; import { v4 } from 'uuid'; import hash from 'object-hash'; import { ExportToCsv } from 'export-to-csv'; import { Workbook } from 'exceljs'; import { SdNotifyService } from '@sd-angular/core/notify'; const API = { uploadTemplate: '/excel/uploadTemplate', generateUploadTemplate: '/excel/generateUploadTemplate', filesInFolder: '/excel/filesInFolder', removeFile: '/excel/remove', sdExportByTemplate: '/excel/sd-export-by-template', sdMergePDF: '/excel/sd-merge-pdf', }; var _fieldStyle, _titleColor, _titleFgColor, _titleStyle, _requiredStyle, _descriptionStyle, _cellStyle, _directory; class SdExportService { constructor(apiService, notifyService, firebaseConfiguration) { this.apiService = apiService; this.notifyService = notifyService; this.firebaseConfiguration = firebaseConfiguration; _fieldStyle.set(this, { border: { bottom: { style: 'thin' }, left: { style: 'thin' }, right: { style: 'thin' }, }, alignment: { vertical: 'middle', horizontal: 'center', wrapText: true, }, font: { bold: true, size: 11, color: { argb: '000000' }, }, fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FAFAFA', }, }, }); _titleColor.set(this, 'FFFFFF'); _titleFgColor.set(this, '143180'); _titleStyle.set(this, { border: { bottom: { style: 'thin' }, left: { style: 'thin' }, right: { style: 'thin' }, }, alignment: { vertical: 'middle', horizontal: 'center', wrapText: true, }, font: { bold: true, size: 11, color: { argb: __classPrivateFieldGet(this, _titleColor) }, }, fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: __classPrivateFieldGet(this, _titleFgColor), }, }, }); _requiredStyle.set(this, { border: { bottom: { style: 'thin' }, left: { style: 'thin' }, right: { style: 'thin' }, }, alignment: { vertical: 'middle', horizontal: 'center', wrapText: true, }, font: { italic: true, size: 11, color: { argb: 'FFFFFF' }, }, fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF1744', }, }, }); _descriptionStyle.set(this, { border: { bottom: { style: 'thin' }, left: { style: 'thin' }, right: { style: 'thin' }, }, alignment: { wrapText: true, }, font: { italic: true, size: 9, color: { argb: '000000' }, }, fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'CFD8DC', }, }, }); _cellStyle.set(this, { alignment: { vertical: 'middle', wrapText: true, }, }); _directory.set(this, (key, group) => { let hashedFolder = hash({ folder: this.folder, userFolder: this.userFolder, }); if (!group) { return `dir1=${this.folder}&dir2=U-${hashedFolder}&dir3=${key || ''}`; } hashedFolder = hash({ folder: this.folder, group, }); return `dir1=${this.folder}&dir2=G-${hashedFolder}&dir3=${key || ''}`; }); this.generateTemplate = (template) => __awaiter(this, void 0, void 0, function* () { const { fileName, columns, sheets } = template; if (!Array.isArray(columns)) { throw new Error('Excel template columns must be an array'); } for (const [idx, column] of columns.entries()) { if (!column.field) { throw new Error(`Column ${idx + 1}: Field is required`); } if (!column.title) { throw new Error(`Column ${idx + 1}: Title is required`); } } const hasDescription = columns.some(column => column.description); const workbook = new Workbook(); //await XlsxPopulate.fromBlankAsync(); // Đọc file sau khi đã download const firstSheet = workbook.addWorksheet('template'); // Lấy ra sheet đầu tiên columns.forEach((column, index) => { var _a, _b, _c, _d, _e, _f; const { required, fill, fontColor } = column; const cellField = firstSheet.getCell(1, index + 1); const cellTitle = firstSheet.getCell(2, index + 1); const cellDescription = firstSheet.getCell(3, index + 1); let width = 120; if (column.width && column.width.endsWith('px')) { width = +column.width.replace('px', ''); } firstSheet.getColumn(index + 1).width = width / 7 || 20; cellField.style = __classPrivateFieldGet(this, _fieldStyle); if (required) { cellField.style = __classPrivateFieldGet(this, _requiredStyle); } else { cellField.style = __classPrivateFieldGet(this, _fieldStyle); } cellTitle.style = Object.assign(Object.assign({}, __classPrivateFieldGet(this, _titleStyle)), { font: Object.assign(Object.assign({}, (_a = __classPrivateFieldGet(this, _titleStyle)) === null || _a === void 0 ? void 0 : _a.font), { color: Object.assign(Object.assign({}, (_c = (_b = __classPrivateFieldGet(this, _titleStyle)) === null || _b === void 0 ? void 0 : _b.font) === null || _c === void 0 ? void 0 : _c.color), { argb: fontColor || ((_f = (_e = (_d = __classPrivateFieldGet(this, _titleStyle)) === null || _d === void 0 ? void 0 : _d.font) === null || _e === void 0 ? void 0 : _e.color) === null || _f === void 0 ? void 0 : _f.argb) }) }), fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: fill || __classPrivateFieldGet(this, _titleFgColor), }, } }); cellField.value = column.field; cellTitle.value = column.title; if (hasDescription) { cellDescription.style = __classPrivateFieldGet(this, _descriptionStyle); cellDescription.value = column.description || ''; } }); if (sheets === null || sheets === void 0 ? void 0 : sheets.length) { for (const sheet of sheets) { if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.fields)) { const newSheet = workbook.addWorksheet(sheet.name); sheet.fields.forEach((field, index) => { newSheet.getColumn(index + 1).width = 30; newSheet.getCell(1, index + 1).style = __classPrivateFieldGet(this, _titleStyle); newSheet.getCell(1, index + 1).value = field; }); sheet.items.forEach((item, idx1) => { sheet.fields.forEach((field, idx2) => { newSheet.getCell(2 + idx1, 1 + idx2).value = item[field]; newSheet.getCell(2 + idx1, 1 + idx2).style = __classPrivateFieldGet(this, _cellStyle); }); }); } } } const file = yield workbook.xlsx.writeBuffer(); SdUtility.downloadBlob(new Blob([file], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }), fileName); }); this.uploadTemplate = (args) => __awaiter(this, void 0, void 0, function* () { const { key, group, validator } = args; const { uploadTemplate } = API; const url = `${this.functionUrl}${uploadTemplate}?${__classPrivateFieldGet(this, _directory).call(this, key, group)}`; const file = yield SdUtility.upload({ extensions: ['xlsx'], maxSizeInMb: 0.1, validator, }); if (file) { const { filePath, fileName } = yield this.apiService.upload(url, file).catch((err) => { this.notifyService.notify.warning(err === null || err === void 0 ? void 0 : err.message); throw err; }); return { filePath, fileName, }; } return null; }); this.generateUploadTemplate = (args) => __awaiter(this, void 0, void 0, function* () { const { key, template, group } = args; const { generateUploadTemplate } = API; const url = `${this.functionUrl}${generateUploadTemplate}?${__classPrivateFieldGet(this, _directory).call(this, key, group)}`; const { filePath, fileName } = yield this.apiService.post(url, template); return { filePath, fileName }; }); this.removeFile = (args) => __awaiter(this, void 0, void 0, function* () { const { key, group, fileName } = args; const { removeFile } = API; const url = `${this.functionUrl}${removeFile}?${__classPrivateFieldGet(this, _directory).call(this, key, group)}&name=${fileName}`; yield this.apiService.post(url); }); this.filesInFolder = (args) => __awaiter(this, void 0, void 0, function* () { var _a; const { key, group } = args; const { filesInFolder } = API; const url = `${this.functionUrl}${filesInFolder}?${__classPrivateFieldGet(this, _directory).call(this, key, group)}`; const res = yield this.apiService.get(url); return (((_a = res.files) === null || _a === void 0 ? void 0 : _a.map(e => ({ filePath: e.publicUrl, fileName: e.name, }))) || []); }); this.download = (filePath, fileName) => { const link = document.createElement('a'); link.download = `${fileName || v4()}.xlsx`; link.href = filePath; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; this.exportByTemplate = (args) => __awaiter(this, void 0, void 0, function* () { const { filePath, columns, items, fileName } = args; const { sdExportByTemplate } = API; const url = `${this.functionUrl}${sdExportByTemplate}`; const buffer = yield this.apiService.post(url, { filePath, columns, items, fileName, }, null, { responseType: 'arraybuffer', }); const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,' }); SdUtility.downloadBlob(blob, fileName); }); this.exportCSV = (option) => __awaiter(this, void 0, void 0, function* () { const { columns, items, fileName } = option; const headerCSV = {}; for (const column of columns) { headerCSV[column.field] = column.title; } const csvExporter = new ExportToCsv({ filename: `${fileName || 'CSV'}_${Date.toFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss')}`, fieldSeparator: ',', quoteStrings: '"', decimalSeparator: '.', showLabels: true, showTitle: false, title: fileName || 'CSV', useBom: true, }); csvExporter.generateCsv([headerCSV, ...items]); }); this.export = (option) => __awaiter(this, void 0, void 0, function* () { const { columns, items, fileName, sheets } = option; let hasDescription = false; for (const [idx, column] of columns.entries()) { if (!column.field) { throw new Error(`Column ${idx + 1}: Field is required`); } if (!column.title) { throw new Error(`Column ${idx + 1}: Title is required`); } if (column.description) { hasDescription = true; } } const workbook = new Workbook(); //await XlsxPopulate.fromBlankAsync(); // Đọc file sau khi đã download const firstSheet = workbook.addWorksheet('data'); // Lấy ra sheet đầu tiên columns.forEach((column, index) => { let width = 120; if (column.width && column.width.endsWith('px')) { width = +column.width.replace('px', ''); } firstSheet.getColumn(index + 1).width = width / 7 || 20; firstSheet.getCell(1, index + 1).style = __classPrivateFieldGet(this, _fieldStyle); if (column.required) { firstSheet.getCell(2, index + 1).style = __classPrivateFieldGet(this, _requiredStyle); } else { firstSheet.getCell(2, index + 1).style = __classPrivateFieldGet(this, _titleStyle); } firstSheet.getCell(1, index + 1).value = column.field; firstSheet.getCell(2, index + 1).value = column.title; if (hasDescription) { firstSheet.getCell(3, index + 1).style = __classPrivateFieldGet(this, _descriptionStyle); firstSheet.getCell(3, index + 1).value = column.description || ''; } }); if (sheets === null || sheets === void 0 ? void 0 : sheets.length) { for (const sheet of sheets) { if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.fields)) { const newSheet = workbook.addWorksheet(sheet.name); sheet.fields.forEach((field, index) => { newSheet.getColumn(index + 1).width = 30; newSheet.getCell(1, index + 1).style = __classPrivateFieldGet(this, _titleStyle); newSheet.getCell(1, index + 1).value = field; }); sheet.items.forEach((item, idx1) => { sheet.fields.forEach((field, idx2) => { newSheet.getCell(2 + idx1, 1 + idx2).value = item[field]; newSheet.getCell(2 + idx1, 1 + idx2).style = __classPrivateFieldGet(this, _cellStyle); }); }); } } } const fromRow = hasDescription ? 4 : 3; items.forEach((e, idx1) => { columns.forEach((column, idx2) => { if (typeof e[column.field] === 'number') { // Format mặc định với kiểu số firstSheet.getCell(fromRow + idx1, 1 + idx2).value = +e[column.field]; firstSheet.getCell(fromRow + idx1, 1 + idx2).numFmt = '#'; } else { firstSheet.getCell(fromRow + idx1, 1 + idx2).value = e[column.field]; } firstSheet.getCell(fromRow + idx1, 1 + idx2).style = Object.assign({}, __classPrivateFieldGet(this, _cellStyle)); }); }); const file = yield workbook.xlsx.writeBuffer(); SdUtility.downloadBlob(new Blob([file], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }), fileName); }); this.exportCustom = (option) => __awaiter(this, void 0, void 0, function* () { const { fileName, sheets } = option; if (!(sheets === null || sheets === void 0 ? void 0 : sheets.length)) { this.notifyService.notify.warning('Phải có ít nhất 1 sheet'); return; } const workbook = new Workbook(); for (const [idx, sheet] of sheets.entries()) { const { name, columns, cells } = sheet; const worksheet = workbook.addWorksheet(name || `Sheet ${idx + 1}`); for (const column of columns || []) { worksheet.getColumn(column.index).style = column.style; worksheet.getColumn(column.index).width = column.width; } for (const cell of cells) { const { row, column, value, style } = cell; worksheet.getCell(row, column).style = style || worksheet.getColumn(column).style; worksheet.getCell(row, column).value = value; } } const file = yield workbook.xlsx.writeBuffer(); SdUtility.downloadBlob(new Blob([file], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }), fileName); }); this.mergePDF = (urls) => __awaiter(this, void 0, void 0, function* () { const { sdMergePDF } = API; const url = `${this.functionUrl}${sdMergePDF}`; const buffer = yield this.apiService.post(url, { urls, }, null, { responseType: 'arraybuffer', }); SdUtility.downloadBlob(new Blob([buffer], { type: 'application/pdf' })); }); this.uploadXlsx = () => __awaiter(this, void 0, void 0, function* () { return yield SdUtility.upload({ extensions: ['xlsx'], maxSizeInMb: 10, }).then(file => { return this.parseXlsx(file); }); }); this.parseXlsx = (file) => __awaiter(this, void 0, void 0, function* () { if (file) { return new Promise((resolve, reject) => { const wb = new Workbook(); const reader = new FileReader(); reader.onload = () => { const buffer = reader.result; if (!buffer) { reject('Có lỗi xảy ra khi đọc file'); return; } wb.xlsx.load(buffer).then(workbook => { const sheet = workbook.worksheets[0]; if (!sheet) { reject('Không tìm thấy dữ liệu'); return; } const items = []; const headers = sheet.getRow(1).values; if (Array.isArray(headers)) { sheet.eachRow((row, rowIndex) => { const { hasValues, values } = row; // console.log(row, hasValues, values) if (hasValues && rowIndex > 1) { const item = {}; headers.forEach((cellValue, index) => { if (cellValue) { const field = cellValue.toString(); item[field] = values[index]; if (typeof item[field] === 'string') { item[field] = item[field].trim(); } if (item[field] === '' || item[field] === undefined) { item[field] = null; } } }); items.push(item); } }); resolve({ items, file, }); } }); }; reader.readAsArrayBuffer(file); }); } else { return { items: [], file: null, }; } }); } get functionUrl() { var _a; return (_a = this.firebaseConfiguration) === null || _a === void 0 ? void 0 : _a.functionUrl; } get folder() { const { project, env } = this.firebaseConfiguration; return `${project}-${env}`; } get userFolder() { const { folder } = this.firebaseConfiguration; if (!folder) { return; } if (typeof folder === 'string') { return folder; } return folder(); } } _fieldStyle = new WeakMap(), _titleColor = new WeakMap(), _titleFgColor = new WeakMap(), _titleStyle = new WeakMap(), _requiredStyle = new WeakMap(), _descriptionStyle = new WeakMap(), _cellStyle = new WeakMap(), _directory = new WeakMap(); SdExportService.ɵprov = ɵɵdefineInjectable({ factory: function SdExportService_Factory() { return new SdExportService(ɵɵinject(SdApiService), ɵɵinject(SdNotifyService), ɵɵinject(FIREBASE_CONFIG, 8)); }, token: SdExportService, providedIn: "root" }); SdExportService.decorators = [ { type: Injectable, args: [{ providedIn: 'root', },] } ]; SdExportService.ctorParameters = () => [ { type: SdApiService }, { type: SdNotifyService }, { type: undefined, decorators: [{ type: Inject, args: [FIREBASE_CONFIG,] }, { type: Optional }] } ]; /** * Generated bundle index. Do not edit. */ export { API, SdExportService }; //# sourceMappingURL=sd-angular-core-export.js.map