diff --git a/.gitignore b/.gitignore
index 543ecab..5b048cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,8 +3,4 @@
/.idea
/coverage/
/.nyc_output/
-/.idea/
-
-
-/src/example.ts
-*.xlsx
\ No newline at end of file
+/.idea/
\ No newline at end of file
diff --git a/README.md b/README.md
index d263d30..c45a579 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,12 @@
# WIP current version of lib is under developing
+# Introduction
+
+This library makes generating xlsx files (Excel) easly.
+
+It consumes template which is common Excel file, then add yours data (called ViewModel). Blend it and done, as result you'll get pretty Excel.
+
# Getting Started:
1. install package
@@ -11,50 +17,58 @@
npm i xlsx-renderer --save
```
-`npm install`
+2. TODO add some example here (https://github.com/Siemienik/xlsx-renderer/issues/6)
-## In Cell Commands:
-
-1. `## varToDisplayInThisCell`
-2. `#! FINISH` - finish processing current worksheet
-2. `#! FINISH booleanVar` - if true it finishes processing current template worksheet, if false it add again this worksheet to output
-3. `#! END_ROW`
-4. `#! DELETE varName`
-5. `#! HYPERLINK labelVar urlVar`
-6. `#! WS_NAME nameVar` set worksheet name
-7. `#! FOR_EACH item collection` (to write item property `## item.property`),
-8. `#! CONTINUE item` item is set to the next collection item.
-9. `#! END_LOOP item`
-10. `#! AVERAGE item` write average formula of all items from previous for-each, it has to be placed after the for-each was finished.
-11. `#! SUM item` similar to average
-12. `#! DUMP_COLS arrayVar` write to next columns all array items (1 item = 1 column)
-
-
-## Sample code: (possible to be outdated yet - todo)
+## Sample code:
```javascript
import Renderer from './xls-renderer/Renderer'
-import {Workbook} from 'exceljs'
-
-//*
-import DebugCellTemplatePool from "./xls-renderer-debug/CellTemplateDebugPool";
-const renderer = new Renderer(new DebugCellTemplatePool());
-/*/
-import CellTemplatePool from "./xls-renderer/CellTemplatePool";
-const renderer = new Renderer(new CellTemplatePool());
-//*/
-
const viewModel = new MyAwesomeReportVm(); //or something else
(async () => {
- const result = await renderer.render(async () => {
- const template = new Workbook();
- return await template.xlsx.readFile('./my-awesome-raport-template.xlsx');
- }, viewModel);
+ const result = await renderer.renderFromFile('./my-awesome-raport-template.xlsx', viewModel);
await result.xlsx.writeFile('./my-awesome-raport.xlsx');
})();
```
+
+# Documentation:
+
+## Cells:
+
+| Category | Name | Order | match rule | Description | More info |
+|----------|-----:|-------|--------|-------------|:---------|
+| - | [BaseCell](./src/cell/BaseCell.ts) | n/o | n/o | All Cell\`s definition classes extend it. | **abstract** |
+| Content | [NormalCell](./src/cell/NormalCell.ts) | 1 | not started by `##` or `#!` | This one copy all styles, width, properties and value form template. | **default** |
+| Content | [VariableCell](./src/cell/VariableCell.ts) | 3 | `## pathToVariable ` | Write variable from `ViewModel`.
Paths to object's property or array item are allowed. | **Examples:**
`simplePath`
`someObject.property`
`array.0.field`
`items.1.path.to.object.prop`|
+| Content | **TODO: describe it!** [HyperlinkCell](./src/cell/HyperlinkCell.ts) | | | | |
+| Content | **TODO: describe it!** [FormulaCell](./src/cell/FormulaCell.ts) | | | | |
+| Navigation | **TODO: describe it!** [EndRowCell](./src/cell/EndRowCell.ts) | | | | |
+| Worksheet
Navigation
Loop | [FinishCell](./src/cell/FinishCell.ts) | 7 | `#! FINISH conditionPath` | Finish rendering for current worksheet and:
1) go to next worksheet if `conditionPath===true`
2) repeat this template worksheet again (`conditionPath === false`) - looping through worksheets
3) finished whole rendering when this worksheet is the last one. | **Examples:**
`#! FINISHED ` or `#! FINISHED itemFromLoop.__iterated` |
+| Worksheet | **TODO: describe it!** [WsNameCell](./src/cell/WsNameCell.ts) | | | | |
+| View Model | **TODO: describe it!** [DeleteCell](./src/cell/DeleteCell.ts) | | | | |
+| Loop | **TODO: describe it!** [DumpColsCell](./src/cell/DumpColsCell.ts) | | | | |
+| Loop | **TODO: describe it!** [ForEachCell](./src/cell/ForEachCell.ts) | | | | |
+| Loop | **TODO: describe it!** [ContinueCell](./src/cell/ContinueCell.ts) | | | | |
+| Loop | **TODO: describe it!** [EndLoopCell](./src/cell/EndLoopCell.ts) | | | | |
+| Aggregation | **TODO: describe it!** [AverageCell](./src/cell/AverageCell.ts) | | | | |
+| Aggregation| **TODO: describe it!** [SumCell](./src/cell/SumCell.ts) | | | | |
+
+
+## Commands [PREVIOUS VERSION]:
+
+1. `#! END_ROW`
+4. `#! DELETE varName`
+5. `#! HYPERLINK labelVar urlVar`
+6. `#! WS_NAME nameVar` set worksheet name
+7. `#! FOR_EACH item collection` (to write item property `## item.property`),
+8. `#! CONTINUE item` item is set to the next collection item.
+9. `#! END_LOOP item`
+10. `#! AVERAGE item` write average formula of all items from previous for-each, it has to be placed after the for-each was finished.
+11. `#! SUM item` similar to average
+12. `#! DUMP_COLS arrayVar` write to next columns all array items (1 item = 1 column)
+
+
[LICENSE](LICENSE)
diff --git a/package.json b/package.json
index e34fe8f..0132259 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"postversion": "git push && git push --tags"
},
"devDependencies": {
+ "@types/node": "^12.12.6",
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.6",
"chai": "^4.2.0",
diff --git a/src/Renderer.ts b/src/Renderer.ts
index fa36b30..203a56f 100644
--- a/src/Renderer.ts
+++ b/src/Renderer.ts
@@ -19,4 +19,13 @@ export class Renderer {
return output;
}
+
+ public async renderFromFile(templatePath: string, viewModel: any): Promise {
+ const result = await this.render(async () => {
+ const template = new Workbook();
+ return await template.xlsx.readFile(templatePath);
+ }, viewModel);
+
+ return await result;
+ }
}
diff --git a/src/cell/BaseCell.ts b/src/cell/BaseCell.ts
index 93d1c9b..082c023 100644
--- a/src/cell/BaseCell.ts
+++ b/src/cell/BaseCell.ts
@@ -4,7 +4,7 @@ import { Scope } from '../Scope';
export declare type CellType = typeof BaseCell;
-export class BaseCell {
+export /* abstract */ class BaseCell { // can't be abstract :(
/**
* check if this commend can parse `value`
*/
@@ -12,7 +12,7 @@ export class BaseCell {
return false;
}
- public BaseCell() {
+ public BaseCell() { // can't be marked by abstract keyword, so it throw type error.
throw new TypeError(`Cannot construct ${BaseCell.name} instances directly. It's abstract.`);
}
diff --git a/src/example.ts b/src/example.ts
deleted file mode 100644
index 64e9431..0000000
--- a/src/example.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Renderer } from './Renderer';
-import { CellTemplateDebugPool } from './CellTemplateDebugPool';
-import { CellTemplatePool } from './CellTemplatePool';
-import { Workbook } from 'exceljs';
-
-// tslint:disable:comment-format
-//*
-const debug = true;
-/*/
-const debug = false;
-//*/
-
-let renderer;
-if (debug) {
- renderer = new Renderer(new CellTemplateDebugPool());
-} else {
- renderer = new Renderer(new CellTemplatePool());
-}
-
-(async () => {
- const result = await renderer.render(async () => {
- const template = new Workbook();
- return await template.xlsx.readFile('./my-awesome-raport-template.xlsx');
- }, {});
-
- await result.xlsx.writeFile('./my-awesome-raport.xlsx');
-})();
diff --git a/tests/integration/Renderer.ts b/tests/integration/Renderer.ts
new file mode 100644
index 0000000..c47a12c
--- /dev/null
+++ b/tests/integration/Renderer.ts
@@ -0,0 +1,92 @@
+import {Renderer} from "../../src/Renderer";
+import * as fs from "fs";
+import * as path from "path";
+import {Workbook} from "exceljs";
+import * as chai from 'chai'
+
+
+function assertCells(expected: Workbook, result: Workbook, factor: number = 10) {
+ chai.expect(expected.worksheets.length).eql(result.worksheets.length);
+ chai.expect(expected.worksheets.map(x => x.name)).eql(result.worksheets.map(x => x.name));
+
+ for (let wi = 0; wi < expected.worksheets.length; wi++) {
+ const ws = {e: expected.worksheets[wi], r: result.worksheets[wi]};
+ for (let i = 0; i < factor * factor; i++) {
+ const r = Math.floor(i / factor) + 1;
+ const c = i % factor + 1;
+ const cell = {
+ e: ws.e.getCell(r, c),
+ r: ws.r.getCell(r, c)
+ };
+
+
+ if (r === 1) {
+ chai.expect(ws.e.getColumn(c).width).eql(ws.r.getColumn(c).width);
+ }
+ if (c === 1) {
+ chai.expect(ws.e.getRow(r).height).eql(ws.r.getRow(r).height);
+ }
+
+ chai.expect(cell.e.style).eql(cell.r.style);
+ chai.expect(cell.e.text).eql(cell.r.text);
+ chai.expect(cell.e.value).eql(cell.r.value);
+ }
+ }
+}
+
+describe('INTEGRATION:: Test xlsx renderer ', function () {
+
+ describe('Checking if assertCells works ok.', function () {
+ it('Same - should pass ok', async function () {
+ const expected = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'main.xlsx'));
+ const correct = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'correct.xlsx'));
+
+ assertCells(expected, correct, 20);
+ });
+
+ it('Different - attempt to broke assertions', async function () {
+ const expected = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'main.xlsx'));
+ const failedWorksheetAmount = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'f-ws-amount.xlsx'));
+ const failedWorksheetNames = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'f-ws-names.xlsx'));
+ const failedWidth = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'f-width.xlsx'));
+ const failedHeight = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'f-height.xlsx'));
+ const failedStyle = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'f-style.xlsx'));
+ const failedText = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'f-text.xlsx'));
+ const failedValue = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'f-value.xlsx'));
+ const failedTable = await new Workbook().xlsx.readFile(path.join(__dirname, 'data', 'assertCells', 'f-table.xlsx'));
+
+ chai.expect(() => assertCells(expected, failedWorksheetAmount, 20)).throw("expected 2 to deeply equal 3");
+ chai.expect(() => assertCells(expected, failedWorksheetNames, 20)).throw('expected [ \'Sheet1\', \'Sheet2\' ] to deeply equal [ \'Sheet1\', \'Sheet3\' ]');
+ chai.expect(() => assertCells(expected, failedWidth, 20)).throw("expected 13 to deeply equal 7.90625");
+ chai.expect(() => assertCells(expected, failedHeight, 20)).throw("expected 15 to deeply equal 34.5");
+ chai.expect(() => assertCells(expected, failedStyle, 20)).throw("expected { Object (font, border, ...) } to deeply equal { Object (font, border, ...) }");
+ chai.expect(() => assertCells(expected, failedText, 20)).throw('expected \'sadasd\' to deeply equal \'sadas\'');
+ chai.expect(() => assertCells(expected, failedValue, 20)).throw('expected { Object (formula, result) } to deeply equal \'asdasda\'');
+ chai.expect(() => assertCells(expected, failedTable, 20)).throw('expected { Object (font, border, ...) } to deeply equal { Object (font, border, ...) }');
+ });
+ });
+ describe('Load examples, render and compare with expected result', function () {
+ const dataPath = path.normalize(path.join(__dirname, 'data/'));
+ const sets = fs.readdirSync(path.normalize(dataPath), {withFileTypes: true})
+ .filter(i => i.isDirectory())
+ .filter(d => /^Renderer[0-9]*-/.test(d.name));
+
+
+ const renderer = new Renderer();
+ sets.forEach(s => {
+ it(`Test for ${s.name}`, async function () {
+ const result = await renderer.renderFromFile(
+ path.join(dataPath, s.name, "template.xlsx"),
+ require(path.join(dataPath, s.name, 'viewModel.json'))
+ );
+
+ const expected = await new Workbook().xlsx.readFile(path.join(dataPath, s.name, "expected.xlsx"));
+
+ assertCells(expected, result);
+ });
+
+
+ })
+
+ });
+});
\ No newline at end of file
diff --git a/tests/integration/data/Renderer000-FinishCell/expected.xlsx b/tests/integration/data/Renderer000-FinishCell/expected.xlsx
new file mode 100644
index 0000000..b4eb627
Binary files /dev/null and b/tests/integration/data/Renderer000-FinishCell/expected.xlsx differ
diff --git a/tests/integration/data/Renderer000-FinishCell/template.xlsx b/tests/integration/data/Renderer000-FinishCell/template.xlsx
new file mode 100644
index 0000000..decb5f3
Binary files /dev/null and b/tests/integration/data/Renderer000-FinishCell/template.xlsx differ
diff --git a/tests/integration/data/Renderer000-FinishCell/viewModel.json b/tests/integration/data/Renderer000-FinishCell/viewModel.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/integration/data/Renderer000-FinishCell/viewModel.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/integration/data/assertCells/correct.xlsx b/tests/integration/data/assertCells/correct.xlsx
new file mode 100644
index 0000000..aaf5eff
Binary files /dev/null and b/tests/integration/data/assertCells/correct.xlsx differ
diff --git a/tests/integration/data/assertCells/f-height.xlsx b/tests/integration/data/assertCells/f-height.xlsx
new file mode 100644
index 0000000..25e9730
Binary files /dev/null and b/tests/integration/data/assertCells/f-height.xlsx differ
diff --git a/tests/integration/data/assertCells/f-style.xlsx b/tests/integration/data/assertCells/f-style.xlsx
new file mode 100644
index 0000000..87a096e
Binary files /dev/null and b/tests/integration/data/assertCells/f-style.xlsx differ
diff --git a/tests/integration/data/assertCells/f-table.xlsx b/tests/integration/data/assertCells/f-table.xlsx
new file mode 100644
index 0000000..2796514
Binary files /dev/null and b/tests/integration/data/assertCells/f-table.xlsx differ
diff --git a/tests/integration/data/assertCells/f-text.xlsx b/tests/integration/data/assertCells/f-text.xlsx
new file mode 100644
index 0000000..c57cb10
Binary files /dev/null and b/tests/integration/data/assertCells/f-text.xlsx differ
diff --git a/tests/integration/data/assertCells/f-value.xlsx b/tests/integration/data/assertCells/f-value.xlsx
new file mode 100644
index 0000000..60bf56e
Binary files /dev/null and b/tests/integration/data/assertCells/f-value.xlsx differ
diff --git a/tests/integration/data/assertCells/f-width.xlsx b/tests/integration/data/assertCells/f-width.xlsx
new file mode 100644
index 0000000..0d7bf6e
Binary files /dev/null and b/tests/integration/data/assertCells/f-width.xlsx differ
diff --git a/tests/integration/data/assertCells/f-ws-amount.xlsx b/tests/integration/data/assertCells/f-ws-amount.xlsx
new file mode 100644
index 0000000..a9b218c
Binary files /dev/null and b/tests/integration/data/assertCells/f-ws-amount.xlsx differ
diff --git a/tests/integration/data/assertCells/f-ws-names.xlsx b/tests/integration/data/assertCells/f-ws-names.xlsx
new file mode 100644
index 0000000..9d41240
Binary files /dev/null and b/tests/integration/data/assertCells/f-ws-names.xlsx differ
diff --git a/tests/integration/data/assertCells/main.xlsx b/tests/integration/data/assertCells/main.xlsx
new file mode 100644
index 0000000..d4ce6eb
Binary files /dev/null and b/tests/integration/data/assertCells/main.xlsx differ