-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: ✨ Adding template export in xlsx format feature
- Loading branch information
1 parent
44ad6a4
commit 881160f
Showing
6 changed files
with
307 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TemplateExcel = void 0; | ||
const exceljs_1 = require("exceljs"); | ||
const StringUtils_1 = require("../utils/StringUtils"); | ||
class TemplateExcel { | ||
constructor(config) { | ||
this._config = config; | ||
this._validationRules = config.validationRules; | ||
this._columns = Object.keys(this._validationRules); | ||
this._workbook = this.createTemplateExcel(); | ||
} | ||
createTemplateExcel() { | ||
const workbook = new exceljs_1.Workbook(); | ||
this.addExcelCoverWorksheet(workbook); | ||
this.addExcelValidationWorksheet(workbook); | ||
this.addExcelTemplateWorksheet(workbook); | ||
return workbook; | ||
} | ||
getExcelBuffer() { | ||
return this._workbook.xlsx.writeBuffer({ filename: 'template.xlsx' }); | ||
} | ||
addExcelCoverWorksheet(workbook) { | ||
const coverSheet = workbook.addWorksheet('cover'); | ||
coverSheet.getCell('A1').value = `Template downloaded on: ${new Date()}`; | ||
coverSheet.getCell('A2').value = `Configuration version: ${this._config.version}`; | ||
} | ||
addExcelValidationWorksheet(workbook) { | ||
const validationTemplate = workbook.addWorksheet('validation'); | ||
this.setExcelWorksheetHeader(validationTemplate); | ||
this.setValidationExcelWorksheetValues(validationTemplate); | ||
} | ||
addExcelTemplateWorksheet(workbook) { | ||
const templateSheet = workbook.addWorksheet('template'); | ||
this.setExcelWorksheetHeader(templateSheet); | ||
this.setTemplateExcelWorksheetDataValidation(templateSheet); | ||
} | ||
setExcelWorksheetHeader(worksheet) { | ||
const columns = ["url", ...this._columns]; | ||
worksheet.columns = columns.map(column => { | ||
return { | ||
header: column, | ||
key: column, | ||
width: 20 | ||
}; | ||
}); | ||
} | ||
setValidationExcelWorksheetValues(validationWorksheet) { | ||
this._columns.forEach(column => { | ||
validationWorksheet.getColumn(column).values = [column, ...this._validationRules[column]]; | ||
}); | ||
} | ||
setTemplateExcelWorksheetDataValidation(templateWorksheet) { | ||
this._columns.forEach(column => { | ||
if (!StringUtils_1.StringUtils.isStringForRegex(this._validationRules[column][0])) { | ||
const validationCount = this._validationRules[column].length; | ||
let columnLetter = templateWorksheet.getColumn(column).letter; | ||
for (let i = 2; i < 1003; i++) { | ||
templateWorksheet.getCell(columnLetter + i).dataValidation = { | ||
type: 'list', | ||
allowBlank: false, | ||
formulae: [`=validation!$${columnLetter}$2:$${columnLetter}$${validationCount + 1}`] | ||
}; | ||
} | ||
} | ||
}); | ||
} | ||
checkRegex(string) { | ||
return string.match(/^\/.*\/$/) !== null; | ||
} | ||
} | ||
exports.TemplateExcel = TemplateExcel; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,61 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
const ConfigDAO_1 = require('../models/DAO/ConfigDAO'); | ||
const ApiResponse_1 = require('../models/ApiResponse'); | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const ConfigDAO_1 = require("../models/DAO/ConfigDAO"); | ||
const ApiResponse_1 = require("../models/ApiResponse"); | ||
const TemplateExcel_1 = require("../models/TemplateExcel"); | ||
const template = (app) => { | ||
app.get('/template', (req, res) => { | ||
const configDAO = new ConfigDAO_1.ConfigDAO('company'); | ||
const apiResponse = new ApiResponse_1.ApiResponse(); | ||
configDAO | ||
.getLastConfig() | ||
.then((config) => { | ||
res.setHeader('Content-disposition', 'attachment; filename=template.csv'); | ||
res.set('Content-Type', 'text/csv; charset=utf-8'); | ||
apiResponse.statusCode = 200; | ||
apiResponse.responseText = config.toCsvTemplate(); | ||
}) | ||
.catch((err) => { | ||
apiResponse.responseText = 'Erro ao recuperar a configuração!'; | ||
apiResponse.statusCode = 500; | ||
apiResponse.errorMessage = err.message; | ||
}) | ||
.finally(() => { | ||
if (apiResponse.statusCode === 200) { | ||
res.status(apiResponse.statusCode).send(apiResponse.responseText); | ||
} else { | ||
res.status(apiResponse.statusCode).send(apiResponse.jsonResponse); | ||
} | ||
}); | ||
}); | ||
app.get('/template', (req, res) => { | ||
const company = req.company; | ||
const configDAO = new ConfigDAO_1.ConfigDAO('company'); | ||
const apiResponse = new ApiResponse_1.ApiResponse(); | ||
configDAO | ||
.getLastConfig() | ||
.then((config) => { | ||
res.setHeader('Content-disposition', 'attachment; filename=template.csv'); | ||
res.set('Content-Type', 'text/csv; charset=utf-8'); | ||
apiResponse.statusCode = 200; | ||
apiResponse.responseText = config.toCsvTemplate(); | ||
}) | ||
.catch((err) => { | ||
apiResponse.responseText = 'Erro ao recuperar a configuração!'; | ||
apiResponse.statusCode = 500; | ||
apiResponse.errorMessage = err.message; | ||
}) | ||
.finally(() => { | ||
if (apiResponse.statusCode === 200) { | ||
res.status(apiResponse.statusCode).send(apiResponse.responseText); | ||
} | ||
else { | ||
res.status(apiResponse.statusCode).send(apiResponse.jsonResponse); | ||
} | ||
}); | ||
}); | ||
app.get('/template/excel', (req, res) => { | ||
const company = req.company; | ||
const configDAO = new ConfigDAO_1.ConfigDAO(company); | ||
const apiResponse = new ApiResponse_1.ApiResponse(); | ||
configDAO | ||
.getLastConfig() | ||
.then((config) => { | ||
const templateExcel = new TemplateExcel_1.TemplateExcel(config); | ||
templateExcel.getExcelBuffer() | ||
.then((buffer) => { | ||
apiResponse.statusCode = 200; | ||
res.contentType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); | ||
res.attachment('template.xlsx'); | ||
res.send(buffer); | ||
}).catch((err) => { | ||
apiResponse.responseText = 'Erro ao baixar o template!'; | ||
apiResponse.statusCode = 500; | ||
apiResponse.errorMessage = err.message; | ||
res.status(apiResponse.statusCode).send(apiResponse.jsonResponse); | ||
}); | ||
}).catch((err) => { | ||
apiResponse.responseText = 'Erro ao recuperar a configuração!'; | ||
apiResponse.statusCode = 500; | ||
apiResponse.errorMessage = err.message; | ||
res.status(apiResponse.statusCode).send(apiResponse.jsonResponse); | ||
}); | ||
}); | ||
}; | ||
exports.default = template; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,38 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.StringUtils = void 0; | ||
class StringUtils { | ||
static normalize(string) { | ||
return string | ||
.toLowerCase() | ||
.replace(/[áàãâä]/gi, 'a') | ||
.replace(/[éèêë]/gi, 'e') | ||
.replace(/[íìîï]/gi, 'i') | ||
.replace(/[óòõôö]/gi, 'o') | ||
.replace(/[úùûü]/gi, 'u') | ||
.replace(/[ç]/gi, 'c'); | ||
} | ||
static replaceWhiteSpace(string, replacer) { | ||
return string.replace(/ /g, replacer); | ||
} | ||
static _isStringForRegex(string) { | ||
return string[0] === '/' && string[string.length - 1] === '/'; | ||
} | ||
static validateString(stringToValidate, rules, separator = ' ') { | ||
const validate = [false]; | ||
rules.forEach((rule) => { | ||
if (this._isStringForRegex(rule)) { | ||
const regexRule = new RegExp(rule.slice(1, rule.length - 1)); | ||
validate.push(!!stringToValidate.match(regexRule)); | ||
} else { | ||
validate.push( | ||
stringToValidate.toLocaleLowerCase() === this.replaceWhiteSpace(rule.toLocaleLowerCase(), separator) | ||
); | ||
} | ||
}); | ||
return validate.indexOf(true) !== -1; | ||
} | ||
static isEmpty(string) { | ||
return !string; | ||
} | ||
static normalize(string) { | ||
return string | ||
.toLowerCase() | ||
.replace(/[áàãâä]/gi, 'a') | ||
.replace(/[éèêë]/gi, 'e') | ||
.replace(/[íìîï]/gi, 'i') | ||
.replace(/[óòõôö]/gi, 'o') | ||
.replace(/[úùûü]/gi, 'u') | ||
.replace(/[ç]/gi, 'c'); | ||
} | ||
static replaceWhiteSpace(string, replacer) { | ||
return string.replace(/ /g, replacer); | ||
} | ||
static isStringForRegex(string) { | ||
return string[0] === '/' && string[string.length - 1] === '/'; | ||
} | ||
static validateString(stringToValidate, rules, separator = ' ') { | ||
const validate = [false]; | ||
rules.forEach((rule) => { | ||
if (this.isStringForRegex(rule)) { | ||
const regexRule = new RegExp(rule.slice(1, rule.length - 1)); | ||
validate.push(!!stringToValidate.match(regexRule)); | ||
} | ||
else { | ||
validate.push(stringToValidate.toLocaleLowerCase() === this.replaceWhiteSpace(rule.toLocaleLowerCase(), separator)); | ||
} | ||
}); | ||
return validate.indexOf(true) !== -1; | ||
} | ||
static isEmpty(string) { | ||
return !string; | ||
} | ||
} | ||
exports.StringUtils = StringUtils; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import { Buffer, Workbook, Worksheet } from 'exceljs'; | ||
import { StringUtils } from '../utils/StringUtils'; | ||
import { Config } from './Config'; | ||
|
||
export class TemplateExcel { | ||
private _config: Config; | ||
private _validationRules: { [key:string]: string[] }; | ||
private _columns: string[]; | ||
private _workbook: Workbook; | ||
|
||
constructor(config: Config) { | ||
this._config = config; | ||
this._validationRules = config.validationRules; | ||
this._columns = Object.keys(this._validationRules); | ||
this._workbook = this.createTemplateExcel(); | ||
} | ||
|
||
/** | ||
* Criar o template em formato Excel .xlsx. | ||
* @returns Workbook Excel com abas 'Template' e 'Validation' populados de acordo com a configuração de validação do AdInfo. | ||
*/ | ||
private createTemplateExcel(): Workbook { | ||
const workbook = new Workbook(); | ||
this.addExcelCoverWorksheet(workbook); | ||
this.addExcelValidationWorksheet(workbook); | ||
this.addExcelTemplateWorksheet(workbook); | ||
return workbook; | ||
} | ||
|
||
/** | ||
* Criar um buffer a partir do Excel gerado na construção da classe. | ||
* @returns Uma Promise que retorna um Buffer a partir do Excel gerado na construção da classe. | ||
*/ | ||
public getExcelBuffer(): Promise<Buffer> { | ||
return this._workbook.xlsx.writeBuffer({filename: 'template.xlsx'}); | ||
} | ||
|
||
/** | ||
* Gerar a aba 'cover' no Excel Template, contendo informações do template, como data de download e versão da configuração. | ||
* @param workbook Objeto Workbook no qual a aba será gerada. | ||
*/ | ||
private addExcelCoverWorksheet(workbook: Workbook): void { | ||
const coverSheet = workbook.addWorksheet('cover'); | ||
coverSheet.getCell('A1').value = `Template downloaded on: ${new Date()}`; | ||
coverSheet.getCell('A2').value = `Configuration version: ${this._config.version}` | ||
} | ||
|
||
/** | ||
* Gerar a aba de 'Validation' no Excel Template, com os valores populados para validação. | ||
* @param workbook Objeto Workbook no qual a aba será gerada. | ||
*/ | ||
private addExcelValidationWorksheet(workbook: Workbook): void { | ||
const validationTemplate = workbook.addWorksheet('validation'); | ||
this.setExcelWorksheetHeader(validationTemplate); | ||
this.setValidationExcelWorksheetValues(validationTemplate); | ||
} | ||
|
||
/** | ||
* Gerar a aba de 'Template' no Excel Template, com os campos e validações populados para uso. | ||
* @param workbook Objeto Workbook no qual a aba será gerada. | ||
*/ | ||
private addExcelTemplateWorksheet(workbook: Workbook): void { | ||
const templateSheet = workbook.addWorksheet('template'); | ||
this.setExcelWorksheetHeader(templateSheet); | ||
this.setTemplateExcelWorksheetDataValidation(templateSheet); | ||
} | ||
|
||
/** | ||
* Nomear as colunas e inserir os valores dos campos na aba do Excel, com os valores de acordo com a configuração de validação do AdInfo. | ||
* @param worksheet Objeto Worksheet (aba do Excel) no qual terá os campos inseridos e as colunas nomeadas. | ||
*/ | ||
private setExcelWorksheetHeader(worksheet: Worksheet): void { | ||
const columns = ["url", ...this._columns]; | ||
worksheet.columns = columns.map(column => { | ||
return { | ||
header: column, | ||
key: column, | ||
width: 20 | ||
} | ||
}) | ||
} | ||
|
||
/** | ||
* Inserir o nome do campo e os valores de cada campo que serão usados para validação de dados, de acordo com a configuração de validação do AdInfo. | ||
* @param validationWorksheet Objeto Worksheet (aba do Excel) referente à aba de validação. | ||
*/ | ||
private setValidationExcelWorksheetValues(validationWorksheet: Worksheet): void { | ||
this._columns.forEach(column => { | ||
validationWorksheet.getColumn(column).values = [column, ...this._validationRules[column]]; | ||
}) | ||
} | ||
|
||
/** | ||
* Aplicar a validação de dados nos campos do template, de acordo com a configuração de validação do AdInfo, para as primeiras 1000 linhas. | ||
* @param templateWorksheet Objecto worksheet (aba do Excel) referente à aba de template. | ||
*/ | ||
private setTemplateExcelWorksheetDataValidation(templateWorksheet: Worksheet): void { | ||
this._columns.forEach(column => { | ||
if (!StringUtils.isStringForRegex(this._validationRules[column][0])) { | ||
const validationCount = this._validationRules[column].length; | ||
let columnLetter = templateWorksheet.getColumn(column).letter; | ||
for(let i = 2; i < 1003; i++) { | ||
templateWorksheet.getCell(columnLetter + i).dataValidation = { | ||
type: 'list', | ||
allowBlank: false, | ||
formulae: [`=validation!$${columnLetter}$2:$${columnLetter}$${validationCount + 1}`] | ||
}; | ||
} | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.