Skip to content

Commit 05e019b

Browse files
authored
Merge branch 'singerla:main' into main
2 parents a6e3903 + 41b31bf commit 05e019b

20 files changed

+619
-109
lines changed

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,39 @@ Find out more about formatting cells:
559559
- [Modify and style table cells](https://github.com/singerla/pptx-automizer/blob/main/__tests__/modify-existing-table.test.ts)
560560
- [Insert data into table with empty cells](https://github.com/singerla/pptx-automizer/blob/main/__tests__/modify-existing-table-create-text.test.ts)
561561

562+
563+
If you need to add rows or columns in a table with merged cells, you can add tags to your template table to expand it:
564+
```ts
565+
slide.modifyElement(
566+
'NestedTable3',
567+
modify.setTable(tableData, {
568+
adjustHeight: false,
569+
adjustWidth: false,
570+
expand: [
571+
{
572+
// Find a cell containing '{{each:row}}' and
573+
// clone it 3 times row-wise
574+
mode: 'row',
575+
tag: '{{each:row}}',
576+
count: 3,
577+
},
578+
{
579+
// Find a cell containing '{{each:sub}}' and
580+
// clone it once column-wise. Merged cells will
581+
// be cloned as well.
582+
mode: 'column',
583+
tag: '{{each:sub}}',
584+
count: 1,
585+
},
586+
],
587+
}),
588+
);
589+
```
590+
591+
Please find some examples in the tests:
592+
- [Expand a table with merged cells](https://github.com/singerla/pptx-automizer/blob/main/__tests__/modify-nested-table.test.ts)
593+
594+
562595
## Modify Charts
563596

564597
All data and styles of a chart can be modified. Please note that if your template contains more data than your data object, Automizer will remove these extra nodes. Conversely, if you provide more data, new nodes will be cloned from the first existing one in the template.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import Automizer, { CmToDxa, modify, TableData } from '../src/index';
2+
3+
test('update row hight/column width in a nested table', async () => {
4+
const automizer = new Automizer({
5+
templateDir: `${__dirname}/pptx-templates`,
6+
outputDir: `${__dirname}/pptx-output`,
7+
});
8+
9+
const pres = automizer
10+
.loadRoot(`RootTemplate.pptx`)
11+
.load(`NestedTables.pptx`, 'tables');
12+
13+
await pres
14+
.addSlide('tables', 4, async (slide) => {
15+
const tableData: TableData = {
16+
body: [
17+
{ values: ['top left', 123, 345, 'subsub3-1', 'subsub3-2', 'Last'] },
18+
{ values: [undefined, 't1', 't2', 't3', 't3', ''] },
19+
{ values: ['label 0', 1, 2, 3, 3, 'l0'] },
20+
{ values: ['label 1', 123, 345, 4563, 4671, 'l1'] },
21+
{ values: ['label 2', 123, 345, 4562, 4672] },
22+
{ values: ['label 3', 123, 345, 4561, 4673, 'l3'] },
23+
{ values: [undefined, 'Foo', 'ter', 4564, 4674, ''] },
24+
],
25+
};
26+
27+
slide.modifyElement('NestedTable3', [
28+
modify.setTable(tableData, {
29+
expand: [
30+
{
31+
mode: 'row',
32+
tag: '{{each:row}}',
33+
count: 3,
34+
},
35+
{
36+
mode: 'column',
37+
tag: '{{each:subSub3}}',
38+
count: 1,
39+
},
40+
],
41+
}),
42+
// Update first column width to 8cm
43+
modify.updateColumnWidth(0, CmToDxa(8)),
44+
// Update last row's height to 3cm
45+
modify.updateRowHeight(6, CmToDxa(3)),
46+
// Will also work on non-nested tables
47+
]);
48+
})
49+
.write(`modify-nested-table-grid-size.test.pptx`);
50+
51+
// expect(data.length).toBe(12);
52+
});
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import Automizer, { modify, TableData } from '../src/index';
2+
3+
test('modify a nested table with tags', async () => {
4+
const automizer = new Automizer({
5+
templateDir: `${__dirname}/pptx-templates`,
6+
outputDir: `${__dirname}/pptx-output`,
7+
});
8+
9+
const pres = automizer
10+
.loadRoot(`RootTemplate.pptx`)
11+
.load(`NestedTables.pptx`, 'tables');
12+
13+
await pres
14+
.addSlide('tables', 3, async (slide) => {
15+
const tableData: TableData = {
16+
body: [
17+
{
18+
values: [
19+
'top left',
20+
'sub-1',
21+
null,
22+
null,
23+
'sub-2',
24+
null,
25+
null,
26+
'Last',
27+
],
28+
styles: [
29+
{
30+
border: [
31+
{
32+
tag: 'lnB',
33+
weight: 35000,
34+
color: {
35+
type: 'srgbClr',
36+
value: 'aacc00',
37+
},
38+
},
39+
],
40+
},
41+
{
42+
border: [
43+
{
44+
tag: 'lnB',
45+
weight: 8500,
46+
type: 'sysDot',
47+
color: {
48+
type: 'srgbClr',
49+
value: 'aacc00',
50+
},
51+
},
52+
{
53+
tag: 'lnR',
54+
weight: 8500,
55+
type: 'sysDot',
56+
color: {
57+
type: 'srgbClr',
58+
value: 'aacc00',
59+
},
60+
},
61+
],
62+
},
63+
],
64+
},
65+
{ values: [undefined, 't1', 't2', 't3', 't3', 't3', 't3', ''] },
66+
{ values: ['label 0', 1, 2, 3, 3, 't3', 't3', 'l0'] },
67+
{ values: ['label 1', 123, 345, 4563, 4671, 't3', 't3', 'l1'] },
68+
{ values: ['label 2', 123, 345, 4562, 4672] },
69+
{ values: ['label 3', 123, 345, 4561, 4673, 't3', 't3', 'l3'] },
70+
{ values: ['', 'Foo', 'ter', 4564, 'foo2', 't3', 't3', ''] },
71+
],
72+
};
73+
74+
slide.modifyElement(
75+
'NestedTable3',
76+
modify.setTable(tableData, {
77+
expand: [
78+
{
79+
mode: 'row',
80+
tag: '{{each:row}}',
81+
count: 3,
82+
},
83+
{
84+
mode: 'column',
85+
tag: '{{each:subSub2}}',
86+
count: 1,
87+
},
88+
{
89+
mode: 'column',
90+
tag: '{{each:sub}}',
91+
count: 1,
92+
},
93+
],
94+
}),
95+
);
96+
})
97+
.addSlide('tables', 4, async (slide) => {
98+
const tableData: TableData = {
99+
body: [
100+
{ values: ['top left', 123, 345, 'subsub3-1', 'subsub3-2', 'Last'] },
101+
{ values: [undefined, 't1', 't2', 't3', 't3', ''] },
102+
{ values: ['label 0', 1, 2, 3, 3, 'l0'] },
103+
{ values: ['label 1', 123, 345, 4563, 4671, 'l1'] },
104+
{ values: ['label 2', 123, 345, 4562, 4672] },
105+
{ values: ['label 3', 123, 345, 4561, 4673, 'l3'] },
106+
{ values: [undefined, 'Foo', 'ter', 4564, 4674, ''] },
107+
],
108+
};
109+
110+
slide.modifyElement(
111+
'NestedTable3',
112+
modify.setTable(tableData, {
113+
expand: [
114+
{
115+
mode: 'row',
116+
tag: '{{each:row}}',
117+
count: 3,
118+
},
119+
{
120+
mode: 'column',
121+
tag: '{{each:subSub3}}',
122+
count: 1,
123+
},
124+
],
125+
}),
126+
);
127+
})
128+
.write(`modify-nested-table.test.pptx`);
129+
130+
// expect(data.length).toBe(12);
131+
});
43.5 KB
Binary file not shown.

__tests__/read-image-alt-text.test.ts

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,21 @@
11
import Automizer from '../src/index';
2-
import { ElementInfo } from '../src/types/xml-types';
32

4-
test('read alt text info', async () => {
3+
test('read alt text from image', async () => {
54
const automizer = new Automizer({
65
templateDir: `${__dirname}/pptx-templates`,
76
outputDir: `${__dirname}/pptx-output`,
87
});
98

109
const pres = automizer
1110
.loadRoot(`RootTemplate.pptx`)
12-
.load(`SlideWithImages.pptx`, 'images')
13-
.load(`ChartBarsStacked.pptx`, 'charts');
11+
.load(`SlideWithImages.pptx`, 'images');
1412

15-
// A simple helper to get/set ElementInfo
16-
const info = {
17-
element: <Promise<ElementInfo>>{},
18-
set: (elementInfo: Promise<ElementInfo>) => {
19-
info.element = elementInfo;
20-
},
21-
get: async (): Promise<ElementInfo> => {
22-
return info.element;
23-
},
24-
};
25-
let altText = '';
26-
pres
27-
.addSlide('images', 1, async (slide) => {
28-
// Read another shape and print its text fragments:
29-
const eleInfo = await slide.getElement('Grafik 5');
30-
altText = eleInfo.altText;
31-
});
13+
let altText = '';
14+
pres.addSlide('images', 1, async (slide) => {
15+
// Read alt text from an image:
16+
const eleInfo = await slide.getElement('Grafik 5');
17+
altText = eleInfo.getAltText();
18+
});
3219

3320
await pres.write(`read-alt-text.test.pptx`);
3421

__tests__/read-table-data.test.ts

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Automizer, { XmlElement } from '../src/index';
2-
import { ChartModificationCallback } from '../src/types/types';
1+
import Automizer from '../src/index';
2+
import { TableInfo } from '../src/types/table-types';
33

44
test('read table data from slide', async () => {
55
const automizer = new Automizer({
@@ -10,40 +10,19 @@ test('read table data from slide', async () => {
1010
const pres = automizer
1111
.loadRoot(`RootTemplate.pptx`)
1212
.load(`SlideWithTables.pptx`, 'tables');
13-
const data = [];
1413

15-
const readTableData =
16-
(data: any): ChartModificationCallback =>
17-
(element: XmlElement): void => {
18-
// XmlHelper.dump(element);
19-
const rows = element.getElementsByTagName('a:tr');
20-
for (let r = 0; r < rows.length; r++) {
21-
const row = rows.item(r);
22-
// XmlHelper.dump(row);
23-
const columns = row.getElementsByTagName('a:tc');
24-
for (let c = 0; c < columns.length; c++) {
25-
const cell = columns.item(c);
26-
// XmlHelper.dump(cell);
27-
const texts = cell.getElementsByTagName('a:t');
28-
for (let t = 0; t < texts.length; t++) {
29-
data.push({
30-
row: r,
31-
column: c,
32-
text: texts.item(t).textContent,
33-
});
34-
}
35-
}
36-
}
37-
};
14+
let data = <TableInfo[]>[];
3815

3916
await pres
40-
.addSlide('tables', 1, (slide) => {
41-
slide.modifyElement('TableWithLabels', [readTableData(data)]);
17+
.addSlide('tables', 1, async (slide) => {
18+
const tableInfo = await slide.getElement('TableWithLabels');
19+
20+
data = tableInfo.getTableInfo();
4221
})
4322
.write(`read-table-data.test.pptx`);
4423

4524
// We have 12 text values in a 3x3 table:
46-
// console.log(data);
25+
console.log(data.map((data) => data.textContent));
4726

4827
expect(data.length).toBe(12);
4928
});

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pptx-automizer",
3-
"version": "0.5.0",
3+
"version": "0.5.1",
44
"description": "A template based pptx generator",
55
"repository": {
66
"type": "git",

src/automizer.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,7 @@ import { IPresentationProps } from './interfaces/ipresentation-props';
1212
import { PresTemplate } from './interfaces/pres-template';
1313
import { RootPresTemplate } from './interfaces/root-pres-template';
1414
import { Template } from './classes/template';
15-
import {
16-
ModifyXmlCallback,
17-
SlideInfo,
18-
TemplateInfo,
19-
XmlElement,
20-
} from './types/xml-types';
15+
import { ModifyXmlCallback, TemplateInfo } from './types/xml-types';
2116
import { GeneralHelper, vd } from './helper/general-helper';
2217
import { Master } from './classes/master';
2318
import path from 'path';

0 commit comments

Comments
 (0)