prg-class
Version:
Clases genéricas utilizadas por microservicios Programamos SPA.
528 lines (527 loc) • 24.3 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ObjExcel = void 0;
const fs = require("fs");
const Excel = require("exceljs");
const C = require("prg-constant");
const F = require("prg-function");
// import U = require('../params'); // Funciones específicas de clases.
// import UF = require('../../shared/mod-func');
class ObjExcel {
constructor() {
this.moLetterHead = {
L1: 'Programamos SPA',
L2: 'Desarrollo de Software',
L3: 'https://www.programamos.cl',
L4: 'La Capitanía 80, Oficina 101 Las Condes',
L5: 'Fono 999082128'
};
this.loL = []; // Arreglo con letras de columnas de Excel. Desde <A> hasta <AZ>.
this.loA = ['', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'];
this.msColPri = 'FF1D7D4D';
this.msColSec = 'FF1D7D4D';
this.msColSec1 = 'FFCFE4DF';
this.msColWhi = 'FFFFFFFF';
this.msBorDel = 'thin';
this.msBorMed = 'medium';
this.msBorGru = 'thick';
this.msFont = 'Calibri';
this.mlMaxTabRegs = 15;
this.mbRawData = false;
this.moXls = {
fileName: 'archivo.xlsx',
stripRow: true,
pattern: {
even: { style: 'solid', color: { argb: this.msColSec1 } }, // eceeef
odd: { style: 'solid', color: { argb: this.msColWhi } },
},
};
}
fnExportDataset(aoParams) {
return __awaiter(this, void 0, void 0, function* () {
for (let k = 0; k < this.loA.length; k++) { // Ciclo para llenar arreglo de letras de columnas de Excel.
for (let i = 0; i < 26; i++) {
const lsL1 = this.loA[k];
const lsL2 = String.fromCharCode(i + 65);
const lsLetra = lsL1 + lsL2;
this.loL.push(lsLetra);
}
}
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
const P = aoParams;
const lsTit = F.trim(P.wb.title);
const lsTag = F.trim(P.wb.tag);
const lsSbj = F.trim(P.wb.subject);
const loWB = this.fnNewBook(lsTit, lsTag, lsSbj); // Crea libro.
const loS1 = this.fnMakeDataDataset(P);
this.exportDataset(loWB, 1, loS1, P.strip, P.wb, P.mc, P.cc, P.vw, P.fml, P.tag);
if (!P.filename || F.trim(P.filename) === '') { // Retorna base 64...
const buffer = yield loWB.xlsx.writeBuffer();
const string64 = buffer.toString('base64');
return resolve(F.fnReturn(null, string64, C.HttpCode.Ok.OK)); // Retorna datos.
}
else { // Escribe Excel en disco...
return loWB.xlsx.writeFile(F.trim(P.filename)).then(() => {
return resolve(F.fnReturn(null, true, C.HttpCode.Ok.OK)); // Retorna datos.
}).catch((err) => {
return resolve(F.fnReturn(null, false, C.HttpCode.Ok.OK)); // Retorna datos.
});
}
}));
});
}
exportDataset(aoWB, alSheetId, aoData, abStripRows, aoEnc = [], aoMC = [], aoCellColor = { colIni: 0, color: '', qty: 0, step: 0 }, aoVw = [], alFormula = 0, aoTag = null) {
let lsAux = ''; // Variable auxiliar.
const llFilTit = 7; // Cantidad de filas de encabezado de título.
const llHeaderRow = llFilTit + 1; // Fila donde se ubica encabezado de fila.
const mlRowHeight = 23; // Alto de fila, por defecto.
const liFacChar = 10; // Factor de conversión de ancho a caracteres.
const ws = aoWB.addWorksheet(`Hoja${alSheetId}`, { properties: { defaultRowHeight: mlRowHeight } }); // Crea nombre de la hoja.
const liCols = aoData.fields.length; // Determina cantidad de columnas.
ws.properties.defaultRowHeight = mlRowHeight;
ws.views = [{ activeCell: 'A1', showGridLines: false }]; // Define vista, por defecto de la hoja.
if (aoVw && aoVw.length > 0) {
ws.views = aoVw;
}
// *** Membrete ***
ws.getCell('B2').value = this.moLetterHead.L1;
ws.getCell('B3').value = this.moLetterHead.L2;
ws.getCell('B4').value = this.moLetterHead.L3;
ws.getCell('B4').font = { underline: true }; // Subraya membrete.
for (let i = 7; i < (llFilTit); i++) { // Fillers
ws.getCell(`B${i}`).value = ''; // Escribe fillers.
}
// *** TÍTULO ***
const lsTit = aoEnc && aoEnc.title ? aoEnc.title : 'Informe';
this.fnAddText(ws, 'B7', lsTit, '', false, { name: this.msFont, size: 14, bold: true });
/* Escribe datos */
const loFld = ['', 'N°'];
const loCols = [{ width: 5 }, { width: 5 }]; // Define las columnas.
aoData.fields.forEach((loEL) => {
loFld.push(loEL['c']);
loCols.push({ width: loEL['w'] / liFacChar });
});
ws.columns = loCols;
ws.addRows(['']); // Escribe separador de título y encabezado de datos.
ws.addRows([loFld]); // Escribe encabezado de datos.
if (aoData && aoData.data && aoData.data.length > 0) {
ws.addRows(aoData.data); // Escribe los datos.
}
const liRegs = aoData.data.length; // Cantidad de registros.
const llEncFil = llFilTit + 1 + 1; // Determina fila de encabezado.
for (let i = 0; i <= liRegs; i++) { // Ciclo para aplicar formato a datos (filas).
for (let j = 0; j <= liCols; j++) { // Ciclo para aplicar formato a datos (columnas).
lsAux = this.loL[j + 1] + (llHeaderRow + i + 1); // Determina letra de la columna.
let lsAli = '';
if (j > 0) {
const lsA = F.trim(aoData.fields[j - 1].a).toUpperCase();
lsAli = (lsA === undefined || lsA === '' || lsA === 'L') ? 'left' : aoData.fields[j - 1].a === 'C'
? 'center' : 'right';
const lsF = aoData.fields[j - 1].f;
if (lsF !== '') {
ws.getCell(lsAux).numFmt = lsF; // Si corresponde, asigna formato.
}
ws.getCell(lsAux).font = { size: 8 }; // Asigna tamaño de letra.
}
ws.getCell(lsAux).alignment = {
wrapText: true, indent: 0, horizontal: lsAli,
}; // Asigna celda que engorda, dependiendo del texto.
if (abStripRows) { // Si se desea resaltar filas alternadas.
const llI2 = i / 2;
if (i > 0 && llI2 === parseInt(llI2.toString(), 10)) { // Resaltado de fila par.
ws.getCell(lsAux).fill = {
type: 'pattern',
pattern: this.moXls.pattern.even.style,
fgColor: this.moXls.pattern.even.color,
};
}
else { // Resaltado de fila impar.
if (i > 0) {
ws.getCell(lsAux).fill = {
type: 'pattern',
pattern: this.moXls.pattern.odd.style,
fgColor: this.moXls.pattern.odd.color,
};
}
}
}
}
}
for (let i = 0; i <= liRegs; i++) { // Ciclo para aplicar altura de fila.
ws.getRow(i + llFilTit + 2).height = mlRowHeight;
}
// *** Asigna Borde para lista de datos ***
const llRowTabIni = llHeaderRow + 1;
const llRowTabFin = llRowTabIni + liRegs;
const lsBd = this.msBorDel;
this.fnSetBox(ws, 'B', llRowTabIni + 1, 'B', llRowTabFin, lsBd, false, false, false, true); // Borde izquierda.
// Borde derecha.
this.fnSetBox(ws, this.loL[liCols + 1], llRowTabIni + 1, this.loL[liCols + 1], llRowTabFin, lsBd, false, true, false, false);
this.fnSetBox(ws, 'B', llRowTabFin, this.loL[liCols + 1], llRowTabFin, lsBd, false, false, true, false); // Borde abajo.
this.fnSetBox(ws, 'B', llRowTabFin, 'B', llRowTabFin, lsBd, false, false, true, true); // Borde esquina inferior izquierda.
// Borde esquina derecha.
this.fnSetBox(ws, this.loL[liCols + 1], llRowTabFin, this.loL[liCols + 1], llRowTabFin, lsBd, false, true, true, false);
this.fnSetTableTitle(ws, 'B', llEncFil, this.loL[liCols + 1], llEncFil, this.msBorDel, false); // Aplica formato a encabezado.
// *** Agrega columnas combinadas ***
if (aoMC && aoMC.length > 0) {
aoMC.forEach((mc) => {
const lsCI = `${mc.il + mc.in}`;
ws.mergeCells(`${lsCI}:${mc.fl}${mc.fn}`);
ws.getCell(lsCI).value = mc.v;
ws.getCell(lsCI).alignment = { horizontal: mc.a };
ws.getRow(mc.in).height = mlRowHeight;
this.fnSetTableTitle(ws, mc.il, mc.in, mc.fl, mc.in + 1, this.msBorDel, true);
});
}
this.setCellColor(aoCellColor, ws, aoData.data.length); // Asigna colores personalizados.
}
cellValue(aoWs, asLetra, alFila, asMsg, alSz = 12, abBold = false) {
if (F.trim(asMsg) !== '') {
aoWs.getCell(`${asLetra}${alFila}`).value = asMsg; // Mensaje.
}
aoWs.getCell(`${asLetra}${alFila}`).font = { size: alSz, bold: abBold }; // Asigna tamaño de letra.
}
cellSumFormula(aoWs, asLetVal, alFilaVal, alSumaIni, alSumaFin, asFM, alSz = 12, abBold = false) {
aoWs.getCell(`${asLetVal}${alFilaVal}`).value = {
formula: `SUM(${asLetVal}${alSumaIni}:${asLetVal}${alSumaFin})`, // Fórmula.
result: 0, // Valor por defecto.
};
aoWs.getCell(`${asLetVal}${alFilaVal}`).numFmt = asFM; // Formato.
aoWs.getCell(`${asLetVal}${alFilaVal}`).font = { size: alSz, bold: abBold }; // Asigna tamaño de letra.
}
setCellColor(aoCellColor, aoWS, alRowCount) {
const CC = aoCellColor;
if (!CC || CC.colIni <= 0 || F.trim(CC.color) === '' || CC.step <= 0 || CC.qty <= 0) {
return;
}
let llCol = CC.colIni;
const llIni = 9;
for (let i = 0; i < CC.qty; i++) {
const lsLet = this.loL[llCol];
const loCell = [];
for (let j = llIni; j <= alRowCount + llIni; j++) {
loCell.push(lsLet + F.trim(j));
}
loCell.map((key) => {
aoWS.getCell(key).fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: CC.color },
};
return;
});
llCol += CC.step;
}
}
fnMakeDataDataset(aoParams) {
const loAux = [];
if (aoParams && aoParams.d && aoParams.d.length > 0) {
for (let i = 0; i < aoParams.d.length; i++) {
const loRow = ['', i + 1];
for (let j = 0; j < aoParams.l.length; j++) {
let lsName = F.trim(aoParams.l[j].n);
const llType = F.intval(aoParams.l[j].t);
if (llType === C.jDTT.xBool) {
lsName += '1'; // En los campos boolean, se muestra la contraparte tipo texto: SI /NO.
}
let loVal = F.trim(aoParams.d[i][lsName]);
if (llType === C.jDTT.xNumb) {
loVal = F.intval(aoParams.d[i][lsName]);
}
if (llType === C.jDTT.xFloat) {
loVal = F.floatval(aoParams.d[i][lsName]);
}
if (llType === C.jDTT.xDate) {
// loVal = F.fnGetDateChile(aoParams.d[i][lsName]);
loVal = F.fnGetDateStringChile(aoParams.d[i][lsName], false);
}
if (llType === C.jDTT.xDateTime) {
loVal = F.fnGetDateStringChile(aoParams.d[i][lsName], true);
}
loRow.push(loVal);
}
loAux.push(loRow);
}
}
const loRet = { data: !this.mbRawData ? loAux : aoParams.d, fields: aoParams.l };
return loRet;
}
fnSetTableTitle(aoWs, asColIni, alFilIni, asColFin = '', alFilFin = 0, asBorder = '', abBorderInterno = true) {
// Bordes encabezado de tabla.
const lsBd = asBorder !== '' ? asBorder : this.msBorMed;
let loBx = {
top: { style: lsBd, color: { argb: this.msColPri } },
left: { style: lsBd, color: { argb: this.msColPri } },
bottom: { style: lsBd, color: { argb: this.msColPri } },
right: { style: lsBd, color: { argb: this.msColPri } },
};
const loBL = {
left: { style: lsBd, color: { argb: this.msColPri } },
top: { style: lsBd, color: { argb: this.msColPri } },
bottom: { style: lsBd, color: { argb: this.msColPri } },
};
const loBR = {
right: { style: lsBd, color: { argb: this.msColPri } },
top: { style: lsBd, color: { argb: this.msColPri } },
bottom: { style: lsBd, color: { argb: this.msColPri } },
};
if (!abBorderInterno) { // No se requiere borde interno.
loBx = {
top: { style: lsBd, color: { argb: this.msColPri } },
bottom: { style: lsBd, color: { argb: this.msColPri } },
};
}
const loGR1 = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: this.msColSec }, //
bgColor: { argb: this.msColSec },
};
// Configura filas.
if (alFilFin < alFilIni) {
alFilFin = alFilIni;
asColFin = asColIni;
}
// Configura columnas.
if (asColFin === '') {
asColFin = asColIni;
}
const liColI = this.loL.indexOf(asColIni); // asColIni.charCodeAt(0);
let liColF = this.loL.indexOf(asColFin); // asColFin.charCodeAt(0);
if (liColF < liColI) {
asColFin = asColIni;
liColF = liColI;
}
if (!abBorderInterno) { // No tiene bordes internos, asigna borde izquierdo y derecho.
// Ciclo para recorrer filas.
for (let i = alFilIni; i <= alFilFin; i++) {
const lsCelL = asColIni + i; // Determina celda izquierda.
const lsCelR = asColFin + i; // Determina celda derecha.
aoWs.getCell(lsCelL).border = loBL;
aoWs.getCell(lsCelR).border = loBR;
}
}
// Ciclo para recorrer filas / columnas.
for (let i = alFilIni; i <= alFilFin; i++) {
for (let j = liColI; j <= liColF; j++) {
const loFont = { name: this.msFont, size: 9, bold: true, color: { argb: this.msColWhi } };
const lsCell = this.loL[j] + i;
aoWs.getCell(lsCell).border = loBx;
// aoWs.getCell(lsCell).font = { name: this.msFont, size: 9, bold: true, color: { argb: this.msColWhi } };
aoWs.getCell(lsCell).alignment = { horizontal: 'center' };
aoWs.getCell(lsCell).fill = loGR1;
aoWs.getCell(lsCell).font = loFont;
}
}
}
fnBoxMedLins(aoWs, asColIni, alFilIni, asColFin = '', alFilFin = 0, asBorder = this.msBorGru) {
// Configura filas.
if (alFilFin < alFilIni) {
alFilFin = alFilIni;
asColFin = asColIni;
}
// Configura columnas.
if (asColFin === '') {
asColFin = asColIni;
}
const liColI = asColIni.charCodeAt(0);
let liColF = asColFin.charCodeAt(0);
if (liColF < liColI) {
asColFin = asColIni;
liColF = liColI;
}
const loBTL = {
top: { style: asBorder, color: { argb: this.msColPri } },
left: { style: asBorder, color: { argb: this.msColPri } },
};
const loBTR = {
top: { style: asBorder, color: { argb: this.msColPri } },
right: { style: asBorder, color: { argb: this.msColPri } },
};
const loBBL = {
bottom: { style: asBorder, color: { argb: this.msColPri } },
left: { style: asBorder, color: { argb: this.msColPri } },
};
const loBBR = {
bottom: { style: asBorder, color: { argb: this.msColPri } },
right: { style: asBorder, color: { argb: this.msColPri } },
};
const loBT = { top: { style: asBorder, color: { argb: this.msColPri } } };
const loBB = { bottom: { style: asBorder, color: { argb: this.msColPri } } };
const loBL = { left: { style: asBorder, color: { argb: this.msColPri } } };
const loBR = { right: { style: asBorder, color: { argb: this.msColPri } } };
const loBF1 = {
bottom: { style: this.msBorDel, color: { argb: this.msColPri } },
top: { style: this.msBorDel, color: { argb: this.msColPri } },
};
const loBRF = {
right: { style: asBorder, color: { argb: this.msColPri } },
bottom: { style: this.msBorDel, color: { argb: this.msColPri } },
top: { style: this.msBorDel, color: { argb: this.msColPri } },
};
// Raya superior e inferior.
for (let j = liColI; j <= liColF; j++) {
const lsCelI = this.loL[j] + alFilIni;
const lsCelF = this.loL[j] + alFilFin;
aoWs.getCell(lsCelI).border = loBT;
aoWs.getCell(lsCelF).border = loBB;
}
// Borde izquierdo y derecho.
for (let j = alFilIni + 1; j < alFilFin; j++) {
const lsCelL = asColIni + j; // Determina celda izquierda.
const lsCelR = asColFin + j; // Determina celda izquierda.
aoWs.getCell(lsCelL).border = loBL;
aoWs.getCell(lsCelR).border = loBRF;
}
// Esquinas.
aoWs.getCell(asColIni + alFilIni).border = loBTL;
aoWs.getCell(asColIni + alFilFin).border = loBBL;
aoWs.getCell(asColFin + alFilIni).border = loBTR;
aoWs.getCell(asColFin + alFilFin).border = loBBR;
// LÃneas delgadas interiores.
for (let i = alFilIni + 1; i < alFilFin; i++) {
for (let j = liColI + 1; j < liColF; j++) {
const lsCell = this.loL[j] + i; // Determina celda para aplicar lÃnea fina.
aoWs.getCell(lsCell).border = loBF1;
}
}
}
fnLinVert(aoWs, asColIni, alFilIni, asColFin = '', alFilFin = 0) {
// Configura filas.
if (alFilFin < alFilIni) {
alFilFin = alFilIni;
asColFin = asColIni;
}
// Configura columnas.
if (asColFin === '') {
asColFin = asColIni;
}
const liColI = asColIni.charCodeAt(0);
let liColF = asColFin.charCodeAt(0);
if (liColF < liColI) {
asColFin = asColIni;
liColF = liColI;
}
const loBy = {
left: { style: this.msBorMed, color: { argb: this.msColPri } },
right: { style: this.msBorMed, color: { argb: this.msColPri } },
};
// Crea bordes.
for (let i = alFilIni; i <= alFilFin; i++) {
for (let j = liColI; j <= liColF; j++) {
const lsCell = this.loL[j] + i; // Determina celda para aplicar lÃnea fina.
aoWs.getCell(lsCell).border = loBy;
}
}
}
fnSetBox(aoWs, asColIni, alFilIni, asColFin = '', alFilFin = 0, asBorderStyle = this.msBorDel, abTop = false, abRight = false, abBottom = false, abLeft = false) {
// Configura filas.
if (alFilFin < alFilIni) {
alFilFin = alFilIni;
asColFin = asColIni;
}
// Configura columnas.
if (asColFin === '') {
asColFin = asColIni;
}
const liColI = this.loL.indexOf(asColIni);
let liColF = this.loL.indexOf(asColFin);
if (liColF < liColI) {
asColFin = asColIni;
liColF = liColI;
}
if (asBorderStyle === '') {
asBorderStyle = this.msBorMed;
}
const loSty = { style: asBorderStyle, color: { argb: this.msColPri } };
let loB = { top: loSty, left: loSty, bottom: loSty, right: loSty };
if (!abTop && !abRight && !abBottom && !abLeft) {
// Aplica todos los bordes.
}
else { // Aplica bordes especÃficos.
const loAux = {};
if (abTop) {
loAux.top = loSty;
}
if (abRight) {
loAux.right = loSty;
}
if (abBottom) {
loAux.bottom = loSty;
}
if (abLeft) {
loAux.left = loSty;
}
loB = loAux;
}
// Crea bordes.
for (let i = alFilIni; i <= alFilFin; i++) {
for (let j = liColI; j <= liColF; j++) {
const lsCell = this.loL[j] + i; // Determina celda para aplicar lÃnea fina.
aoWs.getCell(lsCell).border = loB;
}
}
}
fnAddText(aoWs, asCell, asText, asAliHor = 'left', abWrap = false, aoFont = null) {
aoWs.getCell(asCell).value = asText;
aoWs.getCell(asCell).alignment = {
wrapText: abWrap, horizontal: asAliHor,
};
if (aoFont !== null) {
aoWs.getCell(asCell).font = aoFont;
}
}
fnAddNumber(aoWs, asCell, adNumber, asFormat = '', aoFont = null) {
aoWs.getCell(asCell).value = adNumber;
aoWs.getCell(asCell).alignment = { horizontal: 'right' };
if (aoFont !== null) {
aoWs.getCell(asCell).font = aoFont;
}
if (asFormat !== '') {
aoWs.getCell(asCell).numFmt = asFormat;
}
}
fnNewBook(asTitle = '', asTag = '', asSubject = '') {
const loWB = new Excel.Workbook();
loWB.creator = 'HOSCAR';
loWB.lastModifiedBy = 'HOSCAR';
loWB['title'] = asTitle;
loWB['keywords'] = asTag;
loWB['subject'] = asSubject;
loWB.created = new Date();
loWB.modified = new Date();
loWB.lastPrinted = new Date();
return loWB;
}
fnWriteFile(aoWB, asUserId, asFile) {
return new Promise((resolve, reject) => {
let lsDir = this.fnTempFolder(); // Carpeta Base.
lsDir = `${lsDir}userdata`;
if (!fs.existsSync(lsDir)) {
fs.mkdirSync(lsDir);
}
lsDir = `${lsDir}/${asUserId}`;
if (!fs.existsSync(lsDir)) {
fs.mkdirSync(lsDir);
}
const lsFileName = `${lsDir}/${asFile}`;
aoWB.xlsx.writeFile(lsFileName).then(() => {
const lsRet = F.fnStrReplace('/', '|', lsFileName);
return resolve(F.fnReturn('', lsRet, C.HttpCode.Ok.OK)); // Retorna datos.
});
});
}
fnTempFolder() {
return F.getPathTemp();
}
}
exports.ObjExcel = ObjExcel;