src/app/spreadsheet/spreadsheet-components/pipes/expression-evaluation.pipe.ts
Evaluates algebraic expressions using the Spreadsheet's state to fill-in values for Cell addresses.
It returns an Observable so pair it with the async
pipe.
<div>{{ '= d2 * 2' | expression | async }}</div>
Name | expression |
transform | ||||||
transform(value: number | string | undefined)
|
||||||
Parameters :
Returns :
Observable<string | number>
|
import { Pipe, PipeTransform } from '@angular/core'
import { Store, select } from '@ngrx/store'
import { Observable, of } from 'rxjs'
import { map } from 'rxjs/operators'
import { selectAllSpreadsheetCells } from '../../spreadsheet-data/selectors/spreadsheet-ui.selectors'
import { getCellAddressByPosition } from '../../spreadsheet-data/helpers/cell.helpers'
/**
* Evaluates algebraic expressions using the Spreadsheet's state to fill-in values for Cell addresses.
* It returns an Observable so pair it with the `async` pipe.
*
* @example
* <div>{{ '= d2 * 2' | expression | async }}</div>
*/
@Pipe({name: 'expression', pure: false})
export class ExpressionEvaluationPipe implements PipeTransform {
constructor(private store: Store<any>) {}
transform(value: number|string|undefined): Observable<string|number> {
if (typeof value === 'string') {
// Special Arithmetic Case (Expression Evaluation)
if (value.charAt(0) === '=' && value.length > 2) { // only start evaluating when there is enough
return this.store.pipe(
select(selectAllSpreadsheetCells),
map(cells => {
const expression = value
.substring(1) // get rid of the equals '='
.replace(/ /g, '') // remove spaces
.replace(/([aA-zZ]*){1}\d+/g, cellAddress => {
// Excel Cell Address Regex
// look through the cell positions for a match after converted into Excel Cell Address
const cell = cells.filter(cell => cellAddress.toUpperCase() === getCellAddressByPosition(cell.position))
return cell && cell[0] && cell[0].value ? cell[0].value.toString() : cellAddress
})
let evaluation = ''
try {
evaluation = eval(expression) // please don't do this at home! High Security risk.
} catch(error) {
// console.log('Eval error = ', error)
evaluation = '...'
}
return evaluation
})
)
}
}
return value ? of(value) : of('')
}
}