|
|
@@ -336,48 +336,46 @@ private processExcelDataForCurrentSheet(): void {
|
|
|
}
|
|
|
|
|
|
|
|
|
- private getSheetDataAsMatrix(worksheet: XLSX.WorkSheet): any[][] {
|
|
|
+private getSheetDataAsMatrix(worksheet: XLSX.WorkSheet): any[][] {
|
|
|
if (!worksheet['!ref']) return [[]];
|
|
|
|
|
|
const range = XLSX.utils.decode_range(worksheet['!ref']);
|
|
|
-
|
|
|
- // GUARDAR el rango original para preservar estructura
|
|
|
- const sheetName = this.selectedSheet;
|
|
|
- if (sheetName && !this.originalSheetRanges[sheetName]) {
|
|
|
- this.originalSheetRanges[sheetName] = range;
|
|
|
- }
|
|
|
-
|
|
|
const data: any[][] = [];
|
|
|
|
|
|
- // CAMBIO CLAVE: Empezar desde row 0 y column 0, pero preservar celdas vacías
|
|
|
+ // Preservar estructura completa
|
|
|
for (let rowNum = 0; rowNum <= range.e.r; rowNum++) {
|
|
|
- const row: any[] = [];
|
|
|
-
|
|
|
- // CAMBIO CLAVE: Empezar desde column 0 para preservar estructura
|
|
|
- for (let colNum = 0; colNum <= range.e.c; colNum++) {
|
|
|
- const cellAddress = XLSX.utils.encode_cell({ r: rowNum, c: colNum });
|
|
|
- const cell = worksheet[cellAddress];
|
|
|
-
|
|
|
- // Usar valor formateado (w) si está disponible, de lo contrario el valor (v)
|
|
|
- let value = cell ? (cell.w !== undefined ? cell.w : cell.v) : '';
|
|
|
+ const row: any[] = [];
|
|
|
|
|
|
- // Formatear fechas
|
|
|
- if (cell && cell.t === 'd' && value instanceof Date) {
|
|
|
- value = this.formatDate(value);
|
|
|
- }
|
|
|
-
|
|
|
- // CAMBIO: Si no hay celda y estamos antes del rango original, mantener vacío
|
|
|
- if (!cell && (rowNum < range.s.r || colNum < range.s.c)) {
|
|
|
- value = '';
|
|
|
+ for (let colNum = 0; colNum <= range.e.c; colNum++) {
|
|
|
+ const cellAddress = XLSX.utils.encode_cell({ r: rowNum, c: colNum });
|
|
|
+ const cell = worksheet[cellAddress];
|
|
|
+
|
|
|
+ // Conservar estilos para celdas vacías
|
|
|
+ if (!cell) {
|
|
|
+ row.push('');
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Usar valor formateado (w) si está disponible
|
|
|
+ let value = cell.w !== undefined ? cell.w : cell.v;
|
|
|
+
|
|
|
+ // Formatear fechas
|
|
|
+ if (cell.t === 'd' && value instanceof Date) {
|
|
|
+ value = this.formatDate(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Manejar números como fechas de Excel
|
|
|
+ if (typeof value === 'number' && this.isExcelDate(value)) {
|
|
|
+ value = this.excelDateToJSDate(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ row.push(value || '');
|
|
|
}
|
|
|
-
|
|
|
- row.push(value);
|
|
|
- }
|
|
|
- data.push(row);
|
|
|
+ data.push(row);
|
|
|
}
|
|
|
|
|
|
return data;
|
|
|
- }
|
|
|
+}
|
|
|
|
|
|
private formatDate(date: Date): string {
|
|
|
const day = date.getDate().toString().padStart(2, '0');
|
|
|
@@ -821,36 +819,44 @@ public discardChanges(): void {
|
|
|
// 1. Restaurar datos originales
|
|
|
this.data.sheets = JSON.parse(JSON.stringify(this.originalData));
|
|
|
|
|
|
- // 2. Reiniciar caches
|
|
|
- this.cargaMapCache = {};
|
|
|
- this.lruMapCache = {};
|
|
|
-
|
|
|
- // 3. Reinicializar workbooks
|
|
|
- this.initializeWorkbook();
|
|
|
+ // 2. Restaurar workbook modificado desde el original
|
|
|
+ if (this.originalWorkbook) {
|
|
|
+ this.modifiedWorkbook = this.cloneWorkbook(this.originalWorkbook);
|
|
|
+ }
|
|
|
|
|
|
- // 4. Resetear datos modificados
|
|
|
+ // 3. Resetear datos modificados
|
|
|
this.sheetNames.forEach(sheet => {
|
|
|
- this.modifiedSheetsData[sheet] = [...this.data.sheets[sheet]];
|
|
|
+ if (this.originalWorkbook?.Sheets[sheet]) {
|
|
|
+ this.modifiedSheetsData[sheet] = this.getSheetDataAsMatrix(this.originalWorkbook.Sheets[sheet]);
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
- // 5. Recargar hoja actual
|
|
|
- this.loadSheetData();
|
|
|
+ // 4. Reiniciar caches
|
|
|
+ this.cargaMapCache = {};
|
|
|
+ this.lruMapCache = {};
|
|
|
|
|
|
- // 6. Forzar actualización visual
|
|
|
- this.cdr.detectChanges();
|
|
|
+ // 5. Forzar regeneración de IDs
|
|
|
+ this.needsRegenerateIds = true;
|
|
|
+ this.processExcelData(); // Regenerar IDs inmediatamente
|
|
|
+
|
|
|
+ // 6. Recargar hoja actual
|
|
|
+ this.loadSheetData();
|
|
|
|
|
|
// 7. Restablecer banderas
|
|
|
this.hasUnsavedChanges = false;
|
|
|
this.editMode = false;
|
|
|
this.activeEditCell = null;
|
|
|
|
|
|
+ // 8. Forzar actualización visual completa
|
|
|
+ this.cdr.detectChanges();
|
|
|
+
|
|
|
this._resourcesService?.openSnackBar('Cambios descartados correctamente');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
trackByRowData(index: number, row: any[]): string {
|
|
|
- // Generar un hash único basado en el contenido de la fila
|
|
|
- return row.map(cell => cell?.toString() || '').join('|') + '|' + index;
|
|
|
+ // Usar contenido de la fila + bandera de regeneración para forzar actualización
|
|
|
+ return row.join('|') + '|' + this.needsRegenerateIds;
|
|
|
}
|
|
|
|
|
|
addRow(): void {
|
|
|
@@ -1125,7 +1131,8 @@ private validateWithExistingFileId(idArchivo: string): void {
|
|
|
const body = {
|
|
|
id_user: this.data.userId || localStorage.getItem('idusuario'),
|
|
|
id_file: idArchivo,
|
|
|
- linea: parseInt(this.data.linea?.toString() || '1')
|
|
|
+ linea: parseInt(this.data.linea?.toString() || '1'),
|
|
|
+ auto_transfer: true
|
|
|
};
|
|
|
|
|
|
console.log('🔍 Iniciando validación con archivo:', body);
|