Skip to content

This related with #2123, made editAs attribute value empty for one cell anchor drawing object #2128

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

Merged
merged 8 commits into from
May 9, 2025
36 changes: 27 additions & 9 deletions adjust.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion cell.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
7 changes: 2 additions & 5 deletions chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
14 changes: 5 additions & 9 deletions col.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))
}
2 changes: 1 addition & 1 deletion col_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
2 changes: 1 addition & 1 deletion drawing.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
4 changes: 2 additions & 2 deletions picture.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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{}
Expand Down Expand Up @@ -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,
}
Expand Down
4 changes: 2 additions & 2 deletions rows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
2 changes: 1 addition & 1 deletion rows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions slicer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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: "<a:prstClr val=\"white\"/>"},
PrstGeom: xlsxPrstGeom{
Prst: "rect",
Expand Down
17 changes: 9 additions & 8 deletions xmlDecodeDrawing.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand All @@ -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"`
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"`
}
Expand All @@ -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
Expand Down
12 changes: 6 additions & 6 deletions xmlDrawing.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
Expand All @@ -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
Expand Down Expand Up @@ -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"`
Expand All @@ -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"`
Expand Down
14 changes: 7 additions & 7 deletions xmlStyles.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down