Files
docx-js/src/file/table/table.ts

99 lines
3.7 KiB
TypeScript
Raw Normal View History

2018-09-12 21:01:52 +01:00
// http://officeopenxml.com/WPtableGrid.php
2023-01-23 14:14:05 +00:00
import { FileChild } from "@file/file-child";
2019-11-24 01:22:17 +00:00
import { AlignmentType } from "../paragraph";
2017-09-19 15:49:27 +01:00
import { TableGrid } from "./grid";
import { TableCell, VerticalMergeType } from "./table-cell";
2019-11-18 01:04:31 +00:00
import { ITableBordersOptions, ITableFloatOptions, TableProperties } from "./table-properties";
import { ITableCellMarginOptions } from "./table-properties/table-cell-margin";
2019-06-25 20:57:46 +01:00
import { TableLayoutType } from "./table-properties/table-layout";
2018-10-23 23:44:50 +01:00
import { TableRow } from "./table-row";
import { ITableWidthProperties } from "./table-width";
2019-09-13 00:51:20 +01:00
2019-03-08 01:09:21 +00:00
/*
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
*/
2019-03-13 02:29:11 +00:00
export interface ITableOptions {
readonly rows: readonly TableRow[];
readonly width?: ITableWidthProperties;
readonly columnWidths?: readonly number[];
readonly margins?: ITableCellMarginOptions;
readonly indent?: ITableWidthProperties;
2019-03-13 02:29:11 +00:00
readonly float?: ITableFloatOptions;
2019-06-25 20:57:46 +01:00
readonly layout?: TableLayoutType;
readonly style?: string;
2019-11-18 01:04:31 +00:00
readonly borders?: ITableBordersOptions;
2019-11-24 01:22:17 +00:00
readonly alignment?: AlignmentType;
readonly visuallyRightToLeft?: boolean;
2019-03-13 02:29:11 +00:00
}
2023-01-23 14:14:05 +00:00
export class Table extends FileChild {
2022-08-31 07:52:27 +01:00
public constructor({
2019-03-13 02:29:11 +00:00
rows,
2019-09-26 02:03:17 +01:00
width,
// eslint-disable-next-line functional/immutable-data
2019-09-13 00:51:20 +01:00
columnWidths = Array<number>(Math.max(...rows.map((row) => row.CellCount))).fill(100),
margins,
indent,
2019-03-13 02:29:11 +00:00
float,
2019-06-25 20:57:46 +01:00
layout,
style,
2019-11-18 01:04:31 +00:00
borders,
2019-11-24 01:22:17 +00:00
alignment,
visuallyRightToLeft,
2019-03-13 02:29:11 +00:00
}: ITableOptions) {
2017-09-19 15:49:27 +01:00
super("w:tbl");
2019-09-26 02:03:17 +01:00
2021-03-04 01:42:58 +00:00
this.root.push(
new TableProperties({
borders: borders ?? {},
width: width ?? { size: 100 },
indent,
2021-03-04 01:42:58 +00:00
float,
layout,
style,
2021-03-04 01:42:58 +00:00
alignment,
cellMargin: margins,
visuallyRightToLeft,
2021-03-04 01:42:58 +00:00
}),
);
2017-09-19 15:49:27 +01:00
2019-09-13 00:51:20 +01:00
this.root.push(new TableGrid(columnWidths));
2017-09-19 15:49:27 +01:00
2019-09-13 00:51:20 +01:00
for (const row of rows) {
this.root.push(row);
}
2019-03-13 02:29:11 +00:00
rows.forEach((row, rowIndex) => {
if (rowIndex === rows.length - 1) {
// don't process the end row
return;
}
let columnIndex = 0;
row.cells.forEach((cell) => {
2019-09-25 00:57:24 +01:00
// Row Span has to be added in this method and not the constructor because it needs to know information about the column which happens after Table Cell construction
// Row Span of 1 will crash word as it will add RESTART and not a corresponding CONTINUE
if (cell.options.rowSpan && cell.options.rowSpan > 1) {
const continueCell = new TableCell({
// the inserted CONTINUE cell has rowSpan, and will be handled when process the next row
rowSpan: cell.options.rowSpan - 1,
columnSpan: cell.options.columnSpan,
borders: cell.options.borders,
children: [],
verticalMerge: VerticalMergeType.CONTINUE,
});
rows[rowIndex + 1].addCellToColumnIndex(continueCell, columnIndex);
2019-09-25 00:57:24 +01:00
}
columnIndex += cell.options.columnSpan || 1;
2019-09-25 00:57:24 +01:00
});
});
2017-09-19 15:49:27 +01:00
}
}