diff --git a/src/Controllers/SheetController.ts b/src/Controllers/SheetController.ts index 57cc9bcaab7fbf6df0bcef01a6a5efb3a3f51b80..63b65e7b5fd4bb1bd2843995afcbbcf3fb406d3b 100644 --- a/src/Controllers/SheetController.ts +++ b/src/Controllers/SheetController.ts @@ -1,21 +1,19 @@ import { Handler, Request, Response, Router, } from 'express'; +import { SheetParserResponse } from '../Models/SheetParserResponse'; import SheetService from '../Services/SheetService'; const router = Router(); -// const parseExcel = async (req:Request, res:Response) => { -// res.status(200).send(parseExcelService()); -// }; - const parseSheet: Handler = async (req: Request, res: Response) => { const sheet: Buffer = req.body; try { - const parsedSheet: JSON = SheetService.parseSheetService(sheet); + const parsedSheet: SheetParserResponse = SheetService.parseSheetService(sheet); return res.status(200).send(parsedSheet); } catch (error) { - return res.status(400).send({ error }); + const e = error as Error; + return res.status(400).json({ error: e.message }); } }; diff --git a/src/Models/SheetParserResponse.ts b/src/Models/SheetParserResponse.ts new file mode 100644 index 0000000000000000000000000000000000000000..c29b9e8aa94f52bc8ac2512aba15bbc90e26d29a --- /dev/null +++ b/src/Models/SheetParserResponse.ts @@ -0,0 +1,31 @@ +type SheetParserResponse = { + hombresMenores: Menores[] | null; + mujeresMenores: Menores[] | null; + hombres: Mayores[] | null; + mujeres: Mayores[] | null; +} | null; + +type Menores = { + edad: number; + peso: number; +} | null; + +type Mayores = { + edad: number; + peso?: number; + talla?: number; +} | null; + +type MenoresSheet = { + 'Edad (meses)': number; + 'Peso (Kg)': number; +}; +type MayoresSheet = { + 'Edad (años)': number; + 'Peso (Kg)': number; + 'Talla (cm)': number; +}; + +export type { + SheetParserResponse, Menores, Mayores, MenoresSheet, MayoresSheet, +}; diff --git a/src/Services/SheetService.ts b/src/Services/SheetService.ts index 846ca0e5e60c4b5b57e2daebcd18236c8348401b..79f94f559f76761daa7232daf033ba181fed1962 100644 --- a/src/Services/SheetService.ts +++ b/src/Services/SheetService.ts @@ -1,39 +1,138 @@ import * as XLSX from 'xlsx'; +import { + SheetParserResponse, Menores, Mayores, MenoresSheet, MayoresSheet, +} from '../Models/SheetParserResponse'; /* PRIVATE FUNCTIONS */ -const ec = (r: number, c: number): string => XLSX.utils.encode_cell({ r, c }); -const deleteRow = (ws: XLSX.WorkSheet, rowIndex: number): XLSX.WorkSheet => { - const work = ws; - if (work['!ref'] === undefined) throw new Error('An error has ocurred in deleteRow'); - const variable = XLSX.utils.decode_range(work['!ref']); - for (let R = rowIndex; R < variable.e.r; R += 1) { - for (let C = variable.s.c; C <= variable.e.c; C += 1) { - work[ec(R, C)] = work[ec(R + 1, C)]; - } - } - variable.e.r -= 1; - work['!ref'] = XLSX.utils.encode_range(variable.s, variable.e); - return work; -}; +// const ec = (r: number, c: number): string => XLSX.utils.encode_cell({ r, c }); +// const deleteRow = (ws: XLSX.WorkSheet, rowIndex: number): XLSX.WorkSheet => { +// const work = ws; +// if (work['!ref'] === undefined) throw new Error('An error has ocurred in deleteRow'); +// const variable = XLSX.utils.decode_range(work['!ref']); +// for (let R = rowIndex; R < variable.e.r; R += 1) { +// for (let C = variable.s.c; C <= variable.e.c; C += 1) { +// work[ec(R, C)] = work[ec(R + 1, C)]; +// } +// } +// variable.e.r -= 1; +// work['!ref'] = XLSX.utils.encode_range(variable.s, variable.e); +// return work; +// }; -/* EXPORT FUNCTIONS */ +const parseMen = (worksheet: XLSX.WorkSheet): Mayores[] => { + const res: Mayores[] = []; + const ref = worksheet['!ref']; + if (ref === undefined) throw new Error('An error ocurred'); + const range = XLSX.utils.decode_range(ref); + range.s.c = 0; + range.e.c = 2; + const newRange = XLSX.utils.encode_range(range); -const parseSheetService = (data: Buffer): JSON => { - const workbook: XLSX.WorkBook = XLSX.read(data); - let parsed: JSON = JSON.parse('{}'); + const aux = XLSX.utils.sheet_to_json(worksheet, { range: newRange }) as unknown as MayoresSheet[]; - const sheetName = workbook.SheetNames[0]; - const worksheet: XLSX.WorkSheet = workbook.Sheets[sheetName]; + aux.forEach((element: MayoresSheet) => { + res.push( + { + edad: element['Edad (años)'], + peso: element['Peso (Kg)'], + talla: element['Talla (cm)'], + }, + ); + }); + return res; +}; +const parseWomen = (worksheet: XLSX.WorkSheet): Mayores[] => { + const res: Mayores[] = []; const ref = worksheet['!ref']; - if (ref === undefined) throw new Error('An error has ocurred in parseSheetService'); + if (ref === undefined) throw new Error('An error ocurred'); const range = XLSX.utils.decode_range(ref); - range.s.c = 0; // 0 == XLSX.utils.decode_col("A") - range.e.c = 1; // 1 == XLSX.utils.decode_col("B") + range.s.c = 0; + range.e.c = 2; const newRange = XLSX.utils.encode_range(range); - const workSheetWithRowDeleted: XLSX.WorkSheet = deleteRow(worksheet, 0); - // eslint-disable-next-line max-len - parsed = XLSX.utils.sheet_to_json(workSheetWithRowDeleted, { range: newRange }) as unknown as JSON; + + const aux = XLSX.utils.sheet_to_json(worksheet, { range: newRange }) as unknown as MayoresSheet[]; + aux.forEach((element: MayoresSheet) => { + res.push( + { + edad: element['Edad (años)'], + peso: element['Peso (Kg)'], + talla: element['Talla (cm)'], + }, + ); + }); + return res; +}; + +const parseMenLessThanAYear = (worksheet: XLSX.WorkSheet): Menores[] => { + const res: Menores[] = []; + const aux = XLSX.utils.sheet_to_json(worksheet) as unknown as MenoresSheet[]; + aux.forEach((element: MenoresSheet) => { + res.push( + { + edad: element['Edad (meses)'], + peso: element['Peso (Kg)'], + }, + ); + }); + return res; +}; + +const parseWomenLessThanAYear = (worksheet: XLSX.WorkSheet): Menores[] => { + const res: Menores[] = []; + const aux = XLSX.utils.sheet_to_json(worksheet) as unknown as MenoresSheet[]; + aux.forEach((element: MenoresSheet) => { + res.push( + { + edad: element['Edad (meses)'], + peso: element['Peso (Kg)'], + }, + ); + }); + return res; +}; + +/* EXPORT FUNCTIONS */ + +const parseSheetService = (data: Buffer): SheetParserResponse => { + const workbook: XLSX.WorkBook = XLSX.read(data); + let parsed: SheetParserResponse = null; + let hombresMenores: Menores[] = []; + let hombres: Mayores[] = []; + let mujeresMenores: Menores[] = []; + let mujeres: Mayores[] = []; + + const sheetNames: string[] = workbook.SheetNames; + // Check there are 4 sheets, no more, no less + if (sheetNames.length !== 4) { + throw new Error('File does not respect scheme, there are more or less than 4 sheets'); + } + sheetNames.forEach((name) => { + const worksheet: XLSX.WorkSheet = workbook.Sheets[name]; + switch (name) { + case 'Hombres<1': + hombresMenores = parseMenLessThanAYear(worksheet); + break; + case 'Hombres': + hombres = parseMen(worksheet); + break; + case 'Mujeres<1': + mujeresMenores = parseWomenLessThanAYear(worksheet); + break; + case 'Mujeres': + mujeres = parseWomen(worksheet); + break; + + default: + throw new Error(`Sheet name ${name} is not part of the scheme `); + } + }); + parsed = { + hombresMenores, + hombres, + mujeresMenores, + mujeres, + }; return parsed; // TODO: depends on sheet layout what to do diff --git a/src/Services/test.xlsx b/src/Services/test.xlsx index b667311d3984b4b12e566d04533cd3c294f50c94..9fef8e5821051fe4270710bcec7daf0e25d1894a 100644 Binary files a/src/Services/test.xlsx and b/src/Services/test.xlsx differ