@@ -112,20 +112,12 @@ func (f *File) UnmergeCell(sheet, topLeftCell, bottomRightCell string) error {
112112 if ws .MergeCells == nil {
113113 return nil
114114 }
115- if err = f .mergeOverlapCells (ws ); err != nil {
115+ if err = ws .mergeOverlapCells (); err != nil {
116116 return err
117117 }
118118 i := 0
119119 for _ , mergeCell := range ws .MergeCells .Cells {
120- if mergeCell == nil {
121- continue
122- }
123- mergedCellsRef := mergeCell .Ref
124- if ! strings .Contains (mergedCellsRef , ":" ) {
125- mergedCellsRef += ":" + mergedCellsRef
126- }
127- rect2 , _ := rangeRefToCoordinates (mergedCellsRef )
128- if isOverlap (rect1 , rect2 ) {
120+ if rect2 , _ := rangeRefToCoordinates (mergeCell .Ref ); isOverlap (rect1 , rect2 ) {
129121 continue
130122 }
131123 ws .MergeCells .Cells [i ] = mergeCell
@@ -163,7 +155,7 @@ func (f *File) GetMergeCells(sheet string, withoutValues ...bool) ([]MergeCell,
163155 return mergeCells , err
164156 }
165157 if ws .MergeCells != nil {
166- if err = f .mergeOverlapCells (ws ); err != nil {
158+ if err = ws .mergeOverlapCells (); err != nil {
167159 return mergeCells , err
168160 }
169161 mergeCells = make ([]MergeCell , 0 , len (ws .MergeCells .Cells ))
@@ -179,123 +171,56 @@ func (f *File) GetMergeCells(sheet string, withoutValues ...bool) ([]MergeCell,
179171 return mergeCells , err
180172}
181173
182- // overlapRange calculate overlap range of merged cells, and returns max
183- // column and rows of the range.
184- func overlapRange (ws * xlsxWorksheet ) (row , col int , err error ) {
185- var rect []int
186- for _ , mergeCell := range ws .MergeCells .Cells {
187- if mergeCell == nil {
174+ // mergeOverlapCells merge overlap cells.
175+ func (ws * xlsxWorksheet ) mergeOverlapCells () error {
176+ var (
177+ err error
178+ rectList [][]int
179+ merged = true
180+ )
181+ for _ , cell := range ws .MergeCells .Cells {
182+ if cell == nil {
188183 continue
189184 }
190- if rect , err = mergeCell .Rect (); err != nil {
191- return
192- }
193- x1 , y1 , x2 , y2 := rect [0 ], rect [1 ], rect [2 ], rect [3 ]
194- if x1 > col {
195- col = x1
196- }
197- if x2 > col {
198- col = x2
199- }
200- if y1 > row {
201- row = y1
202- }
203- if y2 > row {
204- row = y2
205- }
206- }
207- return
208- }
209-
210- // flatMergedCells convert merged cells range reference to cell-matrix.
211- func flatMergedCells (ws * xlsxWorksheet , matrix [][]* xlsxMergeCell ) error {
212- for i , cell := range ws .MergeCells .Cells {
213- rect , err := cell .Rect ()
214- if err != nil {
185+ if cell .rect , err = cell .Rect (); err != nil {
215186 return err
216187 }
217- x1 , y1 , x2 , y2 := rect [0 ]- 1 , rect [1 ]- 1 , rect [2 ]- 1 , rect [3 ]- 1
218- var overlapCells []* xlsxMergeCell
219- for x := x1 ; x <= x2 ; x ++ {
220- for y := y1 ; y <= y2 ; y ++ {
221- if matrix [x ][y ] != nil {
222- overlapCells = append (overlapCells , matrix [x ][y ])
223- }
224- matrix [x ][y ] = cell
225- }
226- }
227- if len (overlapCells ) != 0 {
228- newCell := cell
229- for _ , overlapCell := range overlapCells {
230- newCell = mergeCell (cell , overlapCell )
188+ rectList = append (rectList , cell .rect )
189+ }
190+ for merged {
191+ merged = false
192+ var mergedRectList [][]int
193+ used := make ([]bool , len (rectList ))
194+ for i := 0 ; i < len (rectList ); i ++ {
195+ if used [i ] {
196+ continue
231197 }
232- newRect , _ := newCell .Rect ()
233- x1 , y1 , x2 , y2 := newRect [0 ]- 1 , newRect [1 ]- 1 , newRect [2 ]- 1 , newRect [3 ]- 1
234- for x := x1 ; x <= x2 ; x ++ {
235- for y := y1 ; y <= y2 ; y ++ {
236- matrix [x ][y ] = newCell
198+ r1 := rectList [i ]
199+ for j := i + 1 ; j < len (rectList ); j ++ {
200+ if used [j ] {
201+ continue
237202 }
238- }
239- ws .MergeCells .Cells [i ] = newCell
240- }
241- }
242- return nil
243- }
244-
245- // mergeOverlapCells merge overlap cells.
246- func (f * File ) mergeOverlapCells (ws * xlsxWorksheet ) error {
247- rows , cols , err := overlapRange (ws )
248- if err != nil {
249- return err
250- }
251- if rows == 0 || cols == 0 {
252- return nil
253- }
254- matrix := make ([][]* xlsxMergeCell , cols )
255- for i := range matrix {
256- matrix [i ] = make ([]* xlsxMergeCell , rows )
257- }
258- _ = flatMergedCells (ws , matrix )
259- mergeCells := ws .MergeCells .Cells [:0 ]
260- for _ , cell := range ws .MergeCells .Cells {
261- rect , _ := cell .Rect ()
262- x1 , y1 , x2 , y2 := rect [0 ]- 1 , rect [1 ]- 1 , rect [2 ]- 1 , rect [3 ]- 1
263- if matrix [x1 ][y1 ] == cell {
264- mergeCells = append (mergeCells , cell )
265- for x := x1 ; x <= x2 ; x ++ {
266- for y := y1 ; y <= y2 ; y ++ {
267- matrix [x ][y ] = nil
203+ if r2 := rectList [j ]; isOverlap (r1 , r2 ) {
204+ r1 = []int {
205+ min (r1 [0 ], r2 [0 ]),
206+ min (r1 [1 ], r2 [1 ]),
207+ max (r1 [2 ], r2 [2 ]),
208+ max (r1 [3 ], r2 [3 ]),
209+ }
210+ merged , used [j ] = true , true
268211 }
269212 }
213+ mergedRectList = append (mergedRectList , r1 )
270214 }
215+ rectList = mergedRectList
271216 }
272- ws .MergeCells .Count , ws .MergeCells .Cells = len (mergeCells ), mergeCells
273- return nil
274- }
275-
276- // mergeCell merge two cells.
277- func mergeCell (cell1 , cell2 * xlsxMergeCell ) * xlsxMergeCell {
278- rect1 , _ := cell1 .Rect ()
279- rect2 , _ := cell2 .Rect ()
280-
281- if rect1 [0 ] > rect2 [0 ] {
282- rect1 [0 ], rect2 [0 ] = rect2 [0 ], rect1 [0 ]
283- }
284-
285- if rect1 [2 ] < rect2 [2 ] {
286- rect1 [2 ], rect2 [2 ] = rect2 [2 ], rect1 [2 ]
287- }
288-
289- if rect1 [1 ] > rect2 [1 ] {
290- rect1 [1 ], rect2 [1 ] = rect2 [1 ], rect1 [1 ]
291- }
292-
293- if rect1 [3 ] < rect2 [3 ] {
294- rect1 [3 ], rect2 [3 ] = rect2 [3 ], rect1 [3 ]
217+ ws .MergeCells .Cells = make ([]* xlsxMergeCell , 0 , len (rectList ))
218+ for _ , r := range rectList {
219+ ref , _ := coordinatesToRangeRef (r )
220+ ws .MergeCells .Cells = append (ws .MergeCells .Cells , & xlsxMergeCell {Ref : ref , rect : r })
295221 }
296- topLeftCell , _ := CoordinatesToCellName (rect1 [0 ], rect1 [1 ])
297- bottomRightCell , _ := CoordinatesToCellName (rect1 [2 ], rect1 [3 ])
298- return & xlsxMergeCell {rect : rect1 , Ref : topLeftCell + ":" + bottomRightCell }
222+ ws .MergeCells .Count = len (ws .MergeCells .Cells )
223+ return err
299224}
300225
301226// MergeCell define a merged cell data.
@@ -317,9 +242,5 @@ func (m *MergeCell) GetStartAxis() string {
317242// GetEndAxis returns the bottom right cell reference of merged range, for
318243// example: "D4".
319244func (m * MergeCell ) GetEndAxis () string {
320- coordinates := strings .Split ((* m )[0 ], ":" )
321- if len (coordinates ) == 2 {
322- return coordinates [1 ]
323- }
324- return coordinates [0 ]
245+ return strings .Split ((* m )[0 ], ":" )[1 ]
325246}
0 commit comments