Artículo técnico

Exportar hojas de cálculo de Excel a PDF en Delphi sin Office

Para exportar una hoja de cálculo de Excel a PDF desde Delphi o C++Builder sin tener Office instalado, llame a SaveAsPDF en una hoja de cálculo o libro de trabajo de HotXLS. HotXLS es un componente nativo de Excel para VCL, y su exportación de hoja de cálculo a PDF renderiza el rango utilizado de la hoja en un archivo PDF 1.4 independiente, mapeando los anchos de columna de Excel y el texto de visualización de las celdas en páginas A4 con paginación automática de múltiples páginas. Ninguna copia de Excel, controlador de impresora o DLL externa participa en la renderización

HotXLS trata al PDF como un formato de presentación de datos, un equivalente de sus rutas de exportación CSV, TSV y HTML, en lugar de un motor de renderizado con precisión de píxeles. La exportación reproduce el contenido y el diseño de la tabla: los valores que ve en la cuadrícula, las proporciones de las columnas y las líneas de división alrededor de las celdas. Ese enfoque importa porque establece una expectativa honesta desde el principio, y el resto de este artículo trata exactamente sobre los límites de esta funcionalidad

¿Cómo se convierte Excel a PDF en Delphi sin Office?

La ruta más corta es una sola llamada. TXLSWorksheet expone SaveAsPDF(FileName) y SaveAsPDF(Stream), y TXLSWorkbook expone las mismas dos sobrecargas que se redirigen a la hoja activa. Cada una devuelve un valor Integer (1 en caso de éxito y -1 en caso de fallo), de modo que usted puede bifurcar el flujo según el resultado sin tener que envolver la llamada en su propio manejo de excepciones

uses
  lxHandle;

var
  Book: TXLSWorkbook;
begin
  Book := TXLSWorkbook.Create;
  try
    Book.Open('sales-june.xlsx');
    // Render the active sheet's used range straight to report.pdf.
    if Book.SaveAsPDF('report.pdf') = 1 then
      Writeln('PDF written');
  finally
    Book.Free;
  end;
end;

Cuando llama a SaveAsPDF en una hoja de cálculo, HotXLS exporta el UsedRange de esa hoja, que es el cuadro delimitador de cada celda con datos. La sobrecarga del libro de trabajo es una facilidad que delega en la hoja activa, por lo que un reporte de múltiples hojas debe recorrer las hojas que necesita o seleccionar la hoja activa antes de la llamada. No existe un modo de libro completo que procese todo en un solo ciclo concatenando cada pestaña: cada llamada renderiza una hoja o un rango

¿Cómo convierte HotXLS un rango utilizado en páginas PDF?

HotXLS recorre el rango utilizado celda por celda y lo distribuye como una cuadrícula paginada. La geometría de las columnas proviene directamente de Excel: el ancho de cada columna se convierte de la unidad de ancho de Excel a puntos tipográficos, con un límite mínimo para que ninguna columna se reduzca a una línea imperceptible. Cuando el conjunto de las columnas supera el ancho de la página utilizable, HotXLS las escala proporcionalmente para que se ajusten; cuando ya caben, las deja en su ancho natural en lugar de estirarlas a lo largo de la hoja

Luego, las filas descienden por la página hasta que la siguiente cruce el margen inferior, momento en el cual HotXLS abre una nueva página y continúa, por lo que una hoja de mil filas se pagina por sí sola sin que usted tenga que llevar un control de los saltos de página. Cada celda imprime su FormattedText, la cadena de caracteres de visualización producida después de aplicar el formato numérico, de modo que una fecha se muestra tal como aparece en la hoja y una celda de moneda conserva su símbolo y separadores de miles. El texto que excede su columna se recorta al ancho de la celda en lugar de invadir la celda vecina

Control de la orientación, los márgenes y el tamaño de fuente

Para cualquier diseño que difiera del predeterminado, controle el exportador directamente. TXLSPDFExport es la clase que respalda a los asistentes de una sola línea, y publica tres propiedades: Orientation (xlsPdfPortrait o xlsPdfLandscape, vertical por defecto), Margin (puntos, por defecto 40) y FontSize (puntos, por defecto 9). Establézcalos antes de llamar a SaveAsPDF y todo el documento los adoptará

uses
  lxHandle, lxPDF;

var
  Book: TXLSWorkbook;
  Exporter: TXLSPDFExport;
begin
  Book := TXLSWorkbook.Create;
  try
    Book.Open('wide-ledger.xlsx');
    Exporter := TXLSPDFExport.Create;
    try
      Exporter.Orientation := xlsPdfLandscape;  // fit wide sheets on the page
      Exporter.Margin := 28;                     // tighter page margin, in points
      Exporter.FontSize := 8;                    // denser rows
      Exporter.SaveAsPDF(Book.ActiveSheet, 'ledger.pdf');
    finally
      Exporter.Free;
    end;
  finally
    Book.Free;
  end;
end;

TXLSPDFExport también acepta un rango en lugar de una hoja completa a través de SaveAsPDF(Range: IXLSRange; ...), que es cómo se exporta un bloque de resumen de una hoja que también contiene cálculos temporales. Esa sobrecarga de rango es la misma en la que se apoya internamente el asistente de la hoja de cálculo, por lo que el diseño, el escalado y la paginación se comportan de manera idéntica ya sea que le pase un rango utilizado completo o una selección elegida manualmente

var
  Book: TXLSWorkbook;
  Exporter: TXLSPDFExport;
  Summary: IXLSRange;
begin
  Book := TXLSWorkbook.Create;
  try
    Book.Open('quarter.xlsx');
    // Export only the summary block, not the scratch columns beside it.
    Summary := Book.Sheets[1].Range['A1', 'F20'];
    Exporter := TXLSPDFExport.Create;
    try
      Exporter.SaveAsPDF(Summary, 'summary.pdf');
    finally
      Exporter.Free;
    end;
  finally
    Book.Free;
  end;
end;

Por qué HotXLS no incrusta fuentes: el compromiso de Helvetica y WinAnsi

HotXLS escribe el texto con la fuente Helvetica integrada de PDF y la codificación WinAnsiEncoding, una elección deliberada de cero dependencias con un límite real. Debido a que Helvetica es una de las 14 fuentes estándar que cualquier lector de PDF compatible ya incluye, el exportador no incrusta ningún programa de fuente en absoluto: el archivo se mantiene pequeño y se abre en cualquier lugar, sin nada que licenciar o enviar junto con él. El costo de esa elección es el repertorio de caracteres que la página puede mostrar

WinAnsiEncoding cubre el conjunto Windows-1252, por lo que el texto en alfabeto latino, la puntuación común y los acentos habituales de Europa occidental se renderizan correctamente, y HotXLS incluye un puñado de caracteres tipográficos (comillas invertidas, guiones en y em, y el símbolo del euro) en sus posiciones de CP1252. Los caracteres fuera de ese rango (ideogramas CJK, cirílico, griego y árabe) se reducen a un signo de interrogación en la página. Si sus hojas contienen texto no latino, este exportador es la herramienta incorrecta, y un renderizador de PDF con estilo completo es la solución adecuada

Dónde se detiene la exportación de hoja de cálculo a PDF

HotXLS renderiza el contenido y la estructura, no el estilo visual completo de la hoja. Los rellenos de celda, los estilos de borde por borde, las fuentes y colores por celda, los gráficos y las imágenes incrustadas quedan fuera de lo que dibuja el exportador; lo que obtiene es la cuadrícula de texto con líneas de división uniformes. Ese es el mismo contrato que respetan los exportadores de HTML y RTF, y es el adecuado para un reporte o una transferencia de datos donde los números llevan el significado y el tema visual no importa

Cuando el objetivo es un documento con estilo y coherente con la marca, el patrón habitual consiste en organizar primero los números en una plantilla de hoja de cálculo, lo cual cubre en profundidad el flujo de trabajo de generación de reportes basado en plantillas. Y debido a que nada de esto requiere COM ni una instancia de Excel en ejecución, el flujo se adapta al mismo modelo de automatización sin Office que HotXLS utiliza en todo momento: Pascal puro, desplegable en un servidor sin interfaz gráfica, sin interoperabilidad que licenciar o supervisar

El PDF independiente, byte por byte

HotXLS construye la estructura del archivo PDF a mano y calcula su tabla de referencias cruzadas a partir de desplazamientos exactos de bytes, lo cual es la razón por la que la salida se abre en cualquier lector. A medida que serializa cada objeto, HotXLS registra el desplazamiento inicial de ese objeto antes de añadir sus bytes, luego avanza la posición actual según la longitud que acaba de escribir, de modo que la tabla xref se ubica precisamente en cada objeto y startxref marca dónde comienza esa tabla. Un lector que encuentre esos desplazamientos movidos aunque sea por un solo byte rechaza todo el archivo, lo que hace del desplazamiento autocalculado el contrato fundamental del exportador

Ese contrato conlleva una consecuencia estricta que vale la pena conocer. El nodo Pages se escribe primero como el objeto 1, pero su lista de páginas secundarias no se conoce sino hasta que se emiten todas las páginas, por lo que HotXLS lo reserva como un marcador de posición e inserta las páginas finales y el conteo antes de que se ejecute la pasada de desplazamientos, nunca después. Una vez que los bytes de un objeto se miden para la tabla xref, se congelan: cambiar un solo byte después desplazaría cada desplazamiento siguiente y dañaría la tabla. Es una pequeña disciplina que permite obtener un PDF 1.4 válido según los estándares sin ninguna biblioteca adicional subyacente

Los métodos SaveAsPDF y la clase TXLSPDFExport mostrados aquí se distribuyen con el HotXLS Delphi Excel Component, junto con los exportadores CSV, HTML y RTF, y la API completa de hojas de cálculo para Delphi y C++Builder