JSReports JSReports

Menu
Content
Por KyMAN. Creado a fecha 2022/04/22. Última modificación a fecha 2022/04/22.

JSReports

Este proyecto está orientado a crear Reports (Informes) directamente desde JS cliente desde un navegador. Dichos informes se entiende como resultados de información en texto como PDF, DOC, etc. Así como tablas de datos.

Por KyMAN. Creado a fecha 2022/04/22. Última modificación a fecha 2022/04/22.

Proyecto

El proyecto viene siendo una librería Core que permite, desde un cliente JS (Navegador), junto con sus dependencias, en caso de requerirlo, crear informes en múltiples formatos como PDF y DOC, pasando como formato visual HTML y CSS, así como generación de archivos multiplataforma compatibles con Excel y Calc como es el formato CSV. También se baraja la idea de poder gestionar la descarga de información directa en XML, JSON, etc.

La librería final es la siguiente:

https://jsreports.k3y.pw/ecma/JSReports.ecma.js

Por KyMAN. Creado a fecha 2022/04/22. Última modificación a fecha 2022/04/22.

Proyectos y dependencias

Este proyecto depende de una serie de librerías externas las cuales son:

Por otro lado, hay proyectos desarrollados por KyMAN o en los que KyMAN también participó tales como:

Finalmente, este proyecto es usado en los proyectos:

Por KyMAN. Creado a fecha 2022/04/22. Última modificación a fecha 2022/04/22.

Notas

Notas para no olvidarme del proyecto.

El proyecto se basa en una librería ECMA/JS la cual se llama JSReports como nombre de clase. Hay que crear un objecto JSReports para poder trabajar con ella. En el caso de PDF depende de las librerías:

Para poder empezar a trabajar con esta librería hay que esperar asíncronamente a que termine de cargar mediante un Callback "on_ready"

                    
  • Language js
  • Lines 1
  • Characters 117
(js_reports = new JSReports(/* PARAMETROS DE ENTRADA */)).on_ready(() => console.log("Ya terminó de cargar xD"));
NOTA: La librería requiere de un sitio donde poner componentes de forma temporal a modo de caché. No le vale un DocumentFragment. Si no se le establece se pondrá por defecto BODY.

PDF y DOC

El trabajo con esta librería cara los PDF y DOC es exactamente igual. Hay que llamar a un método llamado "create" el cual permite crear este tipo de documentos. La librería se centra en que crees un HTML4 y CSS2, aunque pueden ser adjuntadas cosas de HTML5 y XHTML, así como algunos parámetros CSS3 y customizados cara cualquier a de las dos plataformas. La idea es construir plantillas para cabeceras, pies y cuerpos en HTML y una única hoja de estilos general en CSS, lo que cubriría el 99% del informe, luego hay ciertos parámetros que son necesarios establecer mediante valores.

Con esta información tenemos como parámetros de entrada un único valor que vendrá siendo un diccionario el cual tiene los siguientes elementos:

NOTA: Todas las medidas se toma en mm (Milímetros).
  • header: Cabecera HTML.
  • body: Cuerpo HTML.
  • footer: Pié HTML.
  • css: Estilos CSS.
  • type: Extensión que determina si es "doc" o "pdf".
  • margin: Margen general para cualquier lado.
  • margin_top: Margen superior.
  • margin_right: Margen derecho.
  • margin_bottom: Margen inferior.
  • margin_left: Margen izquierdo.
  • variables: Variables para cubrir dentro de los HTML.
  • header_height: Alto de la cabecera.
  • footer_height: Alto del pié.
  • margin_header: Margen de la cabecera.
  • margin_footer: Margen del pié.
  • dpi: DPI para marcar tamaños digitales en PX.
  • page_format: Formato de página (A4, A3, A5, C5, Letter (L), etc.); o tamaño (alto y ancho).

El formato PDF requiere de embedar las fuentes con las que se vaya a trabajar en formato TTF, que es el formato por defecto cara los OS. Dicho formato requiere de un archivo por estilo (Regular o normal, Light, Bold, Italic, etc). Para embedar fuentes es necesario cubrir la variable "fonts" en el diccionario de parámetros de entrada del objeto y se compone de un Array bidimensional donde el primer nivel es conjunto de fuentes y el segundo se compone de:

  1. Nombre de la fuente.
  2. Link del estilo.
  3. Nombre del estilo.

En ambos casos, las imágenes se embedarán mediante URI Base64, pasando a formar parte del documento. Las imágenes, por defecto, suelen estar protegidas por CORS. Para saltarse dicha restricción es importante hacer uso de un Proxy. Para establecer el Proxy hemos de establecer el parámetro global "proxy" que vendrá siendo una URL contra el Proxy donde la variable String "{url}" determinará donde colocar la URL de la imagen.

                    
  • Language js
  • Lines 3
  • Characters 137
js_reports = new JSReports({ proxy : "https://proxycors.local/api/DHkwPBhzp78Gz8g3BmG4VFnDgnt5kU9J6XQPjWMGDKwjr6s3f9nV7545B/{url}" })
NOTA: Si el Proxy no retorna las cabeceras del CORS, éste no servirá de nada. Se puede hacer uso del proyecto ProxyCORS, proyecto en el que está basado el ejemplo también desarrollado por KyMAN. El Git del proyecto es https://git.k3y.pw/KyMAN/ProxyCORS.
IMPORTANTE: El link del ProxyCORS posiblemente no funcione por el hecho de que con dicho Hash podrían usar mi servidor como salto anónimo para saltarse el CORS entre otros fines por lo que el Hash quede deshabilitado.

También se le pueden agregar componentes especiales al documento como tablas o listas programas directamente como objetos o Arrays a partir de un objeto que determina su tipo y el contenido del mismo. A continuación se titularán los tipos de objetos especiales que hay actualmente.

Tablas (Grids)

Los documentos DOC y PDF permiten la generación de tablas dinámicas a partir de la idea de un Grid, es decir, un objeto que determina la cabecera y los datos y automáticamente, el programa embedará una tabla con dichos datos. La estructura del objeto es la siguiente:

  • type: Tipo (puede ser "table" o "grid").
  • header : Array de textos, cada uno será la cabecera de esa columna concreta.
  • body: Cuerpo de la tabla o datos. Array bidimensional con los valores por cada tupla y columna.

Un ejemplo de una tabla puede ser el siguiente:

                    
  • Language js
  • Lines 14
  • Characters 622
const table = { type : "table", header : ["Cabecera 1", "Cabecera 2", "Cabecera 3", "...", "Cabecera N"], body : [ ["Valor 1", "Valor 2", "Valor 3", "...", "Valor N"], ["Valor 1", "Valor 2", "Valor 3", "...", "Valor N"], ["Valor 1", "Valor 2", "Valor 3", "...", "Valor N"], ["Valor 1", "Valor 2", "Valor 3", "...", "Valor N"], ["Valor 1", "Valor 2", "Valor 3", "...", "Valor N"], ["Valor 1", "Valor 2", "Valor 3", "...", "Valor N"], ["Valor 1", "Valor 2", "Valor 3", "...", "Valor N"], ["Valor 1", "Valor 2", "Valor 3", "...", "Valor N"] ] };

Listas

Los documentos DOC y PDF permiten la generación de listas dinámicas a partir de un Array el cual puede anidar otros Array para hacer Listas de múltiples niveles. Admiten tantos listas ordenadas como desordenadas, y su estructura es la siguiente:

  • type: Tipo (Siempre será "list"),
  • mode: El modo en que se mostrarán los datos. Éste puede ser:
    • ol o ordered: Para mostrar los datos con un valor que representa su posición autoincremental.
    • ul o unordered: Para mostrar los datos con puntos, guiones o como se establezca por CSS.
  • start: Para los elementos ordenados autoincrementalmente, valor numérico de inicio.
  • items: Array de elementos ordenados. Puede contener objetos que anidan otras listas.

Un ejemplo de una tabla puede ser el siguiente:

                    
  • Language js
  • Lines 25
  • Characters 479
const list = { type : "list", mode : "ordered", start : 12, items : [ "cosa 1", "cosa 2", "cosa 3", "...", ["jojo", { mode : "unordered", items : [ "pasa A", ["pasa B", { items : [ "otro xD" ] }], "pasa C" ] }], "juas", "jiji" ] };
Por KyMAN. Creado a fecha 2022/04/22. Última modificación a fecha 2022/04/22.

Bugs

En esta sección se catalogarán todos los Bugs y el estado conforme a si están o no arreglados o si se están tratando.

Cabeceras y pies dispares en UDF

Las cabeceras y pies de página salen en las páginas impares en UDF. El problema recae principalmente en que los etiquetados y marcas de MS no son compatibles con las de UDF, siendo para UDF el 'title="header"' para la cabecera y el 'title="footer"' para el pie; mientras que en MS sería el atributo Style "mso-element:header;" para la cabecera y "mso-elemento:footer;" para el pie. Está globalizado, pero el método UDF sólo muestra las cabeceras y los pies en las páginas impares.

- Arreglar el fallo para que salgan en todas las páginas.

Hay una pseudosolución que aportaron en la respuesta del Link que se muestra a continuación se muestra una pseudosolución (Digo pseudo porque no es una cabecera ni pié real, sino que se usa una tabla que contiene ambas cosas la cual repite su THEAD y su TFOOT en todas las páginas) pero al no ser una cabecera y pié reales no lo establecí, pero decir que en caso de extrema necesidad, ésta puede ser aplicada perfectamente.

https://stackoverflow.com/questions/1360869/how-to-use-html-to-print-header-and-footer-on-every-printed-page-of-a-document#answer-51371081

Problemas cabeceras y piés PDF

El jsPDF no fue diseñado para trabajar en profundidad el HTML de hecho, no es capaz ni de interpretar CSS ni de adjuntar las fuentes de forma autónoma, pero el problema viene a la hora de establecer un elemento HTML pues, aunque establezcas la página donde quieras establecerlo, éste siempre irá a la primera página, y si estableces un margen o posición "top" muy alto, éste desaparece si no es nativo para estar ahí. El HTML se superpondrá a lo que ya hay en el documento y no permite establecer márgenes diferentes a distintos HTML, por lo que el tema de las cabeceras queda totalmente descartado mediante HTML nativo.

  • Conseguir un sistema que permita generar cabeceras y piés de página contra HTML y CSS.
  • Probar el sistema de impresión HTML de CSS para establecer una tabla que por página repita su THEAD y su TFOOT, como la trampa para establecer cabeceras que encontré para DOCs.
IMPORTANTE: Actualmente, este sistema funciona pero es a partir de la creación de una imagen contra el HTML y CSS dado lo que impide seleccionar texto entre otros problemas. No me preocupan los sistemas que migran de PDF a DOC por los OCR.
NOTA: Para arreglar este problema se optó por hacer uso de la dependencia del propio jsPDF: html2canvas, y de ahí se extrae una imagen en URI Base64 que es la que se usa para dichos fines.

Problemas con CSS

En los documentos DOC, la etiqueta STYLE que contiene el CSS, tiene órdenes y sentencias muy específicas que no pueden ser flexibilizadas por lo que hay que hacer una adaptación de la misma para que funcionen.

- Crear adaptación para que se generen.

Básicamente se reutilizó el sistema hecho para los PDF.

Corregir tamaños IMG

Las imágenes, en os documentos DOC tienen el problema del valor de atributo "width" y "height" auto, que cogen como valor su ancho o alto, consecutivamente.

- Conseguir proporcionar las imágenes.

Para arreglar dicho fallo se hice un análisis del CSS contra las imágenes en su precarga y establecer un tamaño relativo con respecto al formato de página, tamaño de la misma y el tamaño de la imagen.

Tamaños de tabla

En los DOC, las tablas no hacen caso de los atributos de tamaño de CSS, requiriendo de hacer uso del atributo WIDTH.

Por otro lado, las celdas tampoo hacen caso de su ancho, teniendo que usar la etiqueta COLGROUP y sus subetiquetas COL.

  • Migrar el ancho en CSS al atributo WIDTH de la tabla.
  • Migrar el ancho de las columnas a los COL.
  • Corregir la porcentualidad de los COL.
IMPORTANTE: Los COL, en los DOC UDF ignora la unidad del atributo y no respeta la proporción de peso, quedando sobre una proporción a 50000. Automáticamente lo tramita desde los DPI en medidas por pixel; y por el tamaño de página en mm, cm, in, etc; así como por los propios porcentajes. Creo que es algo que hay que mejorar, pero que para salir del paso llega.

Medidas mm en DOC UDF

Cuando tratabajamos los márgenes CSS de las cabeceras y los pies de página, éstos se establecen en mm de forma forzada aunque le pongas otra unidad de medida.

NOTA: Al ser un atributo CSS especial para MS puede ser que se condicione forzadamente en mm? No hay información a penas acerca de ello.

- Arreglar el Bug, o al menos, adaptarlo para que salga en otras unidades establecidas en CSS.

NOTA: Actualmente está trabajando en mm, de la misma forma que trabaja esta librería.

PDF en Chrome

Por algún motivo, en Chrome no crea el PDF. Queda como totalmente apagado y sin terminar el proceso.

- Arreglar el Bug.

El Bug parece ser que era porque el evento OnLoad del IFRAME que gestiona los html2canvas no existe en Chrome salvo que éste venga con una URL, por lo que se decidió hacer un Timeout para solventar la precarga del objeto.

Por KyMAN. Creado a fecha 2022/04/22. Última modificación a fecha 2022/04/22.

Objetivos

Aquí se pondrán los objetivos del proyecto JSReports.

  • Crear proyecto Git.
  • Crear base del proyecto.
  • Crear el JS.
  • Crear la parte para HTML compacto.
  • Adjuntador de fuentes.
  • Meter todo en el CDN y comentarlo.
  • Añadir cabeceras y pies al PDF.
  • Posibilidad de múltiples cabeceras y pies.
  • Corregir sobreescritura de elementos CSS y el múltiple ";".
  • Montar el cuerpo de los DOC.
  • Montar cabeceras y pies de página.
  • Corregir Bug de tamaños de imagen.
  • Corregir Bug de ancho de tablas.
  • Corregir Bug de ancho de celdas.
  • Compatibilizar OpenDocument con MSDocument.
  • Montar variables de página.
  • Arreglar Bug de márgenes del Footer y el Header.
  • Corregir fuentes embedadas de PDF.
  • /Hasta aquí es compatible con UDF al 100%./
  • Montar VM temporal con el Office 365 para probar resultados y corregir Bugs.
    • Compatibilizar UDF con MS XML.
  • Documentar.
  • Añadir JSReports al WDictionaries.
  • Publicar.
  • Montar CORS.
  • Subir los archivos de dependencias.
  • Arreglar el tester HTML.
  • Elimintar el tester 0 HTML.
  • Corregir Bug del JSReports en Chrome.
Files