diff options
Diffstat (limited to 'cellmerged.go')
-rw-r--r-- | cellmerged.go | 159 |
1 files changed, 130 insertions, 29 deletions
diff --git a/cellmerged.go b/cellmerged.go index 4a5d11f..968a28a 100644 --- a/cellmerged.go +++ b/cellmerged.go @@ -9,28 +9,102 @@ package excelize -import "strings" +import ( + "fmt" + "strings" +) + +// MergeCell provides a function to merge cells by given coordinate area and +// sheet name. For example create a merged cell of D3:E9 on Sheet1: +// +// err := f.MergeCell("Sheet1", "D3", "E9") +// +// If you create a merged cell that overlaps with another existing merged cell, +// those merged cells that already exist will be removed. +// +// B1(x1,y1) D1(x2,y1) +// +--------------------------------+ +// | | +// | | +// A4(x3,y3) | C4(x4,y3) | +// +-----------------------------+ | +// | | | | +// | | | | +// | |B5(x1,y2) | D5(x2,y2)| +// | +--------------------------------+ +// | | +// | | +// |A8(x3,y4) C8(x4,y4)| +// +-----------------------------+ +// +func (f *File) MergeCell(sheet, hcell, vcell string) error { + rect1, err := f.areaRefToCoordinates(hcell + ":" + vcell) + if err != nil { + return err + } + // Correct the coordinate area, such correct C1:B3 to B1:C3. + if rect1[2] < rect1[0] { + rect1[0], rect1[2] = rect1[2], rect1[0] + } + + if rect1[3] < rect1[1] { + rect1[1], rect1[3] = rect1[3], rect1[1] + } + + hcell, _ = CoordinatesToCellName(rect1[0], rect1[1]) + vcell, _ = CoordinatesToCellName(rect1[2], rect1[3]) -// GetMergeCells provides a function to get all merged cells from a worksheet -// currently. -func (f *File) GetMergeCells(sheet string) ([]MergeCell, error) { - var mergeCells []MergeCell xlsx, err := f.workSheetReader(sheet) if err != nil { - return mergeCells, err + return err } + ref := hcell + ":" + vcell if xlsx.MergeCells != nil { - mergeCells = make([]MergeCell, 0, len(xlsx.MergeCells.Cells)) + for i := 0; i < len(xlsx.MergeCells.Cells); i++ { + cellData := xlsx.MergeCells.Cells[i] + if cellData == nil { + continue + } + cc := strings.Split(cellData.Ref, ":") + if len(cc) != 2 { + return fmt.Errorf("invalid area %q", cellData.Ref) + } - for i := range xlsx.MergeCells.Cells { - ref := xlsx.MergeCells.Cells[i].Ref - axis := strings.Split(ref, ":")[0] - val, _ := f.GetCellValue(sheet, axis) - mergeCells = append(mergeCells, []string{ref, val}) + rect2, err := f.areaRefToCoordinates(cellData.Ref) + if err != nil { + return err + } + + // Delete the merged cells of the overlapping area. + if isOverlap(rect1, rect2) { + xlsx.MergeCells.Cells = append(xlsx.MergeCells.Cells[:i], xlsx.MergeCells.Cells[i+1:]...) + i-- + + if rect1[0] > rect2[0] { + rect1[0], rect2[0] = rect2[0], rect1[0] + } + + if rect1[2] < rect2[2] { + rect1[2], rect2[2] = rect2[2], rect1[2] + } + + if rect1[1] > rect2[1] { + rect1[1], rect2[1] = rect2[1], rect1[1] + } + + if rect1[3] < rect2[3] { + rect1[3], rect2[3] = rect2[3], rect1[3] + } + hcell, _ = CoordinatesToCellName(rect1[0], rect1[1]) + vcell, _ = CoordinatesToCellName(rect1[2], rect1[3]) + ref = hcell + ":" + vcell + } } + xlsx.MergeCells.Cells = append(xlsx.MergeCells.Cells, &xlsxMergeCell{Ref: ref}) + } else { + xlsx.MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: ref}}} } - - return mergeCells, err + return err } // UnmergeCell provides a function to unmerge a given coordinate area. @@ -44,36 +118,41 @@ func (f *File) UnmergeCell(sheet string, hcell, vcell string) error { if err != nil { return err } - coordinates, err := f.areaRefToCoordinates(hcell + ":" + vcell) + rect1, err := f.areaRefToCoordinates(hcell + ":" + vcell) if err != nil { return err } - x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3] - if x2 < x1 { - x1, x2 = x2, x1 + if rect1[2] < rect1[0] { + rect1[0], rect1[2] = rect1[2], rect1[0] } - if y2 < y1 { - y1, y2 = y2, y1 + if rect1[3] < rect1[1] { + rect1[1], rect1[3] = rect1[3], rect1[1] } - hcell, _ = CoordinatesToCellName(x1, y1) - vcell, _ = CoordinatesToCellName(x2, y2) + hcell, _ = CoordinatesToCellName(rect1[0], rect1[1]) + vcell, _ = CoordinatesToCellName(rect1[2], rect1[3]) // return nil since no MergeCells in the sheet if xlsx.MergeCells == nil { return nil } - ref := hcell + ":" + vcell i := 0 for _, cellData := range xlsx.MergeCells.Cells { + if cellData == nil { + continue + } cc := strings.Split(cellData.Ref, ":") - c1, _ := checkCellInArea(hcell, cellData.Ref) - c2, _ := checkCellInArea(vcell, cellData.Ref) - c3, _ := checkCellInArea(cc[0], ref) - c4, _ := checkCellInArea(cc[1], ref) - // skip the overlapped mergecell - if c1 || c2 || c3 || c4 { + if len(cc) != 2 { + return fmt.Errorf("invalid area %q", cellData.Ref) + } + + rect2, err := f.areaRefToCoordinates(cellData.Ref) + if err != nil { + return err + } + + if isOverlap(rect1, rect2) { continue } xlsx.MergeCells.Cells[i] = cellData @@ -83,6 +162,28 @@ func (f *File) UnmergeCell(sheet string, hcell, vcell string) error { return nil } +// GetMergeCells provides a function to get all merged cells from a worksheet +// currently. +func (f *File) GetMergeCells(sheet string) ([]MergeCell, error) { + var mergeCells []MergeCell + xlsx, err := f.workSheetReader(sheet) + if err != nil { + return mergeCells, err + } + if xlsx.MergeCells != nil { + mergeCells = make([]MergeCell, 0, len(xlsx.MergeCells.Cells)) + + for i := range xlsx.MergeCells.Cells { + ref := xlsx.MergeCells.Cells[i].Ref + axis := strings.Split(ref, ":")[0] + val, _ := f.GetCellValue(sheet, axis) + mergeCells = append(mergeCells, []string{ref, val}) + } + } + + return mergeCells, err +} + // MergeCell define a merged cell data. // It consists of the following structure. // example: []string{"D4:E10", "cell value"} |