From dc01264562e6e88d77a28042408029770ea32df4 Mon Sep 17 00:00:00 2001 From: Veniamin Albaev Date: Tue, 19 Mar 2019 19:14:41 +0300 Subject: Huge refactorig for consistent col/row numbering (#356) * Huge refactorig for consistent col/row numbering Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes. But have to go deeper, do fixes, after do related fixes and again and again. Major improvements: 1. Tests made stronger again (But still be weak). 2. "Empty" returns for incorrect input replaces with panic. 3. Check for correct col/row/cell naming & addressing by default. 4. Removed huge amount of duplicated code. 5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all, and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName(). 6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc). * Formatting fixes --- excelize.go | 229 ++---------------------------------------------------------- 1 file changed, 5 insertions(+), 224 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index feb41cb..7a50460 100644 --- a/excelize.go +++ b/excelize.go @@ -206,235 +206,16 @@ func (f *File) UpdateLinkedValue() { } } -// adjustHelper provides a function to adjust rows and columns dimensions, -// hyperlinks, merged cells and auto filter when inserting or deleting rows or -// columns. -// -// sheet: Worksheet name that we're editing -// column: Index number of the column we're inserting/deleting before -// row: Index number of the row we're inserting/deleting before -// offset: Number of rows/column to insert/delete negative values indicate deletion -// -// TODO: adjustCalcChain, adjustPageBreaks, adjustComments, -// adjustDataValidations, adjustProtectedCells -// -func (f *File) adjustHelper(sheet string, column, row, offset int) { - xlsx := f.workSheetReader(sheet) - f.adjustRowDimensions(xlsx, row, offset) - f.adjustColDimensions(xlsx, column, offset) - f.adjustHyperlinks(sheet, column, row, offset) - f.adjustMergeCells(xlsx, column, row, offset) - f.adjustAutoFilter(xlsx, column, row, offset) - checkSheet(xlsx) - checkRow(xlsx) -} - -// adjustColDimensions provides a function to update column dimensions when -// inserting or deleting rows or columns. -func (f *File) adjustColDimensions(xlsx *xlsxWorksheet, column, offset int) { - for i, r := range xlsx.SheetData.Row { - for k, v := range r.C { - axis := v.R - col := string(strings.Map(letterOnlyMapF, axis)) - row, _ := strconv.Atoi(strings.Map(intOnlyMapF, axis)) - yAxis := TitleToNumber(col) - if yAxis >= column && column != -1 { - xlsx.SheetData.Row[i].C[k].R = ToAlphaString(yAxis+offset) + strconv.Itoa(row) - } - } - } -} - -// adjustRowDimensions provides a function to update row dimensions when -// inserting or deleting rows or columns. -func (f *File) adjustRowDimensions(xlsx *xlsxWorksheet, rowIndex, offset int) { - if rowIndex == -1 { - return - } - for i, r := range xlsx.SheetData.Row { - if r.R >= rowIndex { - f.ajustSingleRowDimensions(&xlsx.SheetData.Row[i], r.R+offset) - } - } -} - -// ajustSingleRowDimensions provides a function to ajust single row dimensions. -func (f *File) ajustSingleRowDimensions(r *xlsxRow, row int) { - r.R = row - for i, col := range r.C { - r.C[i].R = string(strings.Map(letterOnlyMapF, col.R)) + strconv.Itoa(r.R) - } -} - -// adjustHyperlinks provides a function to update hyperlinks when inserting or -// deleting rows or columns. -func (f *File) adjustHyperlinks(sheet string, column, rowIndex, offset int) { +// GetMergeCells provides a function to get all merged cells from a worksheet currently. +func (f *File) GetMergeCells(sheet string) []MergeCell { xlsx := f.workSheetReader(sheet) - // order is important - if xlsx.Hyperlinks != nil && offset < 0 { - for i, v := range xlsx.Hyperlinks.Hyperlink { - axis := v.Ref - col := string(strings.Map(letterOnlyMapF, axis)) - row, _ := strconv.Atoi(strings.Map(intOnlyMapF, axis)) - yAxis := TitleToNumber(col) - if row == rowIndex || yAxis == column { - f.deleteSheetRelationships(sheet, v.RID) - if len(xlsx.Hyperlinks.Hyperlink) > 1 { - xlsx.Hyperlinks.Hyperlink = append(xlsx.Hyperlinks.Hyperlink[:i], xlsx.Hyperlinks.Hyperlink[i+1:]...) - } else { - xlsx.Hyperlinks = nil - } - } - } - } + var mergeCells []MergeCell - if xlsx.Hyperlinks != nil { - for i, v := range xlsx.Hyperlinks.Hyperlink { - axis := v.Ref - col := string(strings.Map(letterOnlyMapF, axis)) - row, _ := strconv.Atoi(strings.Map(intOnlyMapF, axis)) - xAxis := row + offset - yAxis := TitleToNumber(col) - if rowIndex != -1 && row >= rowIndex { - xlsx.Hyperlinks.Hyperlink[i].Ref = col + strconv.Itoa(xAxis) - } - if column != -1 && yAxis >= column { - xlsx.Hyperlinks.Hyperlink[i].Ref = ToAlphaString(yAxis+offset) + strconv.Itoa(row) - } - } - } -} - -// adjustMergeCellsHelper provides a function to update merged cells when -// inserting or deleting rows or columns. -func (f *File) adjustMergeCellsHelper(xlsx *xlsxWorksheet, column, rowIndex, offset int) { if xlsx.MergeCells != nil { - for k, v := range xlsx.MergeCells.Cells { - beg := strings.Split(v.Ref, ":")[0] - end := strings.Split(v.Ref, ":")[1] - - begcol := string(strings.Map(letterOnlyMapF, beg)) - begrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, beg)) - begxAxis := begrow + offset - begyAxis := TitleToNumber(begcol) - - endcol := string(strings.Map(letterOnlyMapF, end)) - endrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, end)) - endxAxis := endrow + offset - endyAxis := TitleToNumber(endcol) - - if rowIndex != -1 { - if begrow > 1 && begrow >= rowIndex { - beg = begcol + strconv.Itoa(begxAxis) - } - if endrow > 1 && endrow >= rowIndex { - end = endcol + strconv.Itoa(endxAxis) - } - } - - if column != -1 { - if begyAxis >= column { - beg = ToAlphaString(begyAxis+offset) + strconv.Itoa(endrow) - } - if endyAxis >= column { - end = ToAlphaString(endyAxis+offset) + strconv.Itoa(endrow) - } - } - - xlsx.MergeCells.Cells[k].Ref = beg + ":" + end - } - } -} - -// adjustMergeCells provides a function to update merged cells when inserting -// or deleting rows or columns. -func (f *File) adjustMergeCells(xlsx *xlsxWorksheet, column, rowIndex, offset int) { - f.adjustMergeCellsHelper(xlsx, column, rowIndex, offset) - - if xlsx.MergeCells != nil && offset < 0 { - for k, v := range xlsx.MergeCells.Cells { - beg := strings.Split(v.Ref, ":")[0] - end := strings.Split(v.Ref, ":")[1] - if beg == end { - xlsx.MergeCells.Count += offset - if len(xlsx.MergeCells.Cells) > 1 { - xlsx.MergeCells.Cells = append(xlsx.MergeCells.Cells[:k], xlsx.MergeCells.Cells[k+1:]...) - } else { - xlsx.MergeCells = nil - } - } - } - } -} - -// adjustAutoFilter provides a function to update the auto filter when -// inserting or deleting rows or columns. -func (f *File) adjustAutoFilter(xlsx *xlsxWorksheet, column, rowIndex, offset int) { - f.adjustAutoFilterHelper(xlsx, column, rowIndex, offset) - - if xlsx.AutoFilter != nil { - beg := strings.Split(xlsx.AutoFilter.Ref, ":")[0] - end := strings.Split(xlsx.AutoFilter.Ref, ":")[1] + mergeCells = make([]MergeCell, 0, len(xlsx.MergeCells.Cells)) - begcol := string(strings.Map(letterOnlyMapF, beg)) - begrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, beg)) - begxAxis := begrow + offset - - endcol := string(strings.Map(letterOnlyMapF, end)) - endrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, end)) - endxAxis := endrow + offset - endyAxis := TitleToNumber(endcol) - - if rowIndex != -1 { - if begrow >= rowIndex { - beg = begcol + strconv.Itoa(begxAxis) - } - if endrow >= rowIndex { - end = endcol + strconv.Itoa(endxAxis) - } - } - - if column != -1 && endyAxis >= column { - end = ToAlphaString(endyAxis+offset) + strconv.Itoa(endrow) - } - xlsx.AutoFilter.Ref = beg + ":" + end - } -} - -// adjustAutoFilterHelper provides a function to update the auto filter when -// inserting or deleting rows or columns. -func (f *File) adjustAutoFilterHelper(xlsx *xlsxWorksheet, column, rowIndex, offset int) { - if xlsx.AutoFilter != nil { - beg := strings.Split(xlsx.AutoFilter.Ref, ":")[0] - end := strings.Split(xlsx.AutoFilter.Ref, ":")[1] - - begcol := string(strings.Map(letterOnlyMapF, beg)) - begrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, beg)) - begyAxis := TitleToNumber(begcol) - - endcol := string(strings.Map(letterOnlyMapF, end)) - endyAxis := TitleToNumber(endcol) - endrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, end)) - - if (begrow == rowIndex && offset < 0) || (column == begyAxis && column == endyAxis) { - xlsx.AutoFilter = nil - for i, r := range xlsx.SheetData.Row { - if begrow < r.R && r.R <= endrow { - xlsx.SheetData.Row[i].Hidden = false - } - } - } - } -} - -// GetMergeCells provides a function to get all merged cells from a worksheet currently. -func (f *File) GetMergeCells(sheet string) []MergeCell { - mergeCells := []MergeCell{} - - xlsx := f.workSheetReader(sheet) - if xlsx.MergeCells != nil { - for i := 0; i < len(xlsx.MergeCells.Cells); i++ { + for i := range xlsx.MergeCells.Cells { ref := xlsx.MergeCells.Cells[i].Ref axis := strings.Split(ref, ":")[0] mergeCells = append(mergeCells, []string{ref, f.GetCellValue(sheet, axis)}) -- cgit v1.2.1