Merge pull request #274 from dolanmiu/feat/vertical-table-merge

Add table column and vertical merging
This commit is contained in:
Dolan
2019-03-05 23:53:12 +00:00
committed by GitHub
10 changed files with 234 additions and 11 deletions

View File

@ -3,7 +3,7 @@ import { Paragraph } from "file/paragraph";
import { IXmlableObject, XmlComponent } from "file/xml-components";
import { Table } from "../table";
import { TableCellBorders, VerticalAlign } from "./table-cell-components";
import { TableCellBorders, VerticalAlign, VMergeType } from "./table-cell-components";
import { TableCellProperties } from "./table-cell-properties";
export class TableCell extends XmlComponent {
@ -58,6 +58,12 @@ export class TableCell extends XmlComponent {
return this;
}
public addVerticalMerge(type: VMergeType): TableCell {
this.properties.addVerticalMerge(type);
return this;
}
public get Borders(): TableCellBorders {
return this.properties.Borders;
}

View File

@ -0,0 +1,52 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
import { TableCell } from "./table-cell";
import { TableColumn } from "./table-column";
describe("TableColumn", () => {
let cells: TableCell[];
beforeEach(() => {
cells = [new TableCell(), new TableCell(), new TableCell()];
});
describe("#getCell", () => {
it("should get the correct cell", () => {
const tableColumn = new TableColumn(cells);
const cell = tableColumn.getCell(0);
expect(cell).to.deep.equal(cells[0]);
const cell2 = tableColumn.getCell(1);
expect(cell2).to.deep.equal(cells[1]);
});
it("should throw an error if index is out of bounds", () => {
const tableColumn = new TableColumn(cells);
expect(() => tableColumn.getCell(9)).to.throw();
});
});
describe("#mergeCells", () => {
it("should add vMerge to correct cells", () => {
const tableColumn = new TableColumn(cells);
tableColumn.mergeCells(0, 2);
const tree = new Formatter().format(cells[0]);
expect(tree).to.deep.equal({
"w:tc": [{ "w:tcPr": [{ "w:vMerge": [{ _attr: { "w:val": "restart" } }] }] }, { "w:p": [{ "w:pPr": [] }] }],
});
const tree2 = new Formatter().format(cells[1]);
expect(tree2).to.deep.equal({ "w:tc": [{ "w:tcPr": [] }, { "w:p": [{ "w:pPr": [] }] }] });
const tree3 = new Formatter().format(cells[2]);
expect(tree3).to.deep.equal({
"w:tc": [{ "w:tcPr": [{ "w:vMerge": [{ _attr: { "w:val": "continue" } }] }] }, { "w:p": [{ "w:pPr": [] }] }],
});
});
});
});

View File

@ -0,0 +1,22 @@
import { TableCell, VMergeType } from "./table-cell";
export class TableColumn {
constructor(private readonly cells: TableCell[]) {}
public getCell(index: number): TableCell {
const cell = this.cells[index];
if (!cell) {
throw Error("Index out of bounds when trying to get cell on column");
}
return cell;
}
public mergeCells(startIndex: number, endIndex: number): TableCell {
this.cells[startIndex].addVerticalMerge(VMergeType.RESTART);
this.cells[endIndex].addVerticalMerge(VMergeType.CONTINUE);
return this.cells[startIndex];
}
}

View File

@ -17,7 +17,7 @@ export class TableProperties extends XmlComponent {
this.root.push(this.cellMargin);
}
public setWidth(width: number | string, type: WidthType = WidthType.AUTO): TableProperties {
public setWidth(width: number, type: WidthType = WidthType.AUTO): TableProperties {
this.root.push(new PreferredTableWidth(type, width));
return this;
}

View File

@ -1,3 +1,4 @@
// http://officeopenxml.com/WPtableWidth.php
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { WidthType } from "../table-cell";
@ -12,7 +13,7 @@ class TableWidthAttributes extends XmlAttributeComponent<ITableWidth> {
}
export class PreferredTableWidth extends XmlComponent {
constructor(type: WidthType, w: number | string) {
constructor(type: WidthType, w: number) {
super("w:tblW");
this.root.push(new TableWidthAttributes({ type, w }));
}

View File

@ -106,8 +106,9 @@ describe("Table", () => {
});
describe("#getRow and Row#getCell", () => {
it("returns the correct row", () => {
const table = new Table(2, 2);
const table = new Table(2, 2);
it("should return the correct row", () => {
table
.getRow(0)
.getCell(0)
@ -144,10 +145,25 @@ describe("Table", () => {
],
});
});
it("throws an exception if index is out of bounds", () => {
expect(() => table.getCell(9, 9)).to.throw();
});
});
describe("#getColumn", () => {
const table = new Table(2, 2);
it("should get correct row", () => {
const column = table.getColumn(0);
expect(column.getCell(0)).to.equal(table.getCell(0, 0));
expect(column.getCell(1)).to.equal(table.getCell(1, 0));
});
});
describe("#getCell", () => {
it("returns the correct cell", () => {
it("should returns the correct cell", () => {
const table = new Table(2, 2);
table.getCell(0, 0).addParagraph(new Paragraph("A1"));
table.getCell(0, 1).addParagraph(new Paragraph("B1"));

View File

@ -3,6 +3,7 @@ import { XmlComponent } from "file/xml-components";
import { TableGrid } from "./grid";
import { TableCell, WidthType } from "./table-cell";
import { TableColumn } from "./table-column";
import { ITableFloatOptions, TableProperties } from "./table-properties";
import { TableRow } from "./table-row";
@ -51,8 +52,8 @@ export class Table extends XmlComponent {
}
}
public getRow(ix: number): TableRow {
const row = this.rows[ix];
public getRow(index: number): TableRow {
const row = this.rows[index];
if (!row) {
throw Error("Index out of bounds when trying to get row on table");
@ -61,11 +62,17 @@ export class Table extends XmlComponent {
return row;
}
public getColumn(index: number): TableColumn {
// This is a convinence method for people who like to work with columns
const cells = this.rows.map((row) => row.getCell(index));
return new TableColumn(cells);
}
public getCell(row: number, col: number): TableCell {
return this.getRow(row).getCell(col);
}
public setWidth(width: number | string, type: WidthType = WidthType.AUTO): Table {
public setWidth(width: number, type: WidthType = WidthType.AUTO): Table {
this.properties.setWidth(width, type);
return this;
}