2018-02-02 01:56:08 +00:00
|
|
|
import { IXmlableObject, XmlComponent } from "file/xml-components";
|
2017-09-19 15:49:27 +01:00
|
|
|
import { Paragraph } from "../paragraph";
|
|
|
|
import { TableGrid } from "./grid";
|
|
|
|
import { TableProperties, WidthTypes } from "./properties";
|
2018-05-04 15:56:28 +02:00
|
|
|
import { TableCellBorders, GridSpan, VMerge, VMergeType, VerticalAlign, VAlign, TableCellWidth, WidthType } from "file/table/table-cell";
|
2017-09-19 15:49:27 +01:00
|
|
|
|
|
|
|
export class Table extends XmlComponent {
|
2018-01-29 01:55:25 +00:00
|
|
|
private readonly properties: TableProperties;
|
|
|
|
private readonly rows: TableRow[];
|
|
|
|
private readonly grid: TableGrid;
|
2017-09-19 15:49:27 +01:00
|
|
|
|
2018-04-26 14:16:02 +02:00
|
|
|
constructor(rows: number, cols: number, colSizes?: number[]) {
|
2017-09-19 15:49:27 +01:00
|
|
|
super("w:tbl");
|
|
|
|
this.properties = new TableProperties();
|
|
|
|
this.root.push(this.properties);
|
2018-03-22 23:04:46 +00:00
|
|
|
this.properties.setBorder();
|
2017-09-19 15:49:27 +01:00
|
|
|
|
2018-04-26 14:16:02 +02:00
|
|
|
if (colSizes && colSizes.length > 0) {
|
|
|
|
this.grid = new TableGrid(colSizes);
|
|
|
|
} else {
|
|
|
|
const gridCols: number[] = [];
|
|
|
|
for (let i = 0; i < cols; i++) {
|
|
|
|
/*
|
|
|
|
0-width columns don't get rendered correctly, so we need
|
|
|
|
to give them some value. A reasonable default would be
|
|
|
|
~6in / numCols, but if we do that it becomes very hard
|
|
|
|
to resize the table using setWidth, unless the layout
|
|
|
|
algorithm is set to 'fixed'. Instead, the approach here
|
|
|
|
means even in 'auto' layout, setting a width on the
|
|
|
|
table will make it look reasonable, as the layout
|
|
|
|
algorithm will expand columns to fit its content
|
|
|
|
*/
|
|
|
|
gridCols.push(1);
|
|
|
|
}
|
|
|
|
this.grid = new TableGrid(gridCols);
|
2017-09-19 15:49:27 +01:00
|
|
|
}
|
2018-04-26 14:16:02 +02:00
|
|
|
|
2017-09-19 15:49:27 +01:00
|
|
|
this.root.push(this.grid);
|
|
|
|
|
|
|
|
this.rows = [];
|
|
|
|
for (let i = 0; i < rows; i++) {
|
|
|
|
const cells: TableCell[] = [];
|
|
|
|
for (let j = 0; j < cols; j++) {
|
|
|
|
cells.push(new TableCell());
|
|
|
|
}
|
|
|
|
const row = new TableRow(cells);
|
|
|
|
this.rows.push(row);
|
|
|
|
this.root.push(row);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public getRow(ix: number): TableRow {
|
|
|
|
return this.rows[ix];
|
|
|
|
}
|
|
|
|
|
|
|
|
public getCell(row: number, col: number): TableCell {
|
|
|
|
return this.getRow(row).getCell(col);
|
|
|
|
}
|
|
|
|
|
|
|
|
public setWidth(type: WidthTypes, width: number | string): Table {
|
|
|
|
this.properties.setWidth(type, width);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public fixedWidthLayout(): Table {
|
|
|
|
this.properties.fixedWidthLayout();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class TableRow extends XmlComponent {
|
2018-01-29 01:55:25 +00:00
|
|
|
private readonly properties: TableRowProperties;
|
2017-09-19 15:49:27 +01:00
|
|
|
|
2018-01-29 01:55:25 +00:00
|
|
|
constructor(private readonly cells: TableCell[]) {
|
2017-09-19 15:49:27 +01:00
|
|
|
super("w:tr");
|
|
|
|
this.properties = new TableRowProperties();
|
|
|
|
this.root.push(this.properties);
|
|
|
|
cells.forEach((c) => this.root.push(c));
|
|
|
|
}
|
|
|
|
|
|
|
|
public getCell(ix: number): TableCell {
|
|
|
|
return this.cells[ix];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class TableRowProperties extends XmlComponent {
|
|
|
|
constructor() {
|
|
|
|
super("w:trPr");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class TableCell extends XmlComponent {
|
2018-01-29 01:55:25 +00:00
|
|
|
private readonly properties: TableCellProperties;
|
2017-09-19 15:49:27 +01:00
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super("w:tc");
|
|
|
|
this.properties = new TableCellProperties();
|
|
|
|
this.root.push(this.properties);
|
|
|
|
}
|
|
|
|
|
|
|
|
public addContent(content: Paragraph | Table): TableCell {
|
|
|
|
this.root.push(content);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public prepForXml(): IXmlableObject {
|
|
|
|
// Cells must end with a paragraph
|
|
|
|
const retval = super.prepForXml();
|
|
|
|
const content = retval["w:tc"];
|
|
|
|
if (!content[content.length - 1]["w:p"]) {
|
|
|
|
content.push(new Paragraph().prepForXml());
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
public createParagraph(text?: string): Paragraph {
|
|
|
|
const para = new Paragraph(text);
|
|
|
|
this.addContent(para);
|
|
|
|
return para;
|
|
|
|
}
|
2018-04-26 14:16:02 +02:00
|
|
|
|
|
|
|
get cellProperties() {
|
|
|
|
return this.properties;
|
|
|
|
}
|
2017-09-19 15:49:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export class TableCellProperties extends XmlComponent {
|
2018-05-04 15:56:28 +02:00
|
|
|
private cellBorder: TableCellBorders;
|
2017-09-19 15:49:27 +01:00
|
|
|
constructor() {
|
|
|
|
super("w:tcPr");
|
2018-05-04 15:56:28 +02:00
|
|
|
this.cellBorder = new TableCellBorders();
|
|
|
|
this.root.push(this.cellBorder);
|
|
|
|
}
|
|
|
|
|
|
|
|
get borders() {
|
|
|
|
return this.cellBorder;
|
|
|
|
}
|
|
|
|
addGridSpan(cellSpan: number) {
|
|
|
|
this.root.push(new GridSpan(cellSpan));
|
|
|
|
}
|
|
|
|
|
|
|
|
addVerticalMerge(type: VMergeType) {
|
|
|
|
this.root.push(new VMerge(type));
|
|
|
|
}
|
|
|
|
|
|
|
|
setVerticalAlign(vAlignType: VerticalAlign) {
|
|
|
|
this.root.push(new VAlign(vAlignType));
|
|
|
|
}
|
|
|
|
|
|
|
|
setWidth(width: string | number, type: WidthType) {
|
|
|
|
this.root.push(new TableCellWidth(width, type));
|
2017-09-19 15:49:27 +01:00
|
|
|
}
|
|
|
|
}
|