fix: exportar Excel como SpreadsheetML (.xls) en vez de CSV

Abre directamente en Excel con columnas formateadas, sin asistente
de importación ni apertura en VS Code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-07-24 10:02:12 -05:00
co-authored by Claude Sonnet 4.6
parent dc5fd6e272
commit 5400fd9b32
2 changed files with 23 additions and 13 deletions
+9 -3
View File
@@ -1614,10 +1614,16 @@ async function ffExportarExcel() {
...fieldCols.map(([l,d])=>{ const v=todos[lmap.get(l)||d]; return v==null?'':(Array.isArray(v)?v.join('; '):String(v)); }),
]);
});
const csv = '\uFEFF' + csvRows.map(r=>r.map(v=>'"'+String(v).replace(/"/g,'""')+'"').join(',')).join('\r\n');
const blob = new Blob([csv],{type:'text/csv;charset=utf-8;'});
const xlsEsc = v => String(v).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
const toCell = v => `<Cell><Data ss:Type="String">${xlsEsc(v)}</Data></Cell>`;
const xml = `<?xml version="1.0" encoding="UTF-8"?>\n<?mso-application progid="Excel.Sheet"?>\n`
+ `<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">`
+ `<Worksheet ss:Name="Domicilios"><Table>\n`
+ csvRows.map(r => `<Row>${r.map(toCell).join('')}</Row>`).join('\n')
+ `\n</Table></Worksheet></Workbook>`;
const blob = new Blob([xml], {type:'application/vnd.ms-excel;charset=utf-8'});
const url = URL.createObjectURL(blob);
const a = Object.assign(document.createElement('a'),{href:url,download:'formularios_domicilios_'+new Date().toISOString().slice(0,10)+'.csv'});
const a = Object.assign(document.createElement('a'),{href:url,download:'formularios_domicilios_'+new Date().toISOString().slice(0,10)+'.xls'});
document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
mostrarToast('✅ Excel descargado — ' + rows.length + ' registro(s)', 'success');
}
+14 -10
View File
@@ -35,7 +35,7 @@ if ($tipo) {
ORDER BY o.created_at DESC",
[$desde, $hasta]
);
$filename = "ordenes_$desde\_$hasta.csv";
$filename = "ordenes_$desde\_$hasta.xls";
$headers = ['ID','Paciente','Documento','EPS','Estado','Médico','Fecha Orden','Exámenes','Ayuno','H.Ayuno','Creada','Revisada por','Autorizada por'];
break;
@@ -109,7 +109,7 @@ if ($tipo) {
$sqlParams
);
$rangoLabel = !empty($_GET['fecha']) ? $_GET['fecha'] : "{$desde}_{$hasta}";
$filename = "domicilios_{$rangoLabel}.csv";
$filename = "domicilios_{$rangoLabel}.xls";
$headers = [
'ID','Paciente','Documento','Teléfono','EPS',
'Fecha','Hora programada','Hora llegada','Hora salida','Duración',
@@ -133,7 +133,7 @@ if ($tipo) {
ORDER BY p.nombre_completo",
[]
);
$filename = "pacientes_" . date('Y-m-d') . ".csv";
$filename = "pacientes_" . date('Y-m-d') . ".xls";
$headers = ['ID','Nombre','Tipo Doc.','Documento','Teléfono','Email','EPS','Ciudad','Barrio','Activo','Total Órdenes','Registrado'];
break;
@@ -191,7 +191,7 @@ if ($tipo) {
ORDER BY d.fecha_programada ASC, d.id ASC",
$pParams
);
$filename = "reporte_pagos_{$rangoNombre}.csv";
$filename = "reporte_pagos_{$rangoNombre}.xls";
$headers = [
'ID','Fecha programada','Fecha pago','Paciente','Documento',
'Enfermero/a','Tipo cliente','Seguro','Estado domicilio',
@@ -204,17 +204,21 @@ if ($tipo) {
exit('Tipo de exportación no válido');
}
header('Content-Type: text/csv; charset=utf-8');
header('Content-Type: application/vnd.ms-excel; charset=utf-8');
header("Content-Disposition: attachment; filename=\"$filename\"");
header('Pragma: no-cache');
$f = fopen('php://output', 'w');
fputs($f, "\xEF\xBB\xBF"); // BOM UTF-8 para Excel
fputcsv($f, $headers);
$esc = fn($v) => htmlspecialchars((string)$v, ENT_XML1, 'UTF-8');
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
echo '<?mso-application progid="Excel.Sheet"?>' . "\n";
echo '<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"' . "\n";
echo ' xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">' . "\n";
echo '<Worksheet ss:Name="Reporte"><Table>' . "\n";
echo '<Row>' . implode('', array_map(fn($h) => '<Cell><Data ss:Type="String">' . $esc($h) . '</Data></Cell>', $headers)) . '</Row>' . "\n";
foreach ($rows as $row) {
fputcsv($f, array_values($row));
echo '<Row>' . implode('', array_map(fn($v) => '<Cell><Data ss:Type="String">' . $esc($v) . '</Data></Cell>', array_values($row))) . '</Row>' . "\n";
}
fclose($f);
echo '</Table></Worksheet></Workbook>';
exit;
}