From 684603befa0fbde2ee8db704e37a544f9d92d99d Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 6 Sep 2021 00:01:42 +0800 Subject: [PATCH] This closes #993, closes #1014 - Fix formula percentages calculated incorrectly - Make UpdateLinkedValue skip macro sheet - Fix conditional format bottom N not working --- calc.go | 14 +++++++++++++- calc_test.go | 2 ++ chart_test.go | 2 +- excelize.go | 6 +++--- styles.go | 1 + 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/calc.go b/calc.go index 5661d7d..ef8d0b0 100644 --- a/calc.go +++ b/calc.go @@ -975,6 +975,11 @@ func isOperatorPrefixToken(token efp.Token) bool { return (token.TValue == "-" && token.TType == efp.TokenTypeOperatorPrefix) || (ok && token.TType == efp.TokenTypeOperatorInfix) } +// isOperand determine if the token is parse operand perand. +func isOperand(token efp.Token) bool { + return token.TType == efp.TokenTypeOperand && (token.TSubType == efp.TokenSubTypeNumber || token.TSubType == efp.TokenSubTypeText) +} + // getDefinedNameRefTo convert defined name to reference range. func (f *File) getDefinedNameRefTo(definedNameName string, currentSheet string) (refTo string) { var workbookRefTo, worksheetRefTo string @@ -1034,8 +1039,15 @@ func (f *File) parseToken(sheet string, token efp.Token, opdStack, optStack *Sta } optStack.Pop() } + if token.TType == efp.TokenTypeOperatorPostfix && !opdStack.Empty() { + topOpd := opdStack.Pop().(efp.Token) + opd, err := strconv.ParseFloat(topOpd.TValue, 64) + topOpd.TValue = strconv.FormatFloat(opd/100, 'f', -1, 64) + opdStack.Push(topOpd) + return err + } // opd - if token.TType == efp.TokenTypeOperand && (token.TSubType == efp.TokenSubTypeNumber || token.TSubType == efp.TokenSubTypeText) { + if isOperand(token) { opdStack.Push(token) } return nil diff --git a/calc_test.go b/calc_test.go index 4c32983..cd09e97 100644 --- a/calc_test.go +++ b/calc_test.go @@ -46,6 +46,8 @@ func TestCalcCellValue(t *testing.T) { "=2>=1": "TRUE", "=2>=3": "FALSE", "=1&2": "12", + "=15%": "0.15", + "=1+20%": "1.2", `="A"="A"`: "TRUE", `="A"<>"A"`: "FALSE", // Engineering Functions diff --git a/chart_test.go b/chart_test.go index 8957b93..d2a3975 100644 --- a/chart_test.go +++ b/chart_test.go @@ -230,7 +230,7 @@ func TestAddChartSheet(t *testing.T) { f.SetActiveSheet(sheetIdx) // Test cell value on chartsheet - assert.EqualError(t, f.SetCellValue("Chart1", "A1", true), "sheet Chart1 is chart sheet") + assert.EqualError(t, f.SetCellValue("Chart1", "A1", true), "sheet Chart1 is not a worksheet") // Test add chartsheet on already existing name sheet assert.EqualError(t, f.AddChartSheet("Sheet1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`), ErrExistsWorksheet.Error()) // Test with unsupported chart type diff --git a/excelize.go b/excelize.go index def018b..24a1a4e 100644 --- a/excelize.go +++ b/excelize.go @@ -204,8 +204,8 @@ func (f *File) workSheetReader(sheet string) (ws *xlsxWorksheet, err error) { ws = worksheet.(*xlsxWorksheet) return } - if strings.HasPrefix(name, "xl/chartsheets") { - err = fmt.Errorf("sheet %s is chart sheet", sheet) + if strings.HasPrefix(name, "xl/chartsheets") || strings.HasPrefix(name, "xl/macrosheet") { + err = fmt.Errorf("sheet %s is not a worksheet", sheet) return } ws = new(xlsxWorksheet) @@ -367,7 +367,7 @@ func (f *File) UpdateLinkedValue() error { for _, name := range f.GetSheetList() { ws, err := f.workSheetReader(name) if err != nil { - if err.Error() == fmt.Sprintf("sheet %s is chart sheet", trimSheetName(name)) { + if err.Error() == fmt.Sprintf("sheet %s is not a worksheet", trimSheetName(name)) { continue } return err diff --git a/styles.go b/styles.go index 31fa7fb..e4f3a27 100644 --- a/styles.go +++ b/styles.go @@ -3011,6 +3011,7 @@ func drawCondFmtCellIs(p int, ct string, format *formatConditional) *xlsxCfRule func drawCondFmtTop10(p int, ct string, format *formatConditional) *xlsxCfRule { c := &xlsxCfRule{ Priority: p + 1, + Bottom: format.Type == "bottom", Type: validType[format.Type], Rank: 10, DxfID: &format.Format,