Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pu/aggregation fix #515

Merged
merged 25 commits into from
Sep 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed bug when undoing irreversible operation. (#502)
- Fixed minor issue with CHAR function logic. (#510)
- Fixed `simpleCellAddressToString` behaviour when converting quoted sheet names. (#514)
- Fixed issues with numeric aggregation functions (#515)

## [0.1.3] - 2020-07-21

Expand Down
112 changes: 0 additions & 112 deletions src/interpreter/ArithmeticHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,118 +311,6 @@ export function divide(left: number, right: number): number | CellError {
}
}

/**
* Returns max from two numbers
*
* Implementation of max function which is used in interpreter.
*
* Errors are propagated, non-numerical values are neutral.
*
* @param left - left operand of addition
* @param right - right operand of addition
*/
export function max(left: InternalScalarValue, right: InternalScalarValue): InternalScalarValue {
if (left instanceof CellError) {
return left
}
if (right instanceof CellError) {
return right
}
if (typeof left === 'number') {
if (typeof right === 'number') {
return Math.max(left, right)
} else {
return left
}
} else if (typeof right === 'number') {
return right
} else {
return Number.NEGATIVE_INFINITY
}
}

export function maxa(left: InternalScalarValue, right: InternalScalarValue): InternalScalarValue {
if (left instanceof CellError) {
return left
}
if (right instanceof CellError) {
return right
}
if (typeof left === 'boolean') {
left = coerceBooleanToNumber(left)
}
if (typeof right === 'boolean') {
right = coerceBooleanToNumber(right)
}
if (typeof left === 'number') {
if (typeof right === 'number') {
return Math.max(left, right)
} else {
return left
}
} else if (typeof right === 'number') {
return right
} else {
return Number.NEGATIVE_INFINITY
}
}

/**
* Returns min from two numbers
*
* Implementation of min function which is used in interpreter.
*
* Errors are propagated, non-numerical values are neutral.
*
* @param left - left operand of addition
* @param right - right operand of addition
*/
export function min(left: InternalScalarValue, right: InternalScalarValue): InternalScalarValue {
if (left instanceof CellError) {
return left
}
if (right instanceof CellError) {
return right
}
if (typeof left === 'number') {
if (typeof right === 'number') {
return Math.min(left, right)
} else {
return left
}
} else if (typeof right === 'number') {
return right
} else {
return Number.POSITIVE_INFINITY
}
}

export function mina(left: InternalScalarValue, right: InternalScalarValue): InternalScalarValue {
if (left instanceof CellError) {
return left
}
if (right instanceof CellError) {
return right
}
if (typeof left === 'boolean') {
left = coerceBooleanToNumber(left)
}
if (typeof right === 'boolean') {
right = coerceBooleanToNumber(right)
}
if (typeof left === 'number') {
if (typeof right === 'number') {
return Math.min(left, right)
} else {
return left
}
} else if (typeof right === 'number') {
return right
} else {
return Number.POSITIVE_INFINITY
}
}

export function numberCmp(left: number, right: number): number {
if (left > right) {
return 1
Expand Down
37 changes: 37 additions & 0 deletions src/interpreter/plugin/CountBlankPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @license
* Copyright (c) 2020 Handsoncode. All rights reserved.
*/

import {EmptyValue, InternalScalarValue, SimpleCellAddress} from '../../Cell'
import {ProcedureAst} from '../../parser'
import {ArgumentTypes, FunctionPlugin} from './FunctionPlugin'

/**
* Interpreter plugin containing MEDIAN function
*/
export class CountBlankPlugin extends FunctionPlugin {

public static implementedFunctions = {
'COUNTBLANK': {
method: 'countblank',
parameters: [
{argumentType: ArgumentTypes.SCALAR}
],
repeatLastArgs: 1,
expandRanges: true,
},
}

public countblank(ast: ProcedureAst, formulaAddress: SimpleCellAddress): InternalScalarValue {
return this.runFunction(ast.args, formulaAddress, this.metadata('COUNTBLANK'), (...args: InternalScalarValue[]) => {
let counter = 0
args.forEach((arg) => {
if(arg === EmptyValue) {
counter++
}
})
return counter
})
}
}
15 changes: 10 additions & 5 deletions src/interpreter/plugin/MedianPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import {CellError, ErrorType, InternalScalarValue, SimpleCellAddress} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {AstNodeType, ProcedureAst} from '../../parser'
import {ArgumentTypes, FunctionPlugin} from './FunctionPlugin'

/**
Expand All @@ -17,10 +17,10 @@ export class MedianPlugin extends FunctionPlugin {
'MEDIAN': {
method: 'median',
parameters: [
{argumentType: ArgumentTypes.NOERROR},
],
repeatLastArgs: 1,
expandRanges: true,
{argumentType: ArgumentTypes.NOERROR},
],
repeatLastArgs: 1,
expandRanges: true,
},
}

Expand All @@ -35,6 +35,11 @@ export class MedianPlugin extends FunctionPlugin {
public median(ast: ProcedureAst, formulaAddress: SimpleCellAddress): InternalScalarValue {
return this.runFunction(ast.args, formulaAddress, this.metadata('MEDIAN'), (...args) => {
const values: number[] = args.filter((val: InternalScalarValue) => (typeof val === 'number'))
ast.args.forEach((arg) => { //ugly but works
if (arg.type === AstNodeType.EMPTY) {
values.push(0)
}
})
if (values.length === 0) {
return new CellError(ErrorType.NUM, ErrorMessage.OneValue)
}
Expand Down
Loading