diff --git a/adjust.go b/adjust.go index b932d780f5..61dcb10cde 100644 --- a/adjust.go +++ b/adjust.go @@ -765,60 +765,70 @@ func (f *File) adjustVolatileDeps(ws *xlsxWorksheet, sheet string, dir adjustDir return nil } -// adjustDrawings updates the two cell anchor pictures and charts object when -// inserting or deleting rows or columns. -func (a *xdrCellAnchor) adjustDrawings(dir adjustDirection, num, offset int) { - if a.From == nil || a.To == nil { - return +// adjustDrawings updates the starting anchor of the two cell anchor pictures +// and charts object when inserting or deleting rows or columns. +func (from *xlsxFrom) adjustDrawings(dir adjustDirection, num, offset int, editAs string) (bool, error) { + var ok bool + if dir == columns && from.Col+1 >= num && from.Col+offset >= 0 { + if from.Col+offset >= MaxColumns { + return false, ErrColumnNumber + } + from.Col += offset + ok = editAs == "oneCell" } - if offset > 0 && a.EditAs != "absolute" { - var move bool - if dir == columns { - if a.From.Col+1 >= num { - a.From.Col += offset - move = a.EditAs == "oneCell" - } - if a.To.Col+1 >= num && (move || a.EditAs == "") { - a.To.Col += offset - } - return + if dir == rows && from.Row+1 >= num && from.Row+offset >= 0 { + if from.Row+offset >= TotalRows { + return false, ErrMaxRows } - if a.From.Row+1 >= num { - a.From.Row += offset - move = a.EditAs == "oneCell" + from.Row += offset + ok = editAs == "oneCell" + } + return ok, nil +} + +// adjustDrawings updates the ending anchor of the two cell anchor pictures +// and charts object when inserting or deleting rows or columns. +func (to *xlsxTo) adjustDrawings(dir adjustDirection, num, offset int, editAs string, ok bool) error { + if dir == columns && to.Col+1 >= num && to.Col+offset >= 0 && ok { + if to.Col+offset >= MaxColumns { + return ErrColumnNumber } - if a.To.Row+1 >= num && (move || a.EditAs == "") { - a.To.Row += offset + to.Col += offset + } + if dir == rows && to.Row+1 >= num && to.Row+offset >= 0 && ok { + if to.Row+offset >= TotalRows { + return ErrMaxRows } + to.Row += offset + } + return nil +} + +// adjustDrawings updates the two cell anchor pictures and charts object when +// inserting or deleting rows or columns. +func (a *xdrCellAnchor) adjustDrawings(dir adjustDirection, num, offset int) error { + editAs := a.EditAs + if a.From == nil || a.To == nil || editAs == "absolute" { + return nil } + ok, err := a.From.adjustDrawings(dir, num, offset, editAs) + if err != nil { + return err + } + return a.To.adjustDrawings(dir, num, offset, editAs, ok || editAs == "") } // adjustDrawings updates the existing two cell anchor pictures and charts // object when inserting or deleting rows or columns. -func (a *xlsxCellAnchorPos) adjustDrawings(dir adjustDirection, num, offset int, editAs string) { - if a.From == nil || a.To == nil { - return +func (a *xlsxCellAnchorPos) adjustDrawings(dir adjustDirection, num, offset int, editAs string) error { + if a.From == nil || a.To == nil || editAs == "absolute" { + return nil } - if offset > 0 && editAs != "absolute" { - var move bool - if dir == columns { - if a.From.Col+1 >= num { - a.From.Col += offset - move = editAs == "oneCell" - } - if a.To.Col+1 >= num && (move || editAs == "") { - a.To.Col += offset - } - return - } - if a.From.Row+1 >= num { - a.From.Row += offset - move = editAs == "oneCell" - } - if a.To.Row+1 >= num && (move || editAs == "") { - a.To.Row += offset - } + ok, err := a.From.adjustDrawings(dir, num, offset, editAs) + if err != nil { + return err } + return a.To.adjustDrawings(dir, num, offset, editAs, ok || editAs == "") } // adjustDrawings updates the pictures and charts object when inserting or @@ -836,10 +846,9 @@ func (f *File) adjustDrawings(ws *xlsxWorksheet, sheet string, dir adjustDirecti if wsDr, _, err = f.drawingParser(drawingXML); err != nil { return err } - anchorCb := func(a *xdrCellAnchor) { + anchorCb := func(a *xdrCellAnchor) error { if a.GraphicFrame == "" { - a.adjustDrawings(dir, num, offset) - return + return a.adjustDrawings(dir, num, offset) } deCellAnchor := decodeCellAnchor{} deCellAnchorPos := decodeCellAnchorPos{} @@ -858,12 +867,17 @@ func (f *File) adjustDrawings(ws *xlsxWorksheet, sheet string, dir adjustDirecti Row: deCellAnchor.To.Row, RowOff: deCellAnchor.To.RowOff, } } - xlsxCellAnchorPos.adjustDrawings(dir, num, offset, a.EditAs) + if err = xlsxCellAnchorPos.adjustDrawings(dir, num, offset, a.EditAs); err != nil { + return err + } cellAnchor, _ := xml.Marshal(xlsxCellAnchorPos) a.GraphicFrame = strings.TrimSuffix(strings.TrimPrefix(string(cellAnchor), ""), "") + return err } for _, anchor := range wsDr.TwoCellAnchor { - anchorCb(anchor) + if err = anchorCb(anchor); err != nil { + return err + } } return nil } diff --git a/adjust_test.go b/adjust_test.go index 413e36af2b..7bde84a899 100644 --- a/adjust_test.go +++ b/adjust_test.go @@ -953,9 +953,10 @@ func TestAdjustVolatileDeps(t *testing.T) { func TestAdjustDrawings(t *testing.T) { f := NewFile() // Test add pictures to sheet with positioning - assert.NoError(t, f.AddPicture("Sheet1", "A1", filepath.Join("test", "images", "excel.jpg"), nil)) - assert.NoError(t, f.AddPicture("Sheet1", "A10", filepath.Join("test", "images", "excel.jpg"), &GraphicOptions{Positioning: "oneCell"})) - assert.NoError(t, f.AddPicture("Sheet1", "A20", filepath.Join("test", "images", "excel.jpg"), &GraphicOptions{Positioning: "absolute"})) + assert.NoError(t, f.AddPicture("Sheet1", "B2", filepath.Join("test", "images", "excel.jpg"), nil)) + assert.NoError(t, f.AddPicture("Sheet1", "B11", filepath.Join("test", "images", "excel.jpg"), &GraphicOptions{Positioning: "oneCell"})) + assert.NoError(t, f.AddPicture("Sheet1", "B21", filepath.Join("test", "images", "excel.jpg"), &GraphicOptions{Positioning: "absolute"})) + // Test adjust pictures on inserting columns and rows assert.NoError(t, f.InsertCols("Sheet1", "A", 1)) assert.NoError(t, f.InsertRows("Sheet1", 1, 1)) @@ -964,10 +965,17 @@ func TestAdjustDrawings(t *testing.T) { assert.NoError(t, f.InsertRows("Sheet1", 15, 1)) cells, err := f.GetPictureCells("Sheet1") assert.NoError(t, err) - assert.Equal(t, []string{"B2", "B12", "A20"}, cells) + assert.Equal(t, []string{"D3", "D13", "B21"}, cells) wb := filepath.Join("test", "TestAdjustDrawings.xlsx") assert.NoError(t, f.SaveAs(wb)) + // Test adjust pictures on deleting columns and rows + assert.NoError(t, f.RemoveCol("Sheet1", "A")) + assert.NoError(t, f.RemoveRow("Sheet1", 1)) + cells, err = f.GetPictureCells("Sheet1") + assert.NoError(t, err) + assert.Equal(t, []string{"C2", "C12", "B21"}, cells) + // Test adjust existing pictures on inserting columns and rows f, err = OpenFile(wb) assert.NoError(t, err) @@ -978,16 +986,39 @@ func TestAdjustDrawings(t *testing.T) { assert.NoError(t, f.InsertRows("Sheet1", 16, 1)) cells, err = f.GetPictureCells("Sheet1") assert.NoError(t, err) - assert.Equal(t, []string{"C3", "C14", "A20"}, cells) + assert.Equal(t, []string{"F4", "F15", "B21"}, cells) - // Test adjust pictures with unsupported charset + // Test adjust drawings with unsupported charset f, err = OpenFile(wb) assert.NoError(t, err) f.Pkg.Store("xl/drawings/drawing1.xml", MacintoshCyrillicCharset) assert.EqualError(t, f.InsertCols("Sheet1", "A", 1), "XML syntax error on line 1: invalid UTF-8") + errors := []error{ErrColumnNumber, ErrColumnNumber, ErrMaxRows, ErrMaxRows} + cells = []string{"XFD1", "XFB1"} + for i, cell := range cells { + f = NewFile() + assert.NoError(t, f.AddPicture("Sheet1", cell, filepath.Join("test", "images", "excel.jpg"), nil)) + assert.Equal(t, errors[i], f.InsertCols("Sheet1", "A", 1)) + assert.NoError(t, f.SaveAs(wb)) + f, err = OpenFile(wb) + assert.NoError(t, err) + assert.Equal(t, errors[i], f.InsertCols("Sheet1", "A", 1)) + } + errors = []error{ErrMaxRows, ErrMaxRows} + cells = []string{"A1048576", "A1048570"} + for i, cell := range cells { + f = NewFile() + assert.NoError(t, f.AddPicture("Sheet1", cell, filepath.Join("test", "images", "excel.jpg"), nil)) + assert.Equal(t, errors[i], f.InsertRows("Sheet1", 1, 1)) + assert.NoError(t, f.SaveAs(wb)) + f, err = OpenFile(wb) + assert.NoError(t, err) + assert.Equal(t, errors[i], f.InsertRows("Sheet1", 1, 1)) + } + a := xdrCellAnchor{} - a.adjustDrawings(columns, 0, 0) + assert.NoError(t, a.adjustDrawings(columns, 0, 0)) p := xlsxCellAnchorPos{} - p.adjustDrawings(columns, 0, 0, "") + assert.NoError(t, p.adjustDrawings(columns, 0, 0, "")) }