Refactor row merging to table level
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
// Example of how you would merge cells together - Rows and Columns
|
// Example of how you would merge cells together (Rows and Columns) and apply shading
|
||||||
// Import from 'docx' rather than '../build' if you install from npm
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { Document, HeadingLevel, Packer, Paragraph, ShadingType, Table, TableCell, TableRow, WidthType } from "../build";
|
import { Document, HeadingLevel, Packer, Paragraph, ShadingType, Table, TableCell, TableRow, WidthType } from "../build";
|
||||||
@ -125,13 +125,61 @@ const table3 = new Table({
|
|||||||
|
|
||||||
const table4 = new Table({
|
const table4 = new Table({
|
||||||
rows: [
|
rows: [
|
||||||
|
new TableRow({
|
||||||
|
children: [
|
||||||
|
new TableCell({
|
||||||
|
children: [new Paragraph("0,0")],
|
||||||
|
columnSpan: 2,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new TableRow({
|
||||||
|
children: [
|
||||||
|
new TableCell({
|
||||||
|
children: [new Paragraph("1,0")],
|
||||||
|
}),
|
||||||
|
new TableCell({
|
||||||
|
children: [new Paragraph("1,1")],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new TableRow({
|
||||||
|
children: [
|
||||||
|
new TableCell({
|
||||||
|
children: [new Paragraph("2,0")],
|
||||||
|
columnSpan: 2,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
width: 100,
|
||||||
|
widthUnitType: WidthType.PERCENTAGE,
|
||||||
|
});
|
||||||
|
|
||||||
|
const table5 = new Table({
|
||||||
|
rows: [
|
||||||
|
new TableRow({
|
||||||
|
children: [
|
||||||
|
new TableCell({
|
||||||
|
children: [new Paragraph("0,0")],
|
||||||
|
}),
|
||||||
|
new TableCell({
|
||||||
|
children: [new Paragraph("0,1")],
|
||||||
|
rowSpan: 2,
|
||||||
|
}),
|
||||||
|
new TableCell({
|
||||||
|
children: [new Paragraph("0,2")],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
new TableRow({
|
new TableRow({
|
||||||
children: [
|
children: [
|
||||||
new TableCell({
|
new TableCell({
|
||||||
children: [],
|
children: [],
|
||||||
}),
|
}),
|
||||||
new TableCell({
|
new TableCell({
|
||||||
children: [],
|
children: [new Paragraph("1,2")],
|
||||||
|
rowSpan: 2,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
@ -163,8 +211,10 @@ doc.addSection({
|
|||||||
heading: HeadingLevel.HEADING_2,
|
heading: HeadingLevel.HEADING_2,
|
||||||
}),
|
}),
|
||||||
table3,
|
table3,
|
||||||
new Paragraph("hi"),
|
new Paragraph("Merging columns"),
|
||||||
table4,
|
table4,
|
||||||
|
new Paragraph("More Merging columns"),
|
||||||
|
table5,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
// Multiple cells merging in the same table
|
// Multiple cells merging in the same table - Rows and Columns
|
||||||
// Import from 'docx' rather than '../build' if you install from npm
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { Document, Packer, Paragraph, Table, TableCell, TableRow } from "../build";
|
import { Document, Packer, Paragraph, Table, TableCell, TableRow } from "../build";
|
||||||
|
@ -5,7 +5,6 @@ import { IXmlableObject, XmlComponent } from "file/xml-components";
|
|||||||
|
|
||||||
import { ITableShadingAttributesProperties } from "../shading";
|
import { ITableShadingAttributesProperties } from "../shading";
|
||||||
import { Table } from "../table";
|
import { Table } from "../table";
|
||||||
import { TableRow } from "../table-row";
|
|
||||||
import { ITableCellMarginOptions } from "./cell-margin/table-cell-margins";
|
import { ITableCellMarginOptions } from "./cell-margin/table-cell-margins";
|
||||||
import { VerticalAlign, VMergeType } from "./table-cell-components";
|
import { VerticalAlign, VMergeType } from "./table-cell-components";
|
||||||
import { TableCellProperties } from "./table-cell-properties";
|
import { TableCellProperties } from "./table-cell-properties";
|
||||||
@ -42,15 +41,8 @@ export interface ITableCellOptions {
|
|||||||
readonly children: Array<Paragraph | Table>;
|
readonly children: Array<Paragraph | Table>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ITableCellMetaData {
|
|
||||||
readonly column: TableCell[];
|
|
||||||
readonly row: TableRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TableCell extends XmlComponent {
|
export class TableCell extends XmlComponent {
|
||||||
private readonly properties: TableCellProperties;
|
private readonly properties: TableCellProperties;
|
||||||
// tslint:disable-next-line: readonly-keyword
|
|
||||||
private metaData: ITableCellMetaData;
|
|
||||||
|
|
||||||
constructor(readonly options: ITableCellOptions) {
|
constructor(readonly options: ITableCellOptions) {
|
||||||
super("w:tc");
|
super("w:tc");
|
||||||
@ -82,6 +74,10 @@ export class TableCell extends XmlComponent {
|
|||||||
this.properties.addGridSpan(options.columnSpan);
|
this.properties.addGridSpan(options.columnSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.rowSpan && options.rowSpan > 1) {
|
||||||
|
this.properties.addVerticalMerge(VMergeType.RESTART);
|
||||||
|
}
|
||||||
|
|
||||||
if (options.borders) {
|
if (options.borders) {
|
||||||
if (options.borders.top) {
|
if (options.borders.top) {
|
||||||
this.properties.Borders.addTopBorder(options.borders.top.style, options.borders.top.size, options.borders.top.color);
|
this.properties.Borders.addTopBorder(options.borders.top.style, options.borders.top.size, options.borders.top.color);
|
||||||
@ -107,32 +103,10 @@ export class TableCell extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(): IXmlableObject | undefined {
|
public prepForXml(): IXmlableObject | undefined {
|
||||||
// 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 (this.options.rowSpan && this.options.rowSpan > 1) {
|
|
||||||
this.properties.addVerticalMerge(VMergeType.RESTART);
|
|
||||||
|
|
||||||
const currentIndex = this.metaData.column.indexOf(this);
|
|
||||||
for (let i = currentIndex + 1; i <= currentIndex + this.options.rowSpan - 1; i++) {
|
|
||||||
this.metaData.column[i].metaData.row.Children.splice(
|
|
||||||
i,
|
|
||||||
0,
|
|
||||||
new TableCell({
|
|
||||||
children: [],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
this.metaData.column[i].properties.addVerticalMerge(VMergeType.CONTINUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cells must end with a paragraph
|
// Cells must end with a paragraph
|
||||||
if (!(this.root[this.root.length - 1] instanceof Paragraph)) {
|
if (!(this.root[this.root.length - 1] instanceof Paragraph)) {
|
||||||
this.root.push(new Paragraph({}));
|
this.root.push(new Paragraph({}));
|
||||||
}
|
}
|
||||||
return super.prepForXml();
|
return super.prepForXml();
|
||||||
}
|
}
|
||||||
|
|
||||||
public set MetaData(metaData: ITableCellMetaData) {
|
|
||||||
this.metaData = metaData;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -45,4 +45,9 @@ export class TableRow extends XmlComponent {
|
|||||||
public get Children(): TableCell[] {
|
public get Children(): TableCell[] {
|
||||||
return this.options.children;
|
return this.options.children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addCellToIndex(cell: TableCell, index: number): void {
|
||||||
|
// Offset because properties is also in root.
|
||||||
|
this.root.splice(index + 1, 0, cell);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// http://officeopenxml.com/WPtableGrid.php
|
// http://officeopenxml.com/WPtableGrid.php
|
||||||
import { XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { TableGrid } from "./grid";
|
import { TableGrid } from "./grid";
|
||||||
import { WidthType } from "./table-cell";
|
import { TableCell, VMergeType, WidthType } from "./table-cell";
|
||||||
import { ITableFloatOptions, TableProperties } from "./table-properties";
|
import { ITableFloatOptions, TableProperties } from "./table-properties";
|
||||||
import { TableLayoutType } from "./table-properties/table-layout";
|
import { TableLayoutType } from "./table-properties/table-layout";
|
||||||
import { TableRow } from "./table-row";
|
import { TableRow } from "./table-row";
|
||||||
@ -57,16 +57,31 @@ export class Table extends XmlComponent {
|
|||||||
this.root.push(new TableGrid(columnWidths));
|
this.root.push(new TableGrid(columnWidths));
|
||||||
|
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
row.Children.forEach((cell, i) => {
|
|
||||||
cell.MetaData = {
|
|
||||||
column: rows.map((r) => r.Children[i]),
|
|
||||||
row: row,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
this.root.push(row);
|
this.root.push(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const row of rows) {
|
||||||
|
row.Children.forEach((cell, cellIndex) => {
|
||||||
|
const column = rows.map((r) => r.Children[cellIndex]);
|
||||||
|
// 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 thisCellsColumnIndex = column.indexOf(cell);
|
||||||
|
const endColumnIndex = thisCellsColumnIndex + (cell.options.rowSpan - 1);
|
||||||
|
|
||||||
|
for (let i = thisCellsColumnIndex + 1; i <= endColumnIndex; i++) {
|
||||||
|
rows[i].addCellToIndex(
|
||||||
|
new TableCell({
|
||||||
|
children: [],
|
||||||
|
verticalMerge: VMergeType.CONTINUE,
|
||||||
|
}),
|
||||||
|
i,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (float) {
|
if (float) {
|
||||||
this.properties.setTableFloatProperties(float);
|
this.properties.setTableFloatProperties(float);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user