From bd888219fcaf25e532e44c158dcdf5a5fa1e16eb Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 26 Sep 2019 02:03:17 +0100 Subject: [PATCH] Amend table documentation --- docs/usage/tables.md | 340 ++++++++++-------- .../table/table-cell/table-cell-components.ts | 10 +- .../table-cell/table-cell-properties.spec.ts | 4 +- .../table/table-cell/table-cell-properties.ts | 15 +- src/file/table/table-cell/table-cell.ts | 6 +- src/file/table/table.ts | 21 +- 6 files changed, 229 insertions(+), 167 deletions(-) diff --git a/docs/usage/tables.md b/docs/usage/tables.md index e3230c7293..ece0f6930d 100644 --- a/docs/usage/tables.md +++ b/docs/usage/tables.md @@ -4,6 +4,10 @@ ## Intro +* `Tables` contain a list of `Rows` +* `Rows` contain a list of `TableCells` +* `TableCells` contain a list of `Parahraphs` and/or `Tables`. You can add `Tables` as tables can be nested inside each other + Create a simple table like so: ```ts @@ -20,6 +24,46 @@ doc.addSection({ }); ``` +## Table + +### Set Width + +```ts +const table = new Table({ + ..., + width: { + size: [TABLE_WIDTH], + type: WidthType, + } +}); +``` + +For example: + +```ts + +const table = new Table({ + ..., + width: { + size: 4535, + type: WidthType.DXA, + } +}); +``` + +### Pagination + +#### Prevent row pagination + +To prevent breaking contents of a row across multiple pages, call `cantSplit`: + +```ts +const table = new Table({ + rows: [], + cantSplit: true, +}); +``` + ## Table Row A table consists of multiple `table rows`. Table rows have a list of `children` which accepts a list of `table cells` explained below. You can create a simple `table row` like so: @@ -61,7 +105,18 @@ Here is a list of options you can add to the `table row`: | tableHeader | `boolean` | Optional | | height | `{ value: number, rule: HeightRule }` | Optional | -## Cells +### Repeat row + +If a table is paginated on multiple pages, it is possible to repeat a row at the top of each new page by setting `tableHeader` to `true`: + +```ts +const row = new TableRow({ + ..., + tableHeader: true, +}); +``` + +## Table Cells Cells need to be added in the `table row`, you can create a table cell like: @@ -83,206 +138,197 @@ const tableRow = new TableRow({ }); ``` -| Property | Type | Notes | -| ----------- | ------------------------------------- | -------- | -| children | `Array` | Required | -| cantSplit | `boolean` | Optional | -| tableHeader | `boolean` | Optional | -| height | `{ value: number, rule: HeightRule }` | Optional | - ### Options - readonly shading?: ITableShadingAttributesProperties; - readonly margins?: ITableCellMarginOptions; - readonly verticalAlign?: VerticalAlign; - readonly verticalMerge?: VMergeType; - readonly columnSpan?: number; - readonly borders?: { - readonly top?: { - readonly style: BorderStyle; - readonly size: number; - readonly color: string; - }; - readonly bottom?: { - readonly style: BorderStyle; - readonly size: number; - readonly color: string; - }; - readonly left?: { - readonly style: BorderStyle; - readonly size: number; - readonly color: string; - }; - readonly right?: { - readonly style: BorderStyle; - readonly size: number; - readonly color: string; - }; - }; - readonly children: Array; +| Property | Type | Notes | +| ------------- | ----------------------------------- | ----------------------------------------------------------- | +| children | `Array` | Required. You can nest tables by adding a table into a cell | +| shading | `ITableShadingAttributesProperties` | Optional | +| margins | `ITableCellMarginOptions` | Optional | +| verticalAlign | `VerticalAlign` | Optional | +| columnSpan | `number` | Optional | +| rowSpan | `number` | Optional | +| borders | `BorderOptions` | Optional | +| width | `{ size: number type: WidthType }` | Optional | +#### Border Options +| Property | Type | Notes | +| -------- | ----------------------------------------------------- | -------- | +| top | `{ style: BorderStyle, size: number, color: string }` | Optional | +| bottom | `{ style: BorderStyle, size: number, color: string }` | Optional | +| left | `{ style: BorderStyle, size: number, color: string }` | Optional | +| right | `{ style: BorderStyle, size: number, color: string }` | Optional | + +##### Example + +```ts +const cell = new TableCell({ + ..., + borders: { + top: { + style: BorderStyle.DASH_DOT_STROKED, + size: 1, + color: "red", + }, + bottom: { + style: BorderStyle.THICK_THIN_MEDIUM_GAP, + size: 5, + color: "889900", + }, + }, +}); +``` + +##### Google DOCS + +Google DOCS does not support start and end borders, instead they use left and right borders. So to set left and right borders for Google DOCS you should use: + +```ts +const cell = new TableCell({ + ..., + borders: { + top: { + style: BorderStyle.DOT_DOT_DASH, + size: 3, + color: "green", + }, + bottom: { + style: BorderStyle.DOT_DOT_DASH, + size: 3, + color: "ff8000", + }, + }, +}); +``` ### Add paragraph to a cell -Once you have got the cell, you can add data to it with the `add()` method. +Once you have got the cell, you can add data to it: ```ts -new TableCell({ +const cell = new TableCell({ children: [new Paragraph("Hello")], -}), +}); ``` ### Set width of a cell You can specify the width of a cell using: -`cell.Properties.setWidth(width, format)` +```ts +const cell = new TableCell({ + ..., + width: { + size: number, + type: WidthType, + }, +}); +``` -format can be: +`WidthType` values can be: -- WidthType.AUTO -- WidthType.DXA: value is in twentieths of a point -- WidthType.NIL: is considered as zero -- WidthType.PCT: percent of table width +| Property | Notes | +| -------- | --------------------------------- | +| AUTO | | +| DXA | value is in twentieths of a point | +| NIL | is considered as zero | +| PCT | percent of table width | -### Example +#### Example ```ts cell.Properties.setWidth(100, WidthType.DXA); ``` -```ts -cell.Properties.setWidth("50%", WidthType.PCT); -``` +### Nested Tables -## Borders - -BorderStyle can be imported from `docx`. Size determines the thickness. HTML color can be a hex code or alias such as `red`. +To have a table within a table, simply add it in the `children` block of a `table cell`: ```ts -cell.Borders.addTopBorder([BorderStyle], [SIZE], [HTML COLOR]); +const cell = new TableCell({ + children: [new Table(...)], +}); ``` -```ts -cell.Borders.addBottomBorder([BorderStyle], [SIZE], [HTML COLOR]); -``` - -```ts -cell.Borders.addStartBorder([[BorderStyle]], [SIZE], [HTML COLOR]); -``` - -```ts -cell.Borders.addEndBorder([BorderStyle], [SIZE], [HTML COLOR]); -``` - -### Example - -```ts -import { BorderStyle } from "docx"; - -cell.Borders.addStartBorder(BorderStyle.DOT_DOT_DASH, 3, "green"); -cell.Borders.addEndBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000"); -``` - -### Google DOCS - -Google DOCS does not support start and end borders, instead they use left and right borders. So to set left and right borders for Google DOCS you should use: - -```ts -import { BorderStyle } from "docx"; - -cell.Borders.addLeftBorder(BorderStyle.DOT_DOT_DASH, 3, "green"); -cell.Borders.addRightBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000"); -``` - -## Set Width - -```ts -import { WidthType } from "docx"; - -table.setWidth([WIDTH], [OPTIONAL WidthType. Defaults to DXA]); -``` - -For example: - -```ts -table.setWidth(4535, WidthType.DXA); -``` - -## Vertical Align +### Vertical Align Sets the vertical alignment of the contents of the cell ```ts -import { VerticalAlign } from "docx"; - -cell.setVerticalAlign([VerticalAlign TYPE]); +const cell = new TableCell({ + ..., + verticalAlign: VerticalAlign, +}); ``` +`VerticalAlign` values can be: + +| Property | Notes | +| -------- | ------------------------------------------ | +| BOTTOM | Align the contents on the bottom | +| CENTER | Align the contents on the center | +| TOP | Align the contents on the top. The default | + For example, to center align a cell: ```ts -cell.setVerticalAlign(VerticalAlign.CENTER); +const cell = new TableCell({ + verticalAlign: VerticalAlign.CENTER, +}); ``` -## Rows +## Merging cells together -To get a row, use the `getRow` method on a `table`. There are a handful of methods which you can apply to a row which will be explained below. +### Row Merge + +When cell rows are merged, it counts as multiple rows, so be sure to remove excess cells. It is similar to how HTML's `rowspan` works. +https://www.w3schools.com/tags/att_td_rowspan.asp ```ts -table.getRow([ROW INDEX]); -``` - -## Merge cells together - -### Merging on a row - -First obtain the row, and call `mergeCells()`. The first argument is where the merge should start. The second argument is where the merge should end. - -```ts -table.getRow(0).mergeCells([FROM INDEX], [TO INDEX]); +const cell = new TableCell({ + ..., + rowSpan: [NUMBER_OF_CELLS_TO_MERGE], +}); ``` #### Example -This will merge 3 cells together starting from index `0`: +The example will merge three rows together. ```ts -table.getRow(0).mergeCells(0, 2); +const cell = new TableCell({ + ..., + rowSpan: 3, +}); ``` -### Merging on a column +### Column Merge -It has not been implemented yet, but it will follow a similar structure as merging a row. - -## Nested Tables - -To have a table within a table +When cell columns are merged, it counts as multiple columns, so be sure to remove excess cells. It is similar to how HTML's `colspan` works. +https://www.w3schools.com/tags/att_td_colspan.asp ```ts -cell.add(new Table(1, 1)); +const cell = new TableCell({ + ..., + columnSpan: [NUMBER_OF_CELLS_TO_MERGE], +}); ``` -## Pagination +#### Example -###Prevent row pagination -To prevent breaking contents of a row across multiple pages, call `cantSplit()`: +The example will merge three columns together. ```ts -table.getRow(0).setCantSplit(); -``` - -###Repeat row -If a table is paginated on multiple pages, it is possible to repeat a row at the top of each new page calling `setTableHeader()`: - -```ts -table.getRow(0).setTableHeader(); +const cell = new TableCell({ + ..., + columnSpan: 3, +}); ``` ## Examples -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/4-basic-table.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/4-basic-table.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/4-basic-table.ts_ @@ -290,7 +336,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/4-basic-table.ts_ Example showing how to add colourful borders to tables -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/20-table-cell-borders.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/20-table-cell-borders.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/20-table-cell-borders.ts_ @@ -298,11 +344,11 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/20-table-cell-borders Example showing how to add images to tables -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/24-images-to-table-cell.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/24-images-to-table-cell.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/24-images-to-table-cell.ts_ -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/36-image-to-table-cell.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/36-image-to-table-cell.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/36-image-to-table-cell.ts_ @@ -310,19 +356,19 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/36-image-to-table-cel Example showing how align text in a table cell -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/31-tables.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/31-tables.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/31-tables.ts_ -### Shading +### Shading Example showing merging of columns and rows and shading -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/32-merge-table-cells.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/32-merge-table-cells.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/32-merge-table-cells.ts_ -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/41-merge-table-cells-2.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/41-merge-table-cells-2.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/41-merge-table-cells-2.ts_ @@ -330,12 +376,12 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/41-merge-table-cells- Example showing merging of columns and rows -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/43-images-to-table-cell-2.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/43-images-to-table-cell-2.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/43-images-to-table-cell-2.ts_ ### Floating tables -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/34-floating-tables.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/34-floating-tables.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/34-floating-tables.ts_ diff --git a/src/file/table/table-cell/table-cell-components.ts b/src/file/table/table-cell/table-cell-components.ts index 518b8a67b2..e16c2f6885 100644 --- a/src/file/table/table-cell/table-cell-components.ts +++ b/src/file/table/table-cell/table-cell-components.ts @@ -103,7 +103,7 @@ export class GridSpan extends XmlComponent { /** * Vertical merge types. */ -export enum VMergeType { +export enum VerticalMergeType { /** * Cell that is merged with upper one. */ @@ -114,19 +114,19 @@ export enum VMergeType { RESTART = "restart", } -class VMergeAttributes extends XmlAttributeComponent<{ readonly val: VMergeType }> { +class VerticalMergeAttributes extends XmlAttributeComponent<{ readonly val: VerticalMergeType }> { protected readonly xmlKeys = { val: "w:val" }; } /** * Vertical merge element. Should be used in a table cell. */ -export class VMerge extends XmlComponent { - constructor(value: VMergeType) { +export class VerticalMerge extends XmlComponent { + constructor(value: VerticalMergeType) { super("w:vMerge"); this.root.push( - new VMergeAttributes({ + new VerticalMergeAttributes({ val: value, }), ); diff --git a/src/file/table/table-cell/table-cell-properties.spec.ts b/src/file/table/table-cell/table-cell-properties.spec.ts index 65bfd92fe6..9835aa9623 100644 --- a/src/file/table/table-cell/table-cell-properties.spec.ts +++ b/src/file/table/table-cell/table-cell-properties.spec.ts @@ -3,7 +3,7 @@ import { expect } from "chai"; import { Formatter } from "export/formatter"; import { BorderStyle } from "file/styles"; -import { VerticalAlign, VMergeType, WidthType } from "./table-cell-components"; +import { VerticalAlign, VerticalMergeType, WidthType } from "./table-cell-components"; import { TableCellProperties } from "./table-cell-properties"; describe("TableCellProperties", () => { @@ -30,7 +30,7 @@ describe("TableCellProperties", () => { describe("#addVerticalMerge", () => { it("adds vertical merge", () => { const properties = new TableCellProperties(); - properties.addVerticalMerge(VMergeType.CONTINUE); + properties.addVerticalMerge(VerticalMergeType.CONTINUE); const tree = new Formatter().format(properties); expect(tree).to.deep.equal({ "w:tcPr": [{ "w:vMerge": { _attr: { "w:val": "continue" } } }] }); }); diff --git a/src/file/table/table-cell/table-cell-properties.ts b/src/file/table/table-cell/table-cell-properties.ts index 5a2544b9cd..aed56aaeda 100644 --- a/src/file/table/table-cell/table-cell-properties.ts +++ b/src/file/table/table-cell/table-cell-properties.ts @@ -2,7 +2,16 @@ import { IgnoreIfEmptyXmlComponent } from "file/xml-components"; import { ITableShadingAttributesProperties, TableShading } from "../shading"; import { ITableCellMarginOptions, TableCellMargin } from "./cell-margin/table-cell-margins"; -import { GridSpan, TableCellBorders, TableCellWidth, VAlign, VerticalAlign, VMerge, VMergeType, WidthType } from "./table-cell-components"; +import { + GridSpan, + TableCellBorders, + TableCellWidth, + VAlign, + VerticalAlign, + VerticalMerge, + VerticalMergeType, + WidthType, +} from "./table-cell-components"; export class TableCellProperties extends IgnoreIfEmptyXmlComponent { private readonly cellBorder: TableCellBorders; @@ -23,8 +32,8 @@ export class TableCellProperties extends IgnoreIfEmptyXmlComponent { return this; } - public addVerticalMerge(type: VMergeType): TableCellProperties { - this.root.push(new VMerge(type)); + public addVerticalMerge(type: VerticalMergeType): TableCellProperties { + this.root.push(new VerticalMerge(type)); return this; } diff --git a/src/file/table/table-cell/table-cell.ts b/src/file/table/table-cell/table-cell.ts index 616065a0c1..5c34d17903 100644 --- a/src/file/table/table-cell/table-cell.ts +++ b/src/file/table/table-cell/table-cell.ts @@ -6,14 +6,14 @@ import { IXmlableObject, XmlComponent } from "file/xml-components"; import { ITableShadingAttributesProperties } from "../shading"; import { Table } from "../table"; import { ITableCellMarginOptions } from "./cell-margin/table-cell-margins"; -import { VerticalAlign, VMergeType } from "./table-cell-components"; +import { VerticalAlign, VerticalMergeType } from "./table-cell-components"; import { TableCellProperties } from "./table-cell-properties"; export interface ITableCellOptions { readonly shading?: ITableShadingAttributesProperties; readonly margins?: ITableCellMarginOptions; readonly verticalAlign?: VerticalAlign; - readonly verticalMerge?: VMergeType; + readonly verticalMerge?: VerticalMergeType; readonly columnSpan?: number; readonly rowSpan?: number; readonly borders?: { @@ -75,7 +75,7 @@ export class TableCell extends XmlComponent { } if (options.rowSpan && options.rowSpan > 1) { - this.properties.addVerticalMerge(VMergeType.RESTART); + this.properties.addVerticalMerge(VerticalMergeType.RESTART); } if (options.borders) { diff --git a/src/file/table/table.ts b/src/file/table/table.ts index 64e276f73d..08bd47eda2 100644 --- a/src/file/table/table.ts +++ b/src/file/table/table.ts @@ -1,7 +1,7 @@ // http://officeopenxml.com/WPtableGrid.php import { XmlComponent } from "file/xml-components"; import { TableGrid } from "./grid"; -import { TableCell, VMergeType, WidthType } from "./table-cell"; +import { TableCell, VerticalMergeType, WidthType } from "./table-cell"; import { ITableFloatOptions, TableProperties } from "./table-properties"; import { TableLayoutType } from "./table-properties/table-layout"; import { TableRow } from "./table-row"; @@ -18,8 +18,10 @@ import { TableRow } from "./table-row"; */ export interface ITableOptions { readonly rows: TableRow[]; - readonly width?: number; - readonly widthUnitType?: WidthType; + readonly width?: { + readonly size: number; + readonly type?: WidthType; + }; readonly columnWidths?: number[]; readonly margins?: { readonly marginUnitType?: WidthType; @@ -37,8 +39,7 @@ export class Table extends XmlComponent { constructor({ rows, - width = 100, - widthUnitType = WidthType.AUTO, + width, columnWidths = Array(Math.max(...rows.map((row) => row.CellCount))).fill(100), margins: { marginUnitType, top, bottom, right, left } = { marginUnitType: WidthType.AUTO, top: 0, bottom: 0, right: 0, left: 0 }, float, @@ -48,7 +49,13 @@ export class Table extends XmlComponent { this.properties = new TableProperties(); this.root.push(this.properties); this.properties.setBorder(); - this.properties.setWidth(width, widthUnitType); + + if (width) { + this.properties.setWidth(width.size, width.type); + } else { + this.properties.setWidth(100); + } + this.properties.CellMargin.addBottomMargin(bottom || 0, marginUnitType); this.properties.CellMargin.addTopMargin(top || 0, marginUnitType); this.properties.CellMargin.addLeftMargin(left || 0, marginUnitType); @@ -73,7 +80,7 @@ export class Table extends XmlComponent { rows[i].addCellToIndex( new TableCell({ children: [], - verticalMerge: VMergeType.CONTINUE, + verticalMerge: VerticalMergeType.CONTINUE, }), i, );