formula: add initial support for cell arrays

This is a pretty uncommon feature from what I can tell
and is not fully supported. The example for the MDETERM
function uses an array though, so this will at least add
enough support for the examples to compute correctly.
This commit is contained in:
Todd 2017-09-16 12:12:55 -05:00
parent fb43078e87
commit 5a5c16b89a
12 changed files with 2291 additions and 1952 deletions

View File

@ -7,7 +7,10 @@
package formula
import "math"
import (
"fmt"
"math"
)
// BinOpType is the binary operation operator type
//go:generate stringer -type=BinOpType
@ -46,6 +49,22 @@ func (b BinaryExpr) Eval(ctx Context, ev Evaluator) Result {
lhs := b.lhs.Eval(ctx, ev)
rhs := b.rhs.Eval(ctx, ev)
// peel off array/list ops first
if lhs.Type == rhs.Type {
if lhs.Type == ResultTypeArray {
if !sameDim(lhs.ValueArray, rhs.ValueArray) {
return MakeErrorResult("lhs/rhs should have same dimensions")
}
return arrayOp(b.op, lhs.ValueArray, rhs.ValueArray)
} else if lhs.Type == ResultTypeList {
if len(lhs.ValueList) != len(rhs.ValueList) {
return MakeErrorResult("lhs/rhs should have same dimensions")
}
return listOp(b.op, lhs.ValueList, rhs.ValueList)
}
}
// TODO: check for and add support for binary operators on boolean values
switch b.op {
case BinOpTypePlus:
@ -128,3 +147,73 @@ func (b BinaryExpr) Eval(ctx Context, ev Evaluator) Result {
func (b BinaryExpr) Reference(ctx Context, ev Evaluator) Reference {
return ReferenceInvalid
}
// sameDim returns true if the arrays have the same dimensions.
func sameDim(lhs, rhs [][]Result) bool {
if len(lhs) != len(rhs) {
return false
}
for i := range lhs {
if len(lhs[i]) != len(rhs[i]) {
return false
}
}
return true
}
func arrayOp(op BinOpType, lhs, rhs [][]Result) Result {
// we can assume the arrays are the same size here
res := [][]Result{}
for i := range lhs {
lst := listOp(op, lhs[i], rhs[i])
if lst.Type == ResultTypeError {
return lst
}
res = append(res, lst.ValueList)
}
return MakeArrayResult(res)
}
func listOp(op BinOpType, lhs, rhs []Result) Result {
res := []Result{}
// we can assume the arrays are the same size here
for i := range lhs {
l := lhs[i].AsNumber()
r := rhs[i].AsNumber()
if l.Type != ResultTypeNumber || r.Type != ResultTypeNumber {
return MakeErrorResult("non-nunmeric value in binary operation")
}
switch op {
case BinOpTypePlus:
res = append(res, MakeNumberResult(l.ValueNumber+r.ValueNumber))
case BinOpTypeMinus:
res = append(res, MakeNumberResult(l.ValueNumber-r.ValueNumber))
case BinOpTypeMult:
res = append(res, MakeNumberResult(l.ValueNumber*r.ValueNumber))
case BinOpTypeDiv:
if r.ValueNumber == 0 {
return MakeErrorResultType(ErrorTypeDivideByZero, "")
}
res = append(res, MakeNumberResult(l.ValueNumber/r.ValueNumber))
case BinOpTypeExp:
res = append(res, MakeNumberResult(math.Pow(l.ValueNumber, r.ValueNumber)))
case BinOpTypeLT:
res = append(res, MakeBoolResult(l.ValueNumber < r.ValueNumber))
case BinOpTypeGT:
res = append(res, MakeBoolResult(l.ValueNumber > r.ValueNumber))
case BinOpTypeEQ:
res = append(res, MakeBoolResult(l.ValueNumber == r.ValueNumber))
case BinOpTypeLEQ:
res = append(res, MakeBoolResult(l.ValueNumber <= r.ValueNumber))
case BinOpTypeGEQ:
res = append(res, MakeBoolResult(l.ValueNumber >= r.ValueNumber))
case BinOpTypeNE:
res = append(res, MakeBoolResult(l.ValueNumber != r.ValueNumber))
// TODO: support concat here
// case BinOpTypeConcat:
default:
return MakeErrorResult(fmt.Sprintf("unsupported list binary op %s", op))
}
}
return MakeListResult(res)
}

View File

@ -0,0 +1,32 @@
// Copyright 2017 Baliance. All rights reserved.
//
// Use of this source code is governed by the terms of the Affero GNU General
// Public License version 3.0 as published by the Free Software Foundation and
// appearing in the file LICENSE included in the packaging of this file. A
// commercial license can be purchased by contacting sales@baliance.com.
package formula
type ConstArrayExpr struct {
data [][]Expression
}
func NewConstArrayExpr(data [][]Expression) Expression {
return &ConstArrayExpr{data}
}
func (c ConstArrayExpr) Eval(ctx Context, ev Evaluator) Result {
res := [][]Result{}
for _, row := range c.data {
r := []Result{}
for _, col := range row {
r = append(r, col.Eval(ctx, ev))
}
res = append(res, r)
}
return MakeArrayResult(res)
}
func (c ConstArrayExpr) Reference(ctx Context, ev Evaluator) Reference {
return ReferenceInvalid
}

View File

@ -24,12 +24,25 @@ func Sum(args []Result) Result {
// Sum returns zero with no arguments
res := MakeNumberResult(0)
for _, a := range args {
a = a.AsNumber()
switch a.Type {
case ResultTypeNumber:
res.ValueNumber += a.ValueNumber
case ResultTypeList:
subSum := Sum(a.ValueList)
// error as sum returns only numbers and errors
if subSum.Type != ResultTypeNumber {
return subSum
}
res.ValueNumber += subSum.ValueNumber
case ResultTypeArray:
for _, row := range a.ValueArray {
subSum := Sum(row)
if subSum.Type != ResultTypeNumber {
return subSum
}
res.ValueNumber += subSum.ValueNumber
}
case ResultTypeString:
// treated as zero by Excel
case ResultTypeError:

View File

@ -14,6 +14,7 @@ type yySymType struct {
node *node
expr Expression
args []Expression
rows [][]Expression
}
const tokenHorizontalRange = 57346
@ -45,6 +46,7 @@ const tokenNE = 57371
const tokenColon = 57372
const tokenComma = 57373
const tokenAmpersand = 57374
const tokenSemi = 57375
var yyToknames = [...]string{
"$end",
@ -79,6 +81,7 @@ var yyToknames = [...]string{
"tokenColon",
"tokenComma",
"tokenAmpersand",
"tokenSemi",
}
var yyStatenames = [...]string{}
@ -94,76 +97,82 @@ var yyExca = [...]int{
const yyPrivate = 57344
const yyLast = 149
const yyLast = 175
var yyAct = [...]int{
3, 26, 27, 28, 62, 36, 28, 38, 39, 41,
22, 37, 35, 40, 28, 35, 44, 63, 18, 20,
17, 45, 46, 65, 11, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 64, 59, 42,
24, 25, 26, 27, 28, 33, 29, 30, 31, 32,
34, 9, 1, 35, 19, 10, 2, 8, 0, 0,
0, 0, 61, 0, 66, 60, 24, 25, 26, 27,
28, 33, 29, 30, 31, 32, 34, 0, 0, 35,
24, 25, 26, 27, 28, 33, 29, 30, 31, 32,
34, 0, 0, 35, 24, 25, 26, 27, 28, 0,
0, 0, 0, 13, 14, 15, 16, 35, 23, 22,
21, 5, 0, 12, 0, 6, 7, 0, 0, 0,
4, 13, 14, 15, 16, 0, 23, 22, 21, 0,
0, 12, 43, 6, 7, 13, 14, 15, 16, 0,
23, 22, 21, 0, 0, 12, 0, 6, 7,
3, 41, 18, 9, 70, 37, 29, 43, 44, 42,
27, 28, 29, 45, 46, 36, 67, 71, 29, 23,
49, 36, 47, 51, 65, 40, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63, 13, 19,
64, 66, 42, 14, 15, 16, 17, 72, 21, 69,
25, 26, 27, 28, 29, 34, 30, 31, 32, 33,
35, 50, 75, 36, 11, 1, 20, 10, 73, 2,
42, 74, 76, 68, 25, 26, 27, 28, 29, 34,
30, 31, 32, 33, 35, 8, 0, 36, 25, 26,
27, 28, 29, 34, 30, 31, 32, 33, 35, 0,
0, 36, 25, 26, 27, 28, 29, 0, 0, 0,
0, 14, 15, 16, 17, 36, 24, 23, 22, 5,
0, 12, 0, 6, 7, 0, 0, 0, 4, 14,
15, 16, 17, 0, 24, 23, 22, 38, 0, 12,
48, 6, 7, 14, 15, 16, 17, 0, 24, 23,
22, 38, 0, 12, 0, 6, 7, 14, 15, 16,
17, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 39,
}
var yyPact = [...]int{
96, -1000, -1000, 61, 128, -13, 128, 128, -1000, -1000,
-1000, -1000, 128, -1000, -1000, -1000, -1000, -21, -3, -1000,
-1000, 114, -1000, -1000, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 61, 128, -20, -20,
47, -3, -1000, -1000, -14, -1000, 61, -20, -20, -17,
-17, -1000, 75, 75, 75, 75, 75, 75, -9, 21,
-1000, -1000, -1000, 128, -1000, -1000, 61,
104, -1000, -1000, 69, 136, 150, 136, 136, -1000, -1000,
-1000, -1000, 136, -1000, -1000, -1000, -1000, -1000, -16, 6,
-1000, -1000, 122, -1000, -1000, 136, 136, 136, 136, 136,
136, 136, 136, 136, 136, 136, 136, 69, 36, 136,
8, -15, -1000, -11, -11, 55, 6, -1000, -1000, -14,
-1000, 69, -11, -11, -17, -17, -1000, 83, 83, 83,
83, 83, 83, -5, 31, -1000, 36, 36, -1000, -1000,
-1000, 136, -1000, -15, -1000, -1000, 69,
}
var yyPgo = [...]int{
0, 0, 57, 56, 55, 20, 54, 52, 51, 24,
23, 21, 19, 18, 16,
0, 0, 85, 69, 67, 2, 66, 65, 3, 64,
62, 61, 48, 39, 38, 25, 20, 1,
}
var yyR1 = [...]int{
0, 7, 3, 3, 3, 8, 8, 8, 8, 1,
1, 1, 2, 2, 2, 2, 4, 4, 4, 13,
5, 6, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 9, 9, 9, 14, 14, 11,
10, 10,
1, 1, 2, 2, 2, 2, 2, 14, 15, 15,
17, 17, 4, 4, 4, 13, 5, 6, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
9, 9, 9, 16, 16, 11, 10, 10,
}
var yyR2 = [...]int{
0, 1, 1, 2, 4, 1, 1, 1, 1, 2,
2, 1, 1, 1, 1, 3, 1, 2, 1, 1,
1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 1, 2, 3, 1, 3, 1,
1, 0,
2, 1, 1, 1, 1, 3, 1, 3, 1, 3,
1, 3, 1, 2, 1, 1, 1, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1, 2, 3, 1, 3, 1, 1, 0,
}
var yyChk = [...]int{
-1000, -7, -3, -1, 24, 15, 19, 20, -2, -8,
-4, -9, 17, 7, 8, 9, 10, -5, -13, -6,
-12, 14, 13, 12, 19, 20, 21, 22, 23, 25,
26, 27, 28, 24, 29, 32, -1, 24, -1, -1,
-1, 30, -5, 18, -14, -11, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
18, -5, 18, 31, 16, -10, -1,
-4, -9, 17, -14, 7, 8, 9, 10, -5, -13,
-6, -12, 14, 13, 12, 19, 20, 21, 22, 23,
25, 26, 27, 28, 24, 29, 32, -1, 15, 24,
-15, -17, -8, -1, -1, -1, 30, -5, 18, -16,
-11, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 16, 33, 31, 18, -5,
18, 31, 16, -17, -8, -10, -1,
}
var yyDef = [...]int{
0, -2, 1, 2, 0, 0, 0, 0, 11, 12,
13, 14, 0, 5, 6, 7, 8, 16, 0, 18,
34, 0, 20, 19, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3, 0, 9, 10,
0, 0, 17, 35, 0, 37, 39, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 0,
15, 21, 36, 41, 4, 38, 40,
13, 14, 0, 16, 5, 6, 7, 8, 22, 0,
24, 40, 0, 26, 25, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
0, 18, 20, 9, 10, 0, 0, 23, 41, 0,
43, 45, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 0, 17, 0, 0, 15, 27,
42, 47, 4, 19, 21, 44, 46,
}
var yyTok1 = [...]int{
@ -174,7 +183,7 @@ var yyTok2 = [...]int{
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32,
32, 33,
}
var yyTok3 = [...]int{
0,
@ -565,106 +574,131 @@ yydefault:
yyVAL.expr = yyDollar[2].expr
}
case 17:
yyDollar = yyS[yypt-2 : yypt+1]
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewPrefixExpr(yyDollar[1].expr, yyDollar[2].expr)
yyVAL.expr = NewConstArrayExpr(yyDollar[2].rows)
}
case 19:
case 18:
yyDollar = yyS[yypt-1 : yypt+1]
{
yyVAL.expr = NewSheetPrefixExpr(yyDollar[1].node.val)
yyVAL.rows = append(yyVAL.rows, yyDollar[1].args)
}
case 19:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.rows = append(yyDollar[1].rows, yyDollar[3].args)
}
case 20:
yyDollar = yyS[yypt-1 : yypt+1]
{
yyVAL.expr = NewCellRef(yyDollar[1].node.val)
yyVAL.args = append(yyVAL.args, yyDollar[1].expr)
}
case 21:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewRange(yyDollar[1].expr, yyDollar[3].expr)
}
case 22:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypePlus, yyDollar[3].expr)
yyVAL.args = append(yyDollar[1].args, yyDollar[3].expr)
}
case 23:
yyDollar = yyS[yypt-3 : yypt+1]
yyDollar = yyS[yypt-2 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeMinus, yyDollar[3].expr)
}
case 24:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeMult, yyDollar[3].expr)
yyVAL.expr = NewPrefixExpr(yyDollar[1].expr, yyDollar[2].expr)
}
case 25:
yyDollar = yyS[yypt-3 : yypt+1]
yyDollar = yyS[yypt-1 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeDiv, yyDollar[3].expr)
yyVAL.expr = NewSheetPrefixExpr(yyDollar[1].node.val)
}
case 26:
yyDollar = yyS[yypt-3 : yypt+1]
yyDollar = yyS[yypt-1 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeExp, yyDollar[3].expr)
yyVAL.expr = NewCellRef(yyDollar[1].node.val)
}
case 27:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeLT, yyDollar[3].expr)
yyVAL.expr = NewRange(yyDollar[1].expr, yyDollar[3].expr)
}
case 28:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeGT, yyDollar[3].expr)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypePlus, yyDollar[3].expr)
}
case 29:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeLEQ, yyDollar[3].expr)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeMinus, yyDollar[3].expr)
}
case 30:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeGEQ, yyDollar[3].expr)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeMult, yyDollar[3].expr)
}
case 31:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeEQ, yyDollar[3].expr)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeDiv, yyDollar[3].expr)
}
case 32:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeNE, yyDollar[3].expr)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeExp, yyDollar[3].expr)
}
case 33:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeConcat, yyDollar[3].expr)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeLT, yyDollar[3].expr)
}
case 34:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeGT, yyDollar[3].expr)
}
case 35:
yyDollar = yyS[yypt-2 : yypt+1]
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewFunction(yyDollar[1].node.val, nil)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeLEQ, yyDollar[3].expr)
}
case 36:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewFunction(yyDollar[1].node.val, yyDollar[2].args)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeGEQ, yyDollar[3].expr)
}
case 37:
yyDollar = yyS[yypt-1 : yypt+1]
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.args = append(yyVAL.args, yyDollar[1].expr)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeEQ, yyDollar[3].expr)
}
case 38:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.args = append(yyDollar[1].args, yyDollar[3].expr)
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeNE, yyDollar[3].expr)
}
case 39:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewBinaryExpr(yyDollar[1].expr, BinOpTypeConcat, yyDollar[3].expr)
}
case 41:
yyDollar = yyS[yypt-2 : yypt+1]
{
yyVAL.expr = NewFunction(yyDollar[1].node.val, nil)
}
case 42:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.expr = NewFunction(yyDollar[1].node.val, yyDollar[2].args)
}
case 43:
yyDollar = yyS[yypt-1 : yypt+1]
{
yyVAL.args = append(yyVAL.args, yyDollar[1].expr)
}
case 44:
yyDollar = yyS[yypt-3 : yypt+1]
{
yyVAL.args = append(yyDollar[1].args, yyDollar[3].expr)
}
case 47:
yyDollar = yyS[yypt-0 : yypt+1]
{
yyVAL.expr = NewEmptyExpr()

View File

@ -14,12 +14,14 @@ package formula
node *node
expr Expression
args []Expression
rows [][]Expression
}
%type <expr> formula formula1 initial reference referenceItem refFunctionCall
%type <expr> start constant functionCall argument argument1
%type <expr> binOp prefix
%type <args> arguments
%type <expr> binOp prefix constArray
%type <rows> constArrayRows
%type <args> arguments constArrayCols
%token <expr> tokenHorizontalRange tokenReservedName tokenDDECall
%token <node> tokenBool tokenNumber tokenString tokenError tokenErrorRef tokenSheet tokenCell
@ -27,7 +29,7 @@ package formula
%token tokenLBrace tokenRBrace tokenLParen tokenRParen
%token tokenPlus tokenMinus tokenMult tokenDiv tokenExp tokenEQ tokenLT tokenGT tokenLEQ tokenGEQ tokenNE
%token tokenColon tokenComma tokenAmpersand
%token tokenColon tokenComma tokenAmpersand tokenSemi
%left tokenEQ tokenLT tokenGT tokenLEQ tokenGEQ tokenNE
%left tokenPlus tokenMinus
@ -61,8 +63,19 @@ formula1:
| reference
| functionCall
| tokenLParen formula tokenRParen { $$ = $2 }
| constArray
;
constArray: tokenLBrace constArrayRows tokenRBrace { $$ = NewConstArrayExpr($2)} ;
constArrayRows:
constArrayCols { $$ = append($$, $1) }
| constArrayRows tokenSemi constArrayCols { $$ = append($1, $3)};
constArrayCols:
constant { $$ = append($$,$1) }
| constArrayCols tokenComma constant { $$ = append($1,$3)}
reference:
referenceItem
| prefix referenceItem { $$ = NewPrefixExpr($1,$2)}
@ -70,7 +83,7 @@ reference:
prefix: tokenSheet { $$ = NewSheetPrefixExpr($1.val) };
referenceItem: tokenCell { $$ = NewCellRef($1.val)} ;
referenceItem: tokenCell { $$ = NewCellRef($1.val)} ;
refFunctionCall:
referenceItem tokenColon referenceItem { $$ = NewRange($1,$3) };

File diff suppressed because it is too large Load Diff

View File

@ -89,6 +89,7 @@ import (
'<>' { l.emit(tokenNE,data[ts:te]) };
':' { l.emit(tokenColon,data[ts:te]) };
';' { l.emit(tokenSemi,data[ts:te]) };
',' { l.emit(tokenComma,data[ts:te]) };
*|;

View File

@ -22,6 +22,7 @@ const (
ResultTypeNumber
ResultTypeString
ResultTypeList
ResultTypeArray
ResultTypeError
ResultTypeEmpty
)
@ -31,11 +32,12 @@ type Result struct {
ValueNumber float64
ValueString string
ValueList []Result
ValueArray [][]Result
ErrorMessage string
Type ResultType
}
// Value returns a string version of the formula.
// Value returns a string version of the result.
func (r Result) Value() string {
switch r.Type {
case ResultTypeNumber:
@ -44,6 +46,11 @@ func (r Result) Value() string {
return r.ValueString
case ResultTypeString:
return r.ValueString
case ResultTypeList:
if len(r.ValueList) == 0 {
return ""
}
return r.ValueList[0].Value()
default:
return "unhandled result value"
}
@ -138,3 +145,13 @@ func MakeStringResult(s string) Result {
func MakeEmptyResult() Result {
return Result{Type: ResultTypeEmpty}
}
// MakeArrayResult constructs an array result (matrix).
func MakeArrayResult(arr [][]Result) Result {
return Result{Type: ResultTypeArray, ValueArray: arr}
}
// MakeListResult constructs a list result.
func MakeListResult(list []Result) Result {
return Result{Type: ResultTypeList, ValueList: list}
}

View File

@ -4,9 +4,9 @@ package formula
import "fmt"
const _ResultType_name = "ResultTypeUnknownResultTypeNumberResultTypeStringResultTypeListResultTypeErrorResultTypeEmpty"
const _ResultType_name = "ResultTypeUnknownResultTypeNumberResultTypeStringResultTypeListResultTypeArrayResultTypeErrorResultTypeEmpty"
var _ResultType_index = [...]uint8{0, 17, 33, 49, 63, 78, 93}
var _ResultType_index = [...]uint8{0, 17, 33, 49, 63, 78, 93, 108}
func (i ResultType) String() string {
if i >= ResultType(len(_ResultType_index)-1) {

View File

@ -8,7 +8,6 @@
package spreadsheet
import (
"fmt"
"strings"
sml "baliance.com/gooxml/schema/schemas.openxmlformats.org/spreadsheetml"
@ -42,7 +41,6 @@ func (s MergedCell) Cell() Cell {
ref = ref[0:idx]
return Sheet{w: s.wb, x: s.ws}.Cell(ref)
}
fmt.Println("DIE")
// couldn't find it, log an error?
return Cell{}
}

View File

@ -390,7 +390,7 @@ func (wb *Workbook) onNewRelationship(decMap *zippkg.DecodeMap, target, typ stri
rel.TargetAttr = gooxml.RelativeFilename(dt, typ, len(wb.charts))
default:
fmt.Println("unsupported relationship", target, typ)
log.Printf("unsupported relationship", target, typ)
}
return nil
}