wordxml-builder
Version:
Librería TypeScript para construir documentos XML compatibles con Microsoft Word
220 lines (219 loc) • 8.12 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TableBuilder = void 0;
const paragraph_1 = require("./paragraph");
/**
* Clase para construir tablas en formato XML compatible con Word
*/
class TableBuilder {
/**
* Crea una nueva instancia de TableBuilder
* @param table - Estructura de la tabla a construir
*/
constructor(table) {
this.table = table;
}
/**
* Genera el XML de la tabla
* @returns XML de la tabla como string
*/
toXML() {
const tableStyle = this.generateTableStyle();
const grid = this.generateGrid();
const headers = this.generateHeaders();
const rows = this.generateRows();
return `<w:tbl>${tableStyle}${grid}${headers}${rows}</w:tbl>`;
}
/**
* Genera el XML de los estilos de la tabla
* @returns XML de los estilos
*/
generateTableStyle() {
if (!this.table.style)
return '';
const style = this.table.style;
let styleXml = '<w:tblPr>';
// Ancho de la tabla
if (style.width) {
styleXml += `<w:tblW w:w="${style.width}" w:type="dxa"/>`;
}
// Alineación de la tabla
if (style.alignment) {
styleXml += `<w:jc w:val="${style.alignment}"/>`;
}
// Bordes de la tabla
if (style.borders) {
styleXml += '<w:tblBorders>';
if (style.borders.top) {
styleXml += this.generateBorderXML('top', style.borders.top);
}
if (style.borders.right) {
styleXml += this.generateBorderXML('right', style.borders.right);
}
if (style.borders.bottom) {
styleXml += this.generateBorderXML('bottom', style.borders.bottom);
}
if (style.borders.left) {
styleXml += this.generateBorderXML('left', style.borders.left);
}
if (style.borders.insideH) {
styleXml += this.generateBorderXML('insideH', style.borders.insideH);
}
if (style.borders.insideV) {
styleXml += this.generateBorderXML('insideV', style.borders.insideV);
}
styleXml += '</w:tblBorders>';
}
// Espaciado entre celdas
if (style.cellSpacing !== undefined) {
styleXml += `<w:tblCellSpacing w:w="${style.cellSpacing}" w:type="dxa"/>`;
}
styleXml += '</w:tblPr>';
return styleXml;
}
/**
* Genera el XML de la cuadrícula de la tabla
* @returns XML de la cuadrícula
*/
generateGrid() {
var _a;
const columnCount = this.table.headers.length;
let gridXml = '<w:tblGrid>';
// Distribuir el ancho total entre las columnas
const columnWidth = ((_a = this.table.style) === null || _a === void 0 ? void 0 : _a.width) ? Math.floor(this.table.style.width / columnCount) : 1000;
for (let i = 0; i < columnCount; i++) {
gridXml += `<w:gridCol w:w="${columnWidth}"/>`;
}
gridXml += '</w:tblGrid>';
return gridXml;
}
/**
* Genera el XML de los encabezados superiores
* @returns XML de los encabezados
*/
generateHeaders() {
let headersXml = '<w:tr>';
// Agregar celda vacía si hay cabeceras laterales
if (this.table.leftHeaders && this.table.leftHeaders.length > 0) {
headersXml += '<w:tc><w:p/></w:tc>';
}
this.table.headers.forEach(header => {
var _a;
const cellStyle = header.style || ((_a = this.table.style) === null || _a === void 0 ? void 0 : _a.headerCellStyle);
headersXml += this.generateCell(header, cellStyle);
});
headersXml += '</w:tr>';
return headersXml;
}
/**
* Genera el XML de las filas
* @returns XML de las filas
*/
generateRows() {
let rowsXml = '';
this.table.rows.forEach((row, rowIndex) => {
var _a, _b;
rowsXml += '<w:tr>';
// Agregar cabecera lateral si existe
if (this.table.leftHeaders && this.table.leftHeaders[rowIndex]) {
const leftHeaderStyle = this.table.leftHeaders[rowIndex].style ||
((_a = this.table.style) === null || _a === void 0 ? void 0 : _a.leftHeaderCellStyle) ||
((_b = this.table.style) === null || _b === void 0 ? void 0 : _b.headerCellStyle);
rowsXml += this.generateCell(this.table.leftHeaders[rowIndex], leftHeaderStyle);
}
row.cells.forEach(cell => {
var _a, _b;
const cellStyle = cell.style || ((_a = row.style) === null || _a === void 0 ? void 0 : _a.cellStyle) || ((_b = this.table.style) === null || _b === void 0 ? void 0 : _b.cellStyle);
rowsXml += this.generateCell(cell, cellStyle);
});
rowsXml += '</w:tr>';
});
return rowsXml;
}
/**
* Genera el XML de una celda
* @param cell - Celda a generar
* @param style - Estilo de la celda
* @returns XML de la celda
*/
generateCell(cell, style) {
let cellXml = '<w:tc>';
// Estilos de la celda
if (style) {
cellXml += this.generateCellStyle(style);
}
// Contenido de la celda
const paragraph = new paragraph_1.Paragraph(cell.content, style === null || style === void 0 ? void 0 : style.paragraphStyle);
cellXml += paragraph.toXML();
cellXml += '</w:tc>';
return cellXml;
}
/**
* Genera el XML de los estilos de una celda
* @param style - Estilo de la celda
* @returns XML de los estilos
*/
generateCellStyle(style) {
let styleXml = '<w:tcPr>';
// Ancho de la celda
if (style.width) {
styleXml += `<w:tcW w:w="${style.width}" w:type="dxa"/>`;
}
// Alineación vertical
if (style.alignment) {
styleXml += `<w:vAlign w:val="${style.alignment}"/>`;
}
// Dirección del texto
if (style.textDirection) {
styleXml += `<w:textDirection w:val="${style.textDirection}"/>`;
}
// Bordes
if (style.borders) {
styleXml += '<w:tcBorders>';
if (style.borders.top) {
styleXml += this.generateBorderXML('top', style.borders.top);
}
if (style.borders.right) {
styleXml += this.generateBorderXML('right', style.borders.right);
}
if (style.borders.bottom) {
styleXml += this.generateBorderXML('bottom', style.borders.bottom);
}
if (style.borders.left) {
styleXml += this.generateBorderXML('left', style.borders.left);
}
styleXml += '</w:tcBorders>';
}
// Sombreado
if (style.shading) {
styleXml += '<w:shd';
styleXml += ` w:fill="${style.shading.fill}"`;
if (style.shading.color) {
styleXml += ` w:color="${style.shading.color}"`;
}
if (style.shading.val) {
styleXml += ` w:val="${style.shading.val}"`;
}
styleXml += '/>';
}
// Combinación de celdas
if (style.verticalMerge) {
styleXml += `<w:vMerge w:val="${style.verticalMerge}"/>`;
}
if (style.horizontalMerge) {
styleXml += `<w:gridSpan w:val="${style.gridSpan || 2}"/>`;
}
styleXml += '</w:tcPr>';
return styleXml;
}
/**
* Genera el XML de un borde
* @param position - Posición del borde
* @param border - Configuración del borde
* @returns XML del borde
*/
generateBorderXML(position, border) {
return `<w:${position} w:val="${border.style}" w:sz="${border.size}" w:color="${border.color}" w:space="${border.space}"/>`;
}
}
exports.TableBuilder = TableBuilder;