From 5a039f3045293c58d2383691c30e6ba5ae8da9fb Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 14 Sep 2023 22:56:28 +0800 Subject: [PATCH] This fixes #1658 - Fix a v2.8.0 regression bug, number format code apply result was empty - Fix calculate formula functions CHITEST and MMULT panic in some cases - Updated unit tests --- calc.go | 12 ++++++++++-- calc_test.go | 23 +++++++++++++---------- numfmt.go | 24 ++++++++++++++---------- numfmt_test.go | 6 ++++++ 4 files changed, 43 insertions(+), 22 deletions(-) diff --git a/calc.go b/calc.go index 459616f752..4ae2b3e8bf 100644 --- a/calc.go +++ b/calc.go @@ -4803,11 +4803,16 @@ func (fn *formulaFuncs) MMULT(argsList *list.List) formulaArg { if argsList.Len() != 2 { return newErrorFormulaArg(formulaErrorVALUE, "MMULT requires 2 argument") } - numMtx1, errArg1 := newNumberMatrix(argsList.Front().Value.(formulaArg), false) + arr1 := argsList.Front().Value.(formulaArg) + arr2 := argsList.Back().Value.(formulaArg) + if arr1.Type == ArgNumber && arr2.Type == ArgNumber { + return newNumberFormulaArg(arr1.Number * arr2.Number) + } + numMtx1, errArg1 := newNumberMatrix(arr1, false) if errArg1.Type == ArgError { return errArg1 } - numMtx2, errArg2 := newNumberMatrix(argsList.Back().Value.(formulaArg), false) + numMtx2, errArg2 := newNumberMatrix(arr2, false) if errArg2.Type == ArgError { return errArg2 } @@ -7191,6 +7196,9 @@ func (fn *formulaFuncs) CHITEST(argsList *list.List) formulaArg { actual, expected := argsList.Front().Value.(formulaArg), argsList.Back().Value.(formulaArg) actualList, expectedList := actual.ToList(), expected.ToList() rows := len(actual.Matrix) + if rows == 0 { + return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) + } columns := len(actualList) / rows if len(actualList) != len(expectedList) || len(actualList) == 1 { return newErrorFormulaArg(formulaErrorNA, formulaErrorNA) diff --git a/calc_test.go b/calc_test.go index ba5a35b4f5..6042715206 100644 --- a/calc_test.go +++ b/calc_test.go @@ -673,6 +673,8 @@ func TestCalcCellValue(t *testing.T) { // MINVERSE "=MINVERSE(A1:B2)": "-0", // MMULT + "=MMULT(0,0)": "0", + "=MMULT(2,4)": "8", "=MMULT(A4:A4,A4:A4)": "0", // MOD "=MOD(6,4)": "2", @@ -5139,16 +5141,17 @@ func TestCalcCHITESTandCHISQdotTEST(t *testing.T) { assert.Equal(t, expected, result, formula) } calcError := map[string][]string{ - "=CHITEST()": {"#VALUE!", "CHITEST requires 2 arguments"}, - "=CHITEST(B3:C5,F3:F4)": {"#N/A", "#N/A"}, - "=CHITEST(B3:B3,F3:F3)": {"#N/A", "#N/A"}, - "=CHITEST(F3:F5,B4:B6)": {"#NUM!", "#NUM!"}, - "=CHITEST(F3:F5,C4:C6)": {"#DIV/0!", "#DIV/0!"}, - "=CHISQ.TEST()": {"#VALUE!", "CHISQ.TEST requires 2 arguments"}, - "=CHISQ.TEST(B3:C5,F3:F4)": {"#N/A", "#N/A"}, - "=CHISQ.TEST(B3:B3,F3:F3)": {"#N/A", "#N/A"}, - "=CHISQ.TEST(F3:F5,B4:B6)": {"#NUM!", "#NUM!"}, - "=CHISQ.TEST(F3:F5,C4:C6)": {"#DIV/0!", "#DIV/0!"}, + "=CHITEST()": {"#VALUE!", "CHITEST requires 2 arguments"}, + "=CHITEST(MUNIT(0),MUNIT(0))": {"#VALUE!", "#VALUE!"}, + "=CHITEST(B3:C5,F3:F4)": {"#N/A", "#N/A"}, + "=CHITEST(B3:B3,F3:F3)": {"#N/A", "#N/A"}, + "=CHITEST(F3:F5,B4:B6)": {"#NUM!", "#NUM!"}, + "=CHITEST(F3:F5,C4:C6)": {"#DIV/0!", "#DIV/0!"}, + "=CHISQ.TEST()": {"#VALUE!", "CHISQ.TEST requires 2 arguments"}, + "=CHISQ.TEST(B3:C5,F3:F4)": {"#N/A", "#N/A"}, + "=CHISQ.TEST(B3:B3,F3:F3)": {"#N/A", "#N/A"}, + "=CHISQ.TEST(F3:F5,B4:B6)": {"#NUM!", "#NUM!"}, + "=CHISQ.TEST(F3:F5,C4:C6)": {"#DIV/0!", "#DIV/0!"}, } for formula, expected := range calcError { assert.NoError(t, f.SetCellFormula("Sheet1", "I1", formula)) diff --git a/numfmt.go b/numfmt.go index b63e74a1c8..b0fd7c2e01 100644 --- a/numfmt.go +++ b/numfmt.go @@ -4759,9 +4759,9 @@ func (nf *numberFormat) getNumberFmtConf() { if token.TType == nfp.TokenTypeHashPlaceHolder { if nf.usePointer { nf.fracHolder += len(token.TValue) - } else { - nf.intHolder += len(token.TValue) + continue } + nf.intHolder += len(token.TValue) } if token.TType == nfp.TokenTypeExponential { nf.useScientificNotation = true @@ -4779,6 +4779,7 @@ func (nf *numberFormat) getNumberFmtConf() { nf.switchArgument = token.TValue } if token.TType == nfp.TokenTypeZeroPlaceHolder { + nf.intHolder = 0 if nf.usePointer { if nf.useScientificNotation { nf.expBaseLen += len(token.TValue) @@ -4795,7 +4796,7 @@ func (nf *numberFormat) getNumberFmtConf() { // printNumberLiteral apply literal tokens for the pre-formatted text. func (nf *numberFormat) printNumberLiteral(text string) string { var result string - var useLiteral, useZeroPlaceHolder bool + var useLiteral, usePlaceHolder bool if nf.usePositive { result += "-" } @@ -4807,17 +4808,17 @@ func (nf *numberFormat) printNumberLiteral(text string) string { result += nf.currencyString } if token.TType == nfp.TokenTypeLiteral { - if useZeroPlaceHolder { + if usePlaceHolder { useLiteral = true } result += token.TValue } - if token.TType == nfp.TokenTypeZeroPlaceHolder { - if useLiteral && useZeroPlaceHolder { + if token.TType == nfp.TokenTypeHashPlaceHolder || token.TType == nfp.TokenTypeZeroPlaceHolder { + if useLiteral && usePlaceHolder { return nf.value } - if !useZeroPlaceHolder { - useZeroPlaceHolder = true + if !usePlaceHolder { + usePlaceHolder = true result += text } } @@ -4896,8 +4897,11 @@ func (nf *numberFormat) numberHandler() string { result string ) nf.getNumberFmtConf() - if intLen = intPart; nf.intPadding > intPart { - intLen = nf.intPadding + if nf.intHolder > intPart { + nf.intHolder = intPart + } + if intLen = intPart; nf.intPadding+nf.intHolder > intPart { + intLen = nf.intPadding + nf.intHolder } if fracLen = fracPart; fracPart > nf.fracHolder+nf.fracPadding { fracLen = nf.fracHolder + nf.fracPadding diff --git a/numfmt_test.go b/numfmt_test.go index 02a73af9ec..143357c87a 100644 --- a/numfmt_test.go +++ b/numfmt_test.go @@ -3504,6 +3504,12 @@ func TestNumFmt(t *testing.T) { {"1234.5678", "#,##0 ;[red](#,##0)", "1,235 "}, {"1234.5678", "#,##0.00;(#,##0.00)", "1,234.57"}, {"1234.5678", "#,##0.00;[red](#,##0.00)", "1,234.57"}, + {"1234.5678", "#", "1235"}, + {"1234.5678", "#0", "1235"}, + {"1234.5678", "##", "1235"}, + {"1234.5678", "00000.00#", "01234.568"}, + {"1234.5678", "00000####", "000001235"}, + {"1234.5678", "00000######", "000001235"}, {"-1234.5678", "0.00", "-1234.57"}, {"-1234.5678", "0.00;-0.00", "-1234.57"}, {"-1234.5678", "0.00%%", "-12345678.00%%"},