diff --git a/adjust.go b/adjust.go index 7150dfcf27..38e6207689 100644 --- a/adjust.go +++ b/adjust.go @@ -416,30 +416,48 @@ func (f *File) adjustFormulaOperand(sheet, sheetN string, keepRelative bool, tok // adjustFormulaRef returns adjusted formula by giving adjusting direction and // the base number of column or row, and offset. func (f *File) adjustFormulaRef(sheet, sheetN, formula string, keepRelative bool, dir adjustDirection, num, offset int) (string, error) { - var definedNames []string + var ( + val string + definedNames []string + ps = efp.ExcelParser() + ) for _, definedName := range f.GetDefinedName() { if definedName.Scope == "Workbook" || definedName.Scope == sheet { definedNames = append(definedNames, definedName.Name) } } - ps := efp.ExcelParser() - tokens := ps.Parse(formula) - for i, token := range tokens { + for _, token := range ps.Parse(formula) { if token.TType == efp.TokenTypeUnknown { - return formula, nil + val = formula + break } if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeRange { - if inStrSlice(definedNames, token.TValue, true) != -1 || strings.ContainsAny(token.TValue, "[]") { + if inStrSlice(definedNames, token.TValue, true) != -1 { + val += token.TValue + continue + } + if strings.ContainsAny(token.TValue, "[]") { + val += token.TValue continue } operand, err := f.adjustFormulaOperand(sheet, sheetN, keepRelative, token, dir, num, offset) if err != nil { - return ps.Render(), err + return val, err } - tokens[i].TValue = operand + val += operand + continue } + if paren := transformParenthesesToken(token); paren != "" { + val += transformParenthesesToken(token) + continue + } + if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeText { + val += string(efp.QuoteDouble) + strings.ReplaceAll(token.TValue, "\"", "\"\"") + string(efp.QuoteDouble) + continue + } + val += token.TValue } - return ps.Render(), nil + return val, nil } // transformParenthesesToken returns formula part with parentheses by given diff --git a/cell.go b/cell.go index 4d4695cc02..4553a0e3ca 100644 --- a/cell.go +++ b/cell.go @@ -189,11 +189,11 @@ func (f *File) removeFormula(c *xlsxC, ws *xlsxWorksheet, sheet string) error { } if c.F.T == STCellFormulaTypeShared && c.F.Ref != "" { si := c.F.Si - ws.deleteSharedFormula(c) for r, row := range ws.SheetData.Row { for col, cell := range row.C { if cell.F != nil && cell.F.Si != nil && *cell.F.Si == *si { ws.SheetData.Row[r].C[col].F = nil + ws.deleteSharedFormula(c) _ = f.deleteCalcChain(sheetID, cell.R) } } diff --git a/chart_test.go b/chart_test.go index 1b17ce555d..989d9337d8 100644 --- a/chart_test.go +++ b/chart_test.go @@ -93,11 +93,8 @@ func TestChartSize(t *testing.T) { t.FailNow() } - if !assert.Equal(t, 11, anchor.To.Col, "Expected 'to' column 11") || - !assert.Equal(t, 27, anchor.To.Row, "Expected 'to' row 27") { - - t.FailNow() - } + assert.Equal(t, 14, anchor.To.Col, "Expected 'to' column 14") + assert.Equal(t, 29, anchor.To.Row, "Expected 'to' row 29") } func TestAddDrawingChart(t *testing.T) { diff --git a/col.go b/col.go index 457c6132a0..d8c3d0dbe9 100644 --- a/col.go +++ b/col.go @@ -22,10 +22,10 @@ import ( // Define the default cell size and EMU unit of measurement. const ( - defaultColWidth float64 = 10.5 - defaultColWidthPixels float64 = 84.0 - defaultRowHeight float64 = 15.6 - defaultRowHeightPixels float64 = 20.8 + defaultColWidth float64 = 9.140625 + defaultColWidthPixels float64 = 64 + defaultRowHeight float64 = 15 + defaultRowHeightPixels float64 = 20 EMU int = 9525 ) @@ -625,7 +625,7 @@ func (f *File) positionObjectPixels(sheet string, col, row, width, height int, o // Initialized end cell to the same as the start cell. colEnd, rowEnd := colIdx, rowIdx x1, y1, x2, y2 := opts.OffsetX, opts.OffsetY, width, height - if opts.Positioning == "" || opts.Positioning == "twoCell" { + if opts.Positioning != "oneCell" { // Using a twoCellAnchor, the maximum possible offset is limited by the // "from" cell dimensions. If these were to be exceeded the "toPoint" would // be calculated incorrectly, since the requested "fromPoint" is not possible @@ -801,10 +801,6 @@ func convertColWidthToPixels(width float64) float64 { if width == 0 { return pixels } - if width < 1 { - pixels = (width * 12) + 0.5 - return float64(int(pixels)) - } pixels = (width*maxDigitWidth + 0.5) return float64(int(pixels)) } diff --git a/col_test.go b/col_test.go index 0019587434..5c4bfc5559 100644 --- a/col_test.go +++ b/col_test.go @@ -484,5 +484,5 @@ func TestRemoveCol(t *testing.T) { } func TestConvertColWidthToPixels(t *testing.T) { - assert.Equal(t, -11.0, convertColWidthToPixels(-1)) + assert.Equal(t, -7.0, convertColWidthToPixels(-1)) } diff --git a/drawing.go b/drawing.go index 180ad349f8..5f1c9dd4b0 100644 --- a/drawing.go +++ b/drawing.go @@ -1466,7 +1466,7 @@ func (f *File) addSheetDrawingChart(drawingXML string, rID int, opts *GraphicOpt absoluteAnchor := xdrCellAnchor{ EditAs: opts.Positioning, Pos: &xlsxPoint2D{}, - Ext: &aExt{}, + Ext: &xlsxPositiveSize2D{}, } graphicFrame := xlsxGraphicFrame{ diff --git a/picture.go b/picture.go index 3be2e23dd3..5f7a7d3c53 100644 --- a/picture.go +++ b/picture.go @@ -372,7 +372,6 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, ext string, rID, hyper return err } cellAnchor := xdrCellAnchor{} - cellAnchor.EditAs = opts.Positioning from := xlsxFrom{} from.Col = colStart from.ColOff = x1 * EMU @@ -387,6 +386,7 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, ext string, rID, hyper to.Row = rowEnd to.RowOff = y2 * EMU cellAnchor.To = &to + cellAnchor.EditAs = opts.Positioning } pic := xlsxPic{} @@ -420,7 +420,7 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, ext string, rID, hyper if opts.Positioning == "oneCell" { cx := x2 * EMU cy := y2 * EMU - cellAnchor.Ext = &aExt{ + cellAnchor.Ext = &xlsxPositiveSize2D{ Cx: cx, Cy: cy, } diff --git a/rows.go b/rows.go index 12bb4e34c7..85a0d0780d 100644 --- a/rows.go +++ b/rows.go @@ -467,7 +467,7 @@ func (f *File) getRowHeight(sheet string, row int) int { return int(convertRowHeightToPixels(ws.SheetFormatPr.DefaultRowHeight)) } // Optimization for when the row heights haven't changed. - return int(math.Round(defaultRowHeightPixels)) + return int(defaultRowHeightPixels) } // GetRowHeight provides a function to get row height by given worksheet name @@ -1012,5 +1012,5 @@ func convertRowHeightToPixels(height float64) float64 { if height == 0 { return 0 } - return float64(int(height*4.0/3.0 + 0.5)) + return math.Ceil(4.0 / 3.4 * height) } diff --git a/rows_test.go b/rows_test.go index 53a4f1e9c4..17755d76bb 100644 --- a/rows_test.go +++ b/rows_test.go @@ -205,7 +205,7 @@ func TestRowHeight(t *testing.T) { assert.NoError(t, f.SetCellValue("Sheet2", "A2", true)) height, err = f.GetRowHeight("Sheet2", 1) assert.NoError(t, err) - assert.Equal(t, 15.6, height) + assert.Equal(t, 15.0, height) err = f.SaveAs(filepath.Join("test", "TestRowHeight.xlsx")) if !assert.NoError(t, err) { diff --git a/slicer.go b/slicer.go index 8073cf72ff..c20b053571 100644 --- a/slicer.go +++ b/slicer.go @@ -612,7 +612,7 @@ func (f *File) addDrawingSlicer(sheet, slicerName string, ns xml.Attr, opts *Sli Name: slicerName, }, }, - Xfrm: xlsxXfrm{Off: xlsxOff{}, Ext: aExt{}}, + Xfrm: xlsxXfrm{Off: xlsxOff{}, Ext: xlsxPositiveSize2D{}}, Graphic: &xlsxGraphic{ GraphicData: &xlsxGraphicData{ URI: NameSpaceDrawingMLSlicer.Value, @@ -632,7 +632,7 @@ func (f *File) addDrawingSlicer(sheet, slicerName string, ns xml.Attr, opts *Sli }, }, SpPr: &xlsxSpPr{ - Xfrm: xlsxXfrm{Off: xlsxOff{X: 2914650, Y: 152400}, Ext: aExt{Cx: 1828800, Cy: 2238375}}, + Xfrm: xlsxXfrm{Off: xlsxOff{X: 2914650, Y: 152400}, Ext: xlsxPositiveSize2D{Cx: 1828800, Cy: 2238375}}, SolidFill: &xlsxInnerXML{Content: ""}, PrstGeom: xlsxPrstGeom{ Prst: "rect", diff --git a/xmlDecodeDrawing.go b/xmlDecodeDrawing.go index 8a20c5d5c6..747352182e 100644 --- a/xmlDecodeDrawing.go +++ b/xmlDecodeDrawing.go @@ -21,6 +21,7 @@ type decodeCellAnchor struct { EditAs string `xml:"editAs,attr,omitempty"` From *decodeFrom `xml:"from"` To *decodeTo `xml:"to"` + Ext *decodePositiveSize2D `xml:"ext"` Sp *decodeSp `xml:"sp"` Pic *decodePic `xml:"pic"` ClientData *decodeClientData `xml:"clientData"` @@ -35,7 +36,7 @@ type decodeCellAnchorPos struct { From *xlsxFrom `xml:"from"` To *xlsxTo `xml:"to"` Pos *xlsxInnerXML `xml:"pos"` - Ext *xlsxInnerXML `xml:"ext"` + Ext *xlsxPositiveSize2D `xml:"ext"` Sp *xlsxSp `xml:"sp"` GrpSp *xlsxInnerXML `xml:"grpSp"` GraphicFrame *xlsxInnerXML `xml:"graphicFrame"` @@ -85,9 +86,9 @@ type decodeSp struct { // shape. This allows for additional information that does not affect the // appearance of the shape to be stored. type decodeNvSpPr struct { - CNvPr *decodeCNvPr `xml:"cNvPr"` - ExtLst *decodeAExt `xml:"extLst"` - CNvSpPr *decodeCNvSpPr `xml:"cNvSpPr"` + CNvPr *decodeCNvPr `xml:"cNvPr"` + ExtLst *decodePositiveSize2D `xml:"extLst"` + CNvSpPr *decodeCNvSpPr `xml:"cNvSpPr"` } // decodeCNvSpPr (Connection Non-Visual Shape Properties) directly maps the @@ -164,8 +165,8 @@ type decodeOff struct { Y int `xml:"y,attr"` } -// decodeAExt directly maps the a:ext element. -type decodeAExt struct { +// decodePositiveSize2D directly maps the a:ext element. +type decodePositiveSize2D struct { Cx int `xml:"cx,attr"` Cy int `xml:"cy,attr"` } @@ -183,8 +184,8 @@ type decodePrstGeom struct { // frame. This transformation is applied to the graphic frame just as it would // be for a shape or group shape. type decodeXfrm struct { - Off decodeOff `xml:"off"` - Ext decodeAExt `xml:"ext"` + Off decodeOff `xml:"off"` + Ext decodePositiveSize2D `xml:"ext"` } // decodeCNvPicPr directly maps the cNvPicPr (Non-Visual Picture Drawing diff --git a/xmlDrawing.go b/xmlDrawing.go index f363849014..89fe986cec 100644 --- a/xmlDrawing.go +++ b/xmlDrawing.go @@ -83,8 +83,8 @@ type xlsxOff struct { Y int `xml:"y,attr"` } -// aExt directly maps the a:ext element. -type aExt struct { +// xlsxPositiveSize2D directly maps the a:ext element. +type xlsxPositiveSize2D struct { Cx int `xml:"cx,attr"` Cy int `xml:"cy,attr"` } @@ -102,8 +102,8 @@ type xlsxPrstGeom struct { // frame. This transformation is applied to the graphic frame just as it would // be for a shape or group shape. type xlsxXfrm struct { - Off xlsxOff `xml:"a:off"` - Ext aExt `xml:"a:ext"` + Off xlsxOff `xml:"a:off"` + Ext xlsxPositiveSize2D `xml:"a:ext"` } // xlsxCNvPicPr directly maps the cNvPicPr (Non-Visual Picture Drawing @@ -222,7 +222,7 @@ type xdrCellAnchor struct { Pos *xlsxPoint2D `xml:"xdr:pos"` From *xlsxFrom `xml:"xdr:from"` To *xlsxTo `xml:"xdr:to"` - Ext *aExt `xml:"xdr:ext"` + Ext *xlsxPositiveSize2D `xml:"xdr:ext"` Sp *xdrSp `xml:"xdr:sp"` Pic *xlsxPic `xml:"xdr:pic,omitempty"` GraphicFrame string `xml:",innerxml"` @@ -237,7 +237,7 @@ type xlsxCellAnchorPos struct { From *xlsxFrom `xml:"xdr:from"` To *xlsxTo `xml:"xdr:to"` Pos *xlsxInnerXML `xml:"xdr:pos"` - Ext *xlsxInnerXML `xml:"xdr:ext"` + Ext *xlsxPositiveSize2D `xml:"xdr:ext"` Sp *xlsxSp `xml:"xdr:sp"` GrpSp *xlsxInnerXML `xml:"xdr:grpSp"` GraphicFrame *xlsxInnerXML `xml:"xdr:graphicFrame"` diff --git a/xmlStyles.go b/xmlStyles.go index 93ad33cce3..76826c1cc4 100644 --- a/xmlStyles.go +++ b/xmlStyles.go @@ -253,13 +253,13 @@ type xlsxDxfs struct { // xlsxDxf directly maps the dxf element. A single dxf record, expressing // incremental formatting to be applied. type xlsxDxf struct { - Font *xlsxFont `xml:"font"` - NumFmt *xlsxNumFmt `xml:"numFmt"` - Fill *xlsxFill `xml:"fill"` - Alignment *xlsxAlignment `xml:"alignment"` - Border *xlsxBorder `xml:"border"` - Protection *xlsxProtection `xml:"protection"` - ExtLst *aExt `xml:"extLst"` + Font *xlsxFont `xml:"font"` + NumFmt *xlsxNumFmt `xml:"numFmt"` + Fill *xlsxFill `xml:"fill"` + Alignment *xlsxAlignment `xml:"alignment"` + Border *xlsxBorder `xml:"border"` + Protection *xlsxProtection `xml:"protection"` + ExtLst *xlsxPositiveSize2D `xml:"extLst"` } // xlsxTableStyles directly maps the tableStyles element. This element