Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions demo/97-table-look.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Example of using tableLook to control conditional table formatting
import { Document, Packer, Paragraph, Table, TableCell, TableRow, TextRun, WidthType } from "docx";
import * as fs from "fs";

const styles = fs.readFileSync("./demo/assets/custom-styles.xml", "utf-8");

const doc = new Document({
externalStyles: styles,
sections: [
{
children: [
new Paragraph({
children: [new TextRun({ text: "Table 1: Table Look Default Values", bold: true })],
}),
new Paragraph({ text: "" }),
new Table({
rows: [
new TableRow({
children: [
new TableCell({ children: [new Paragraph("Header 1")] }),
new TableCell({ children: [new Paragraph("Header 2")] }),
new TableCell({ children: [new Paragraph("Header 3")] }),
],
}),
new TableRow({
children: [
new TableCell({ children: [new Paragraph("Row 1, Col 1")] }),
new TableCell({ children: [new Paragraph("Row 1, Col 2")] }),
new TableCell({ children: [new Paragraph("Row 1, Col 3")] }),
],
}),
new TableRow({
children: [
new TableCell({ children: [new Paragraph("Row 2, Col 1")] }),
new TableCell({ children: [new Paragraph("Row 2, Col 2")] }),
new TableCell({ children: [new Paragraph("Row 2, Col 3")] }),
],
}),
new TableRow({
children: [
new TableCell({ children: [new Paragraph("Row 3, Col 1")] }),
new TableCell({ children: [new Paragraph("Row 3, Col 2")] }),
new TableCell({ children: [new Paragraph("Row 3, Col 3")] }),
],
}),
],
width: {
size: 100,
type: WidthType.PERCENTAGE,
},
style: "MyCustomTableStyle",
}),
new Paragraph({ text: "" }),
new Paragraph({ text: "" }),
new Paragraph({
children: [new TextRun({ text: "Table 2: Table Look All Look Values Enabled", bold: true })],
}),
new Paragraph({ text: "" }),
new Table({
tableLook: {
firstRow: true,
lastRow: true,
firstColumn: true,
lastColumn: true,
noHBand: false,
noVBand: false,
},
rows: [
new TableRow({
children: [
new TableCell({ children: [new Paragraph("Header 1")] }),
new TableCell({ children: [new Paragraph("Header 2")] }),
new TableCell({ children: [new Paragraph("Header 3")] }),
],
}),
new TableRow({
children: [
new TableCell({ children: [new Paragraph("Row 1, Col 1")] }),
new TableCell({ children: [new Paragraph("Row 1, Col 2")] }),
new TableCell({ children: [new Paragraph("Row 1, Col 3")] }),
],
}),
new TableRow({
children: [
new TableCell({ children: [new Paragraph("Row 2, Col 1")] }),
new TableCell({ children: [new Paragraph("Row 2, Col 2")] }),
new TableCell({ children: [new Paragraph("Row 2, Col 3")] }),
],
}),
new TableRow({
children: [
new TableCell({ children: [new Paragraph("Row 3, Col 1")] }),
new TableCell({ children: [new Paragraph("Row 3, Col 2")] }),
new TableCell({ children: [new Paragraph("Row 3, Col 3")] }),
],
}),
],
width: {
size: 100,
type: WidthType.PERCENTAGE,
},
style: "MyCustomTableStyle",
}),
],
},
],
});

Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("97-table-look.docx", buffer);
console.log("Document created successfully at 97-table-look.docx");
});
31 changes: 31 additions & 0 deletions docs/usage/tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,37 @@ const table = new Table({
});
```

### Table Look (Conditional Formatting)

Control which conditional formatting from a table style is applied. Table styles can define special formatting for the first row, first column, etc. Use `tableLook` to toggle these formatting options.

```ts
const table = new Table({
style: "GridTable5Dark-Accent3",
tableLook: {
firstRow: true, // Apply first row formatting
lastRow: false, // Don't apply last row formatting
firstColumn: true, // Apply first column formatting
lastColumn: false, // Don't apply last column formatting
noHBand: false, // Apply horizontal banding (row stripes)
noVBand: true, // Don't apply vertical banding (column stripes)
},
});
```

**Note**: When `tableLook` is not specified at all, Word applies row and column banding by default, but does not apply first/last row/column formatting.

#### Options

| Property | Type | Description |
| ------------ | --------- | -------------------------------------------- |
| firstRow | `boolean` | Apply special formatting to first row |
| lastRow | `boolean` | Apply special formatting to last row |
| firstColumn | `boolean` | Apply special formatting to first column |
| lastColumn | `boolean` | Apply special formatting to last column |
| noHBand | `boolean` | Disable horizontal banding (row stripes) |
| noVBand | `boolean` | Disable vertical banding (column stripes) |

## Examples

[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/4-basic-table.ts ':include')
Expand Down
1 change: 1 addition & 0 deletions src/file/table/table-properties/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./table-properties";
export * from "./table-float-properties";
export * from "./table-layout";
export * from "./table-borders";
export * from "./table-look";
159 changes: 159 additions & 0 deletions src/file/table/table-properties/table-look.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { describe, expect, it } from "vitest";

import { Formatter } from "@export/formatter";

import { TableLook } from "./table-look";

describe("TableLook", () => {
describe("#constructor", () => {
it("should create table look with firstRow enabled", () => {
const tableLook = new TableLook({
firstRow: true,
});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {
"w:firstRow": true,
},
},
});
});

it("should create table look with lastRow enabled", () => {
const tableLook = new TableLook({
lastRow: true,
});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {
"w:lastRow": true,
},
},
});
});

it("should create table look with firstColumn enabled", () => {
const tableLook = new TableLook({
firstColumn: true,
});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {
"w:firstColumn": true,
},
},
});
});

it("should create table look with lastColumn enabled", () => {
const tableLook = new TableLook({
lastColumn: true,
});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {
"w:lastColumn": true,
},
},
});
});

it("should create table look with noHBand enabled", () => {
const tableLook = new TableLook({
noHBand: true,
});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {
"w:noHBand": true,
},
},
});
});

it("should create table look with noVBand enabled", () => {
const tableLook = new TableLook({
noVBand: true,
});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {
"w:noVBand": true,
},
},
});
});

it("should create table look with firstRow set to false", () => {
const tableLook = new TableLook({
firstRow: false,
});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {
"w:firstRow": false,
},
},
});
});

it("should create table look with multiple attributes", () => {
const tableLook = new TableLook({
firstRow: true,
firstColumn: true,
noVBand: true,
});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {
"w:firstRow": true,
"w:firstColumn": true,
"w:noVBand": true,
},
},
});
});

it("should create table look with all attributes", () => {
const tableLook = new TableLook({
firstRow: true,
lastRow: false,
firstColumn: true,
lastColumn: false,
noHBand: false,
noVBand: true,
});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {
"w:firstRow": true,
"w:lastRow": false,
"w:firstColumn": true,
"w:lastColumn": false,
"w:noHBand": false,
"w:noVBand": true,
},
},
});
});

it("should create table look with empty options", () => {
const tableLook = new TableLook({});
const tree = new Formatter().format(tableLook);
expect(tree).to.deep.equal({
"w:tblLook": {
_attr: {},
},
});
});
});
});
37 changes: 37 additions & 0 deletions src/file/table/table-properties/table-look.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// http://officeopenxml.com/WPtblLook.php
// <xsd:complexType name="CT_TblLook">
// <xsd:attribute name="firstRow" type="s:ST_OnOff"/>
// <xsd:attribute name="lastRow" type="s:ST_OnOff"/>
// <xsd:attribute name="firstColumn" type="s:ST_OnOff"/>
// <xsd:attribute name="lastColumn" type="s:ST_OnOff"/>
// <xsd:attribute name="noHBand" type="s:ST_OnOff"/>
// <xsd:attribute name="noVBand" type="s:ST_OnOff"/>
// </xsd:complexType>
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";

export type ITableLookOptions = {
readonly firstRow?: boolean;
readonly lastRow?: boolean;
readonly firstColumn?: boolean;
readonly lastColumn?: boolean;
readonly noHBand?: boolean;
readonly noVBand?: boolean;
};

class TableLookAttributes extends XmlAttributeComponent<ITableLookOptions> {
protected readonly xmlKeys = {
firstRow: "w:firstRow",
lastRow: "w:lastRow",
firstColumn: "w:firstColumn",
lastColumn: "w:lastColumn",
noHBand: "w:noHBand",
noVBand: "w:noVBand",
};
}

export class TableLook extends XmlComponent {
public constructor(options: ITableLookOptions) {
super("w:tblLook");
this.root.push(new TableLookAttributes(options));
}
}
Loading