diff --git a/src/CellTemplatePool.ts b/src/CellTemplatePool.ts index 7cfdc27..0ec3bf8 100644 --- a/src/CellTemplatePool.ts +++ b/src/CellTemplatePool.ts @@ -4,14 +4,14 @@ import { BaseCell, CellType } from './cell/BaseCell'; import { NormalCell } from './cell/NormalCell'; import { VariableCell } from './cell/VariableCell'; import { FinishCell } from './cell/FinishCell'; -// import ForEachCell from "./cell/ForEachCell"; -// import ContinueCell from "./cell/ContinueCell"; -// import EndLoopCell from "./cell/EndLoopCell"; +import { ForEachCell } from './cell/ForEachCell'; +import { ContinueCell } from './cell/ContinueCell'; +import { EndLoopCell } from './cell/EndLoopCell'; import { EndRowCell } from './cell/EndRowCell'; -// import SumCell from "./cell/SumCell"; -// import AverageCell from "./cell/AverageCell"; +import { SumCell } from './cell/SumCell'; +import { AverageCell } from './cell/AverageCell'; import { DeleteCell } from './cell/DeleteCell'; -// import DumpColsCell from "./cell/DumpColsCell"; +import { DumpColsCell } from './cell/DumpColsCell'; import { WsNameCell } from './cell/WsNameCell'; import { HyperlinkCell } from './cell/HyperlinkCell'; import { FormulaCell } from './cell/FormulaCell'; @@ -23,13 +23,13 @@ export class CellTemplatePool { VariableCell, FormulaCell, HyperlinkCell, - // ForEachCell, + ForEachCell, FinishCell, - // EndLoopCell, - // ContinueCell, - // DumpColsCell, - // SumCell, - // AverageCell, + EndLoopCell, + ContinueCell, + DumpColsCell, + SumCell, + AverageCell, WsNameCell, DeleteCell, ]; diff --git a/src/cell/AverageCell.js b/src/cell/AverageCell.ts similarity index 52% rename from src/cell/AverageCell.js rename to src/cell/AverageCell.ts index 7476b8c..3512512 100644 --- a/src/cell/AverageCell.js +++ b/src/cell/AverageCell.ts @@ -1,16 +1,12 @@ -import BaseCell from "./BaseCell"; -import Scope from "../Scope"; -import {ValueType} from "exceljs"; - -export default class AverageCell extends BaseCell { - /** - * @param {Scope} scope - * @returns {AverageCell} - */ - apply(scope) { +import { BaseCell } from './BaseCell'; +import { Scope } from '../Scope'; +import { Cell, CellFormulaValue, ValueType } from 'exceljs'; + +export class AverageCell extends BaseCell { + public apply(scope: Scope): AverageCell { super.apply(scope); - const target = AverageCell._getTargetParam(scope); + const target = AverageCell.getTargetParam(scope); const __startOutput = scope.vm[target] && scope.vm[target].__startOutput; const __endOutput = scope.vm[target] && scope.vm[target].__endOutput; @@ -18,7 +14,7 @@ export default class AverageCell extends BaseCell { const start = scope.output.worksheets[scope.outputCell.ws].getCell(__startOutput, scope.outputCell.c).address; //todo refactoring const end = scope.output.worksheets[scope.outputCell.ws].getCell(__endOutput, scope.outputCell.c).address; //todo refactoring - scope.setCurrentOutputValue({formula: `average(${start}:${end})`}); + scope.setCurrentOutputValue({ formula: `average(${start}:${end})` } as CellFormulaValue); } scope.incrementCol(); @@ -26,20 +22,11 @@ export default class AverageCell extends BaseCell { return this; } - /** - * @param {Scope} scope - * @returns {string} - * @protected - */ - static _getTargetParam(scope) { - return scope.getCurrentTemplateValue().split(' ')[2]; + protected static getTargetParam(scope: Scope): string { + return scope.getCurrentTemplateValue()?.toString().split(' ')[2] || ''; } - /** - * @param {Cell} cell - * @returns {boolean} - */ - static match(cell) { + public static match(cell: Cell): boolean { return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 10) === '#! AVERAGE'; } } \ No newline at end of file diff --git a/src/cell/ContinueCell.js b/src/cell/ContinueCell.js deleted file mode 100644 index 5f90ead..0000000 --- a/src/cell/ContinueCell.js +++ /dev/null @@ -1,28 +0,0 @@ -import ForEachCell from "./ForEachCell"; -import {ValueType} from "exceljs"; - -class ContinueCell extends ForEachCell { - /** - * @inheritDoc - * @param {Scope} scope - * @returns {string} - * @protected - */ - _getFromParam(scope) { - const target = ForEachCell._getTargetParam(scope); - - return scope.vm[target] && scope.vm[target].__from; - } - - /** - * @inheritDoc - * @param {Cell} cell - * @returns {boolean} - */ - static match(cell) { - return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 11) === '#! CONTINUE'; - } - -} - -export default ContinueCell \ No newline at end of file diff --git a/src/cell/ContinueCell.ts b/src/cell/ContinueCell.ts new file mode 100644 index 0000000..d614e11 --- /dev/null +++ b/src/cell/ContinueCell.ts @@ -0,0 +1,16 @@ +import { ForEachCell } from './ForEachCell'; +import { Cell, ValueType } from 'exceljs'; +import { Scope } from '../Scope'; + +export class ContinueCell extends ForEachCell { + public static match(cell: Cell): boolean { + return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 11) === '#! CONTINUE'; + } + + public getSourceParam(scope: Scope): string { + const target = ForEachCell.getTargetParam(scope); + + return scope.vm[target] && scope.vm[target].__from; + } + +} diff --git a/src/cell/DumpColsCell.js b/src/cell/DumpColsCell.js deleted file mode 100644 index ba1fede..0000000 --- a/src/cell/DumpColsCell.js +++ /dev/null @@ -1,38 +0,0 @@ -import BaseCell from "./BaseCell"; -import {ValueType} from "exceljs"; - -export default class DumpColsCell extends BaseCell { - /** - * @inheritDoc - * @param {Scope} scope - * @returns {DumpColsCell} - */ - apply(scope) { - super.apply(scope); - - const path = scope.getCurrentTemplateValue().substring(13).split('.'); - const cols = path.reduce((p, c) => p[c] || [], scope.vm); - - scope.setCurrentOutputValue(null); - - cols.forEach((x) => { - scope.setCurrentOutputValue(x); - scope.applyStyles(); - scope.outputCell = Object.freeze({ ...scope.outputCell, c: scope.outputCell.c + 1 }); - }); - - scope.incrementCol(); - - return this; - } - - /** - * @inheritDoc - * @param {Cell} cell - * @returns {boolean} - */ - static match(cell) { - return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 12) === '#! DUMP_COLS'; - } - -} diff --git a/src/cell/DumpColsCell.ts b/src/cell/DumpColsCell.ts new file mode 100644 index 0000000..a1a8167 --- /dev/null +++ b/src/cell/DumpColsCell.ts @@ -0,0 +1,29 @@ +import { BaseCell } from './BaseCell'; +import { Cell, ValueType } from 'exceljs'; +import { Scope } from '../Scope'; + +export class DumpColsCell extends BaseCell { + static match(cell: Cell): boolean { + return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 12) === '#! DUMP_COLS'; + } + + public apply(scope: Scope): DumpColsCell { + super.apply(scope); + + const path = scope.getCurrentTemplateValue()?.toString().substring(13).split('.') || ''; + const cols = Array.from(path).reduce((p, c) => p[c] || [], scope.vm); + + scope.setCurrentOutputValue(null); + + cols.forEach((x: any) => { + scope.setCurrentOutputValue(x); + scope.applyStyles(); + scope.outputCell = Object.freeze({ ...scope.outputCell, c: scope.outputCell.c + 1 }); + }); + + scope.incrementCol(); + + return this; + } + +} diff --git a/src/cell/EndLoopCell.js b/src/cell/EndLoopCell.js deleted file mode 100644 index bc99f56..0000000 --- a/src/cell/EndLoopCell.js +++ /dev/null @@ -1,45 +0,0 @@ -import BaseCell from "./BaseCell"; -import {ValueType} from "exceljs"; - -class EndLoopCell extends BaseCell { - /** - * @inheritDoc - * @param {Scope} scope - * @returns {EndLoopCell} - */ - apply(scope) { - super.apply(scope); - - const target = scope.getCurrentTemplateValue().split(' ')[2]; - const __start = scope.vm[target] && scope.vm[target].__start; - const __iterated = scope.vm[target] && scope.vm[target].__iterated; - - scope.unfreezeOutput(); - - scope.vm[target] = Object.freeze({ - ...scope.vm[target], - __end: scope.templateCell, - __insetRows: true - }); - - if (__start && !__iterated) { - scope.templateCell = __start; - } else { - scope.incrementRow(); - } - - return this; - } - - /** - * @inheritDoc - * @param {Cell} cell - * @returns {boolean} - */ - static match(cell) { - return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 11) === '#! END_LOOP'; - } - -} - -export default EndLoopCell \ No newline at end of file diff --git a/src/cell/EndLoopCell.ts b/src/cell/EndLoopCell.ts new file mode 100644 index 0000000..0088a68 --- /dev/null +++ b/src/cell/EndLoopCell.ts @@ -0,0 +1,42 @@ +import { BaseCell } from './BaseCell'; +import { Cell, ValueType } from 'exceljs'; +import { Scope } from '../Scope'; + +export class EndLoopCell extends BaseCell { + public static match(cell: Cell): boolean { + return ( + cell && + cell.type === ValueType.String && + typeof cell.value === 'string' && + cell.value.substring(0, 11) === '#! END_LOOP' + ); + } + + public apply(scope: Scope): EndLoopCell { + super.apply(scope); + + const target = + scope + .getCurrentTemplateValue() + ?.toString() + .split(' ')[2] || ''; + const __start = scope.vm[target] && scope.vm[target].__start; + const __iterated = scope.vm[target] && scope.vm[target].__iterated; + + scope.unfreezeOutput(); + + scope.vm[target] = Object.freeze({ + ...scope.vm[target], + __end: scope.templateCell, + __insetRows: true, + }); + + if (__start && !__iterated) { + scope.templateCell = __start; + } else { + scope.incrementRow(); + } + + return this; + } +} diff --git a/src/cell/ForEachCell.js b/src/cell/ForEachCell.ts similarity index 68% rename from src/cell/ForEachCell.js rename to src/cell/ForEachCell.ts index 3baf630..846da6f 100644 --- a/src/cell/ForEachCell.js +++ b/src/cell/ForEachCell.ts @@ -1,14 +1,14 @@ -import BaseCell from "./BaseCell"; -import Scope from "../Scope"; -import {ValueType} from "exceljs"; +import { BaseCell } from './BaseCell'; +import { Scope } from '../Scope'; +import { Cell, ValueType } from 'exceljs'; /** - * Pattern: `#! FOR_EACH [TARGET] [FROM]` - * Iterate through `vm[FROM]` and store current item in readonly `vm[TARGET]`. + * Pattern: `#! FOR_EACH [TARGET] [SOURCE]` + * Iterate through `vm[SOURCE]` and store current item in readonly `vm[TARGET]`. * `vm[TARGET]` has additional fields: * - * * `__from` - keeps `FROM` parameter's value - * * `__index` - current 1-based iteration index (`vm[TARGET]` is `vm[FROM][__index-1]`) + * * `__from` - keeps `SOURCE` parameter's value + * * `__index` - current 1-based iteration index (`vm[TARGET]` is `vm[SOURCE][__index-1]`) * * `__start` - template foreach start cell * * `__end` - template loop's end cell, it is undefined before first `END_LOOP` * * `__iterated` - iteration has been finished @@ -16,14 +16,23 @@ import {ValueType} from "exceljs"; * * `__startOutput` - first output cell * * `__endOutput` - last output cell */ -class ForEachCell extends BaseCell { - /** - * @param {Scope} scope - * @returns {ForEachCell} - */ - apply(scope) { - const target = ForEachCell._getTargetParam(scope); - const __from = this._getFromParam(scope); +export class ForEachCell extends BaseCell { + public static match(cell: Cell): boolean { + return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 11) === '#! FOR_EACH'; + } + + protected static getTargetParam(scope: Scope): string { + return scope.getCurrentTemplateValue()?.toString().split(' ')[2] || ''; + } + + protected getSourceParam(scope: Scope): string { + return scope.getCurrentTemplateValue()?.toString().split(' ')[3] || ''; + } + + + public apply(scope: Scope): ForEachCell { + const target = ForEachCell.getTargetParam(scope); + const __from = this.getSourceParam(scope); //todo refactoring const __index = (scope.vm[target] && scope.vm[target].__index || 0) + 1; @@ -56,11 +65,10 @@ class ForEachCell extends BaseCell { __insetRows = false; if (!scope.isFrozen()) { for (let i = __end.r; i > __start.r; i--) { - // noinspection JSCheckFunctionSignatures - todo exceljs signature mismatch scope.output.worksheets[scope.outputCell.ws].spliceRows( //todo refactoring scope.outputCell.r + 1, 0, - scope.template.worksheets[scope.templateCell.ws].getRow(i), + [], ); } } @@ -87,33 +95,4 @@ class ForEachCell extends BaseCell { return this; } - - /** - * @param {Scope} scope - * @returns {string} - * @protected - */ - static _getTargetParam(scope) { - return scope.getCurrentTemplateValue().split(' ')[2]; - } - - /** - * @param {Scope} scope - * @returns {string} - * @protected - */ - _getFromParam(scope) { - return scope.getCurrentTemplateValue().split(' ')[3]; - } - - - /** - * @param {Cell} cell - * @returns {boolean} - */ - static match(cell) { - return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 11) === '#! FOR_EACH'; - } } - -export default ForEachCell \ No newline at end of file diff --git a/src/cell/SumCell.js b/src/cell/SumCell.ts similarity index 53% rename from src/cell/SumCell.js rename to src/cell/SumCell.ts index e158834..80b4d1d 100644 --- a/src/cell/SumCell.js +++ b/src/cell/SumCell.ts @@ -1,16 +1,20 @@ -import BaseCell from "./BaseCell"; -import Scope from "../Scope"; -import {ValueType} from "exceljs"; - -export default class SumCell extends BaseCell { - /** - * @param {Scope} scope - * @returns {SumCell} - */ - apply(scope) { +import { BaseCell } from './BaseCell'; +import { Scope } from '../Scope'; +import { Cell, CellFormulaValue, ValueType } from 'exceljs'; + +export class SumCell extends BaseCell { + public static match(cell: Cell): boolean { + return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 6) === '#! SUM'; + } + + protected static getTargetParam(scope: Scope): string { + return scope.getCurrentTemplateValue()?.toString().split(' ')[2] || ''; + } + + public apply(scope: Scope): SumCell { super.apply(scope); - const target = SumCell._getTargetParam(scope); + const target = SumCell.getTargetParam(scope); const __startOutput = scope.vm[target] && scope.vm[target].__startOutput; const __endOutput = scope.vm[target] && scope.vm[target].__endOutput; @@ -18,28 +22,11 @@ export default class SumCell extends BaseCell { const start = scope.output.worksheets[scope.outputCell.ws].getCell(__startOutput, scope.outputCell.c).address; //todo refactoring const end = scope.output.worksheets[scope.outputCell.ws].getCell(__endOutput, scope.outputCell.c).address; //todo refactoring - scope.setCurrentOutputValue({formula: `sum(${start}:${end})`}); + scope.setCurrentOutputValue({ formula: `sum(${start}:${end})` } as CellFormulaValue); } scope.incrementCol(); return this; } - - /** - * @param {Scope} scope - * @returns {string} - * @protected - */ - static _getTargetParam(scope) { - return scope.getCurrentTemplateValue().split(' ')[2]; - } - - /** - * @param {Cell} cell - * @returns {boolean} - */ - static match(cell) { - return cell && cell.type === ValueType.String && typeof cell.value === 'string' && cell.value.substring(0, 6) === '#! SUM'; - } } \ No newline at end of file