Merge pull request #228 from dolanmiu/feat/improve-docs

Change table methods and document it
This commit is contained in:
Dolan
2019-01-03 02:43:16 +00:00
committed by GitHub
16 changed files with 411 additions and 59 deletions

View File

@ -84,8 +84,7 @@ doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph")
.basedOn("Normal");
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"));
doc
.createParagraph("HEADING")
doc.createParagraph("HEADING")
.heading1()
.center();
@ -111,8 +110,8 @@ const table = new Table(4, 4);
table
.getRow(0)
.getCell(0)
.addContent(new Paragraph("Pole No."));
// table.Properties.width = 10000;
.addParagraph(new Paragraph("Pole No."));
doc.addTable(table);
const arrboth = [
@ -129,8 +128,6 @@ const arrboth = [
arrboth.forEach((item) => {
const para = doc.createParagraph();
para.addImage(doc.createImage(fs.readFileSync(item.image)));
// para.Properties.width = 60;
// para.Properties.height = 90;
doc.createParagraph(item.comment).style("normalPara2");
});

View File

@ -8,8 +8,8 @@ const doc = new Document();
const table = doc.createTable(4, 4);
table
.getCell(2, 2)
.addContent(new Paragraph("Hello"))
.CellProperties.Borders.addTopBorder(BorderStyle.DASH_DOT_STROKED, 3, "red")
.addParagraph(new Paragraph("Hello"))
.Borders.addTopBorder(BorderStyle.DASH_DOT_STROKED, 3, "red")
.addBottomBorder(BorderStyle.DOUBLE, 3, "blue")
.addStartBorder(BorderStyle.DOT_DOT_DASH, 3, "green")
.addEndBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000");

View File

@ -6,10 +6,10 @@ import { Document, Media, Packer, Paragraph } from "../build";
const doc = new Document();
const table = doc.createTable(4, 4);
table.getCell(2, 2).addContent(new Paragraph("Hello"));
table.getCell(2, 2).addParagraph(new Paragraph("Hello"));
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
table.getCell(1, 1).addContent(image.Paragraph);
table.getCell(1, 1).addParagraph(image.Paragraph);
const packer = new Packer();

View File

@ -8,12 +8,12 @@ const doc = new Document();
const table = doc.createTable(2, 2);
table
.getCell(1, 1)
.addContent(new Paragraph("This text should be in the middle of the cell"))
.CellProperties.setVerticalAlign(VerticalAlign.CENTER);
.addParagraph(new Paragraph("This text should be in the middle of the cell"))
.setVerticalAlign(VerticalAlign.CENTER);
table
.getCell(1, 0)
.addContent(
.addParagraph(
new Paragraph(
"Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah",
).heading1(),

View File

@ -1,4 +1,4 @@
// Example of how you would create a table and add data to it
// Example of how you would merge cells together
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build";
@ -7,24 +7,24 @@ const doc = new Document();
let table = doc.createTable(2, 2);
table.getCell(0, 0).addContent(new Paragraph("Hello"));
table.getCell(0, 0).addParagraph(new Paragraph("Hello"));
table.getRow(0).mergeCells(0, 1);
doc.createParagraph("Another table").heading2();
table = doc.createTable(2, 3);
table.getCell(0, 0).addContent(new Paragraph("World"));
table.getCell(0, 0).addParagraph(new Paragraph("World"));
table.getRow(0).mergeCells(0, 2);
doc.createParagraph("Another table").heading2();
table = doc.createTable(2, 4);
table.getCell(0, 0).addContent(new Paragraph("Foo"));
table.getCell(0, 0).addParagraph(new Paragraph("Foo"));
table.getCell(1, 0).addContent(new Paragraph("Bar1"));
table.getCell(1, 1).addContent(new Paragraph("Bar2"));
table.getCell(1, 2).addContent(new Paragraph("Bar3"));
table.getCell(1, 3).addContent(new Paragraph("Bar4"));
table.getCell(1, 0).addParagraph(new Paragraph("Bar1"));
table.getCell(1, 1).addParagraph(new Paragraph("Bar2"));
table.getCell(1, 2).addParagraph(new Paragraph("Bar3"));
table.getCell(1, 3).addParagraph(new Paragraph("Bar4"));
table.getRow(0).mergeCells(0, 3);

View File

@ -22,7 +22,7 @@ const table = doc.createTable(2, 2).float({
table.setFixedWidthLayout();
table.setWidth(4535, WidthType.DXA);
table.getCell(0, 0).addContent(new Paragraph("Hello"));
table.getCell(0, 0).addParagraph(new Paragraph("Hello"));
table.getRow(0).mergeCells(0, 1);
const packer = new Packer();

View File

@ -6,7 +6,7 @@ import { Document, Packer, Paragraph } from "../build";
const doc = new Document();
const table = doc.createTable(4, 4);
table.getCell(2, 2).addContent(new Paragraph("Hello"));
table.getCell(2, 2).addParagraph(new Paragraph("Hello"));
const packer = new Packer();

View File

@ -2,7 +2,7 @@
> Tab stops are useful, if you are unclear of what they are, [here is a link explaining](https://en.wikipedia.org/wiki/Tab_stop). It enables side by side text which is nicely laid out without the need for tables, or constantly pressing space bar.
**Note**: At the moment, the unit of measurement for a tab stop is counter intuitive for a human. It is using OpenXMLs own measuring system. For example, 2268 roughly translates to 3cm. Therefore in the future, I may consider changing it to percentages or even cm.
!> **Note**: At the moment, the unit of measurement for a tab stop is counter intuitive for a human. It is using OpenXMLs own measuring system. For example, 2268 roughly translates to 3cm. Therefore in the future, I may consider changing it to percentages or even cm.
![Word 2013 Tabs](http://www.teachucomp.com/wp-content/uploads/blog-4-22-2015-UsingTabStopsInWord-1024x577.png "Word 2013 Tab Stops")

154
docs/usage/tables.md Normal file
View File

@ -0,0 +1,154 @@
# Tables
You can create tables with `docx`. More information can be found [here](http://officeopenxml.com/WPtable.php).
## Create Table
To create a table, simply use the `createTable()` method on a `document`.
```ts
const table = doc.createTable([NUMBER OF ROWS], [NUMBER OF COLUMNS]);
```
Alternatively, you can create a table object directly, and then add it in the `document`
```ts
const table = new Table(4, 4);
doc.addTable(table);
```
The snippet below creates a table of 2 rows and 4 columns.
```ts
const table = doc.createTable(2, 4);
// Or
const table = new Table(2, 4);
doc.addTable(table);
```
## Cells
The above section created a table with cells. To access the cell, use the `getCell` method.
```ts
const cell = table.getCell([ROW INDEX], [COLUMN INDEX]);
```
For example:
```ts
const cell = table.getCell(0, 2);
```
### Add paragraph to a cell
Once you have got the cell, you can add data to it with the `addParagraph` method.
```ts
cell.addParagraph(new Paragraph("Hello"));
```
## Borders
BorderStyle can be imported from `docx`. Size determines the thickness. HTML color can be a hex code or alias such as `red`.
```ts
cell.Borders.addTopBorder([BorderStyle], [SIZE], [HTML COLOR]);
```
```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.addStartBorder(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
Sets the vertical alignment of the contents of the cell
```ts
import { VerticalAlign } from "docx";
cell.setVerticalAlign([VerticalAlign TYPE]);
```
For example, to center align a cell:
```ts
cell.setVerticalAlign(VerticalAlign.CENTER);
```
## Rows
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.
```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]);
```
#### Example
This will merge 3 cells together starting from index `0`:
```ts
table.getRow(0).mergeCells(0, 2);
```
### Merging on a column
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
```ts
cell.addTable(new Table(1, 1));
```
## Examples
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo4.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo4.ts_

View File

@ -9,7 +9,7 @@ import { Table } from "./table";
describe("File", () => {
describe("#constructor", () => {
it("should create with correct headers", () => {
it("should create with correct headers and footers", () => {
const doc = new File();
const header = doc.createHeader();
const footer = doc.createFooter();
@ -29,6 +29,26 @@ describe("File", () => {
expect(tree["w:body"][1]["w:sectPr"][5]["w:footerReference"][0]._attr["w:type"]).to.equal("default");
});
it("should create with first headers and footers", () => {
const doc = new File();
const header = doc.createHeader();
const footer = doc.createFooter();
doc.addSection({
headers: {
first: header,
},
footers: {
first: footer,
},
});
const tree = new Formatter().format(doc.Document.Body);
expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"][0]._attr["w:type"]).to.equal("first");
expect(tree["w:body"][1]["w:sectPr"][5]["w:footerReference"][0]._attr["w:type"]).to.equal("first");
});
it("should create with correct headers", () => {
const doc = new File();
const header = doc.createHeader();
@ -60,7 +80,7 @@ describe("File", () => {
});
describe("#addParagraph", () => {
it("should call the underlying header's addParagraph", () => {
it("should call the underlying document's addParagraph", () => {
const file = new File();
const spy = sinon.spy(file.Document, "addParagraph");
file.addParagraph(new Paragraph());
@ -70,7 +90,7 @@ describe("File", () => {
});
describe("#addTable", () => {
it("should call the underlying header's addParagraph", () => {
it("should call the underlying document's addTable", () => {
const wrapper = new File();
const spy = sinon.spy(wrapper.Document, "addTable");
wrapper.addTable(new Table(1, 1));
@ -78,4 +98,68 @@ describe("File", () => {
expect(spy.called).to.equal(true);
});
});
describe("#createTable", () => {
it("should call the underlying document's createTable", () => {
const wrapper = new File();
const spy = sinon.spy(wrapper.Document, "createTable");
wrapper.createTable(1, 1);
expect(spy.called).to.equal(true);
});
});
describe("#addTableOfContents", () => {
it("should call the underlying document's addTableOfContents", () => {
const wrapper = new File();
const spy = sinon.spy(wrapper.Document, "addTableOfContents");
// tslint:disable-next-line:no-any
wrapper.addTableOfContents({} as any);
expect(spy.called).to.equal(true);
});
});
describe("#createParagraph", () => {
it("should call the underlying document's createParagraph", () => {
const wrapper = new File();
const spy = sinon.spy(wrapper.Document, "createParagraph");
wrapper.createParagraph("test");
expect(spy.called).to.equal(true);
});
});
describe("#addImage", () => {
it("should call the underlying document's addImage", () => {
const wrapper = new File();
const spy = sinon.spy(wrapper.Document, "addParagraph");
// tslint:disable-next-line:no-any
wrapper.addImage({} as any);
expect(spy.called).to.equal(true);
});
});
describe("#createImage", () => {
it("should call the underlying document's createImage", () => {
const wrapper = new File();
const spy = sinon.spy(wrapper.Media, "addMedia");
const wrapperSpy = sinon.spy(wrapper.Document, "addParagraph");
wrapper.createImage("");
expect(spy.called).to.equal(true);
expect(wrapperSpy.called).to.equal(true);
});
});
describe("#createFootnote", () => {
it("should call the underlying document's createFootnote", () => {
const wrapper = new File();
const spy = sinon.spy(wrapper.FootNotes, "createFootNote");
wrapper.createFootnote(new Paragraph(""));
expect(spy.called).to.equal(true);
});
});
});

View File

@ -281,12 +281,6 @@ export class File {
for (const header of headers) {
switch (header.type) {
case HeaderReferenceType.DEFAULT:
newGroup = {
...newGroup,
default: header.header,
};
break;
case HeaderReferenceType.FIRST:
newGroup = {
...newGroup,
@ -299,6 +293,7 @@ export class File {
even: header.header,
};
break;
case HeaderReferenceType.DEFAULT:
default:
newGroup = {
...newGroup,
@ -316,12 +311,6 @@ export class File {
for (const footer of footers) {
switch (footer.type) {
case FooterReferenceType.DEFAULT:
newGroup = {
...newGroup,
default: footer.footer,
};
break;
case FooterReferenceType.FIRST:
newGroup = {
...newGroup,
@ -334,6 +323,7 @@ export class File {
even: footer.footer,
};
break;
case FooterReferenceType.DEFAULT:
default:
newGroup = {
...newGroup,

View File

@ -8,7 +8,7 @@ import { Table } from "./table";
describe("FooterWrapper", () => {
describe("#addParagraph", () => {
it("should call the underlying header's addParagraph", () => {
it("should call the underlying footer's addParagraph", () => {
const file = new FooterWrapper(new Media(), 1);
const spy = sinon.spy(file.Footer, "addParagraph");
file.addParagraph(new Paragraph());
@ -18,10 +18,64 @@ describe("FooterWrapper", () => {
});
describe("#addTable", () => {
it("should call the underlying header's addParagraph", () => {
it("should call the underlying footer's addParagraph", () => {
const file = new FooterWrapper(new Media(), 1);
const spy = sinon.spy(file.Footer, "addTable");
file.addTable(new Table(1, 1));
expect(spy.called).to.equal(true);
});
});
describe("#createTable", () => {
it("should call the underlying footer's createTable", () => {
const wrapper = new FooterWrapper(new Media(), 1);
const spy = sinon.spy(wrapper.Footer, "addTable");
wrapper.addTable(new Table(1, 1));
const spy = sinon.spy(wrapper.Footer, "createTable");
wrapper.createTable(1, 1);
expect(spy.called).to.equal(true);
});
});
describe("#createParagraph", () => {
it("should call the underlying footer's createParagraph", () => {
const file = new FooterWrapper(new Media(), 1);
const spy = sinon.spy(file.Footer, "addParagraph");
file.createParagraph();
expect(spy.called).to.equal(true);
});
});
describe("#addImage", () => {
it("should call the underlying footer's addImage", () => {
const file = new FooterWrapper(new Media(), 1);
const spy = sinon.spy(file.Footer, "addParagraph");
// tslint:disable-next-line:no-any
file.addImage({} as any);
expect(spy.called).to.equal(true);
});
});
describe("#createImage", () => {
it("should call the underlying footer's createImage", () => {
const file = new FooterWrapper(new Media(), 1);
const spy = sinon.spy(file.Media, "addMedia");
const fileSpy = sinon.spy(file, "addImage");
file.createImage("");
expect(spy.called).to.equal(true);
expect(fileSpy.called).to.equal(true);
});
});
describe("#addChildElement", () => {
it("should call the underlying footer's addChildElement", () => {
const file = new FooterWrapper(new Media(), 1);
const spy = sinon.spy(file.Footer, "addChildElement");
// tslint:disable-next-line:no-any
file.addChildElement({} as any);
expect(spy.called).to.equal(true);
});

View File

@ -18,7 +18,7 @@ describe("HeaderWrapper", () => {
});
describe("#addTable", () => {
it("should call the underlying header's addParagraph", () => {
it("should call the underlying header's addTable", () => {
const wrapper = new HeaderWrapper(new Media(), 1);
const spy = sinon.spy(wrapper.Header, "addTable");
wrapper.addTable(new Table(1, 1));
@ -26,4 +26,58 @@ describe("HeaderWrapper", () => {
expect(spy.called).to.equal(true);
});
});
describe("#createTable", () => {
it("should call the underlying header's createTable", () => {
const wrapper = new HeaderWrapper(new Media(), 1);
const spy = sinon.spy(wrapper.Header, "createTable");
wrapper.createTable(1, 1);
expect(spy.called).to.equal(true);
});
});
describe("#createParagraph", () => {
it("should call the underlying header's createParagraph", () => {
const file = new HeaderWrapper(new Media(), 1);
const spy = sinon.spy(file.Header, "addParagraph");
file.createParagraph();
expect(spy.called).to.equal(true);
});
});
describe("#addImage", () => {
it("should call the underlying header's addImage", () => {
const file = new HeaderWrapper(new Media(), 1);
const spy = sinon.spy(file.Header, "addParagraph");
// tslint:disable-next-line:no-any
file.addImage({} as any);
expect(spy.called).to.equal(true);
});
});
describe("#createImage", () => {
it("should call the underlying header's createImage", () => {
const file = new HeaderWrapper(new Media(), 1);
const spy = sinon.spy(file.Media, "addMedia");
const fileSpy = sinon.spy(file, "addImage");
file.createImage("");
expect(spy.called).to.equal(true);
expect(fileSpy.called).to.equal(true);
});
});
describe("#addChildElement", () => {
it("should call the underlying header's addChildElement", () => {
const file = new HeaderWrapper(new Media(), 1);
const spy = sinon.spy(file.Header, "addChildElement");
// tslint:disable-next-line:no-any
file.addChildElement({} as any);
expect(spy.called).to.equal(true);
});
});
});

View File

@ -3,6 +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 { TableCellProperties } from "./table-cell-properties";
export class TableCell extends XmlComponent {
@ -14,7 +15,12 @@ export class TableCell extends XmlComponent {
this.root.push(this.properties);
}
public addContent(content: Paragraph | Table): TableCell {
public addParagraph(content: Paragraph): TableCell {
this.root.push(content);
return this;
}
public addTable(content: Table): TableCell {
this.root.push(content);
return this;
}
@ -35,11 +41,24 @@ export class TableCell extends XmlComponent {
public createParagraph(text?: string): Paragraph {
const para = new Paragraph(text);
this.addContent(para);
this.addParagraph(para);
return para;
}
public get CellProperties(): TableCellProperties {
return this.properties;
public setVerticalAlign(type: VerticalAlign): TableCell {
this.properties.setVerticalAlign(type);
return this;
}
public addGridSpan(cellSpan: number): TableCell {
this.properties.addGridSpan(cellSpan);
return this;
}
public get Borders(): TableCellBorders {
return this.properties.Borders;
}
}

View File

@ -25,7 +25,7 @@ export class TableRow extends XmlComponent {
public addGridSpan(index: number, cellSpan: number): TableCell {
const remainCell = this.cells[index];
remainCell.CellProperties.addGridSpan(cellSpan);
remainCell.addGridSpan(cellSpan);
this.cells.splice(index + 1, cellSpan - 1);
this.root.splice(index + 2, cellSpan - 1);

View File

@ -111,19 +111,19 @@ describe("Table", () => {
table
.getRow(0)
.getCell(0)
.addContent(new Paragraph("A1"));
.addParagraph(new Paragraph("A1"));
table
.getRow(0)
.getCell(1)
.addContent(new Paragraph("B1"));
.addParagraph(new Paragraph("B1"));
table
.getRow(1)
.getCell(0)
.addContent(new Paragraph("A2"));
.addParagraph(new Paragraph("A2"));
table
.getRow(1)
.getCell(1)
.addContent(new Paragraph("B2"));
.addParagraph(new Paragraph("B2"));
const tree = new Formatter().format(table);
const cell = (c) => ({
"w:tc": [
@ -149,10 +149,10 @@ describe("Table", () => {
describe("#getCell", () => {
it("returns the correct cell", () => {
const table = new Table(2, 2);
table.getCell(0, 0).addContent(new Paragraph("A1"));
table.getCell(0, 1).addContent(new Paragraph("B1"));
table.getCell(1, 0).addContent(new Paragraph("A2"));
table.getCell(1, 1).addContent(new Paragraph("B2"));
table.getCell(0, 0).addParagraph(new Paragraph("A1"));
table.getCell(0, 1).addParagraph(new Paragraph("B1"));
table.getCell(1, 0).addParagraph(new Paragraph("A2"));
table.getCell(1, 1).addParagraph(new Paragraph("B2"));
const tree = new Formatter().format(table);
const cell = (c) => ({
"w:tc": [
@ -232,7 +232,7 @@ describe("Table", () => {
it("inserts a paragraph at the end of the cell even if it has a child table", () => {
const parentTable = new Table(1, 1);
parentTable.getCell(0, 0).addContent(new Table(1, 1));
parentTable.getCell(0, 0).addTable(new Table(1, 1));
const tree = new Formatter().format(parentTable);
expect(tree)
.to.have.property("w:tbl")
@ -251,7 +251,7 @@ describe("Table", () => {
it("does not insert a paragraph if it already ends with one", () => {
const parentTable = new Table(1, 1);
parentTable.getCell(0, 0).addContent(new Paragraph("Hello"));
parentTable.getCell(0, 0).addParagraph(new Paragraph("Hello"));
const tree = new Formatter().format(parentTable);
expect(tree)
.to.have.property("w:tbl")