From 055349d8a62e6b4e66bcf3854c8a9086e912c409 Mon Sep 17 00:00:00 2001 From: xuri Date: Fri, 26 Apr 2024 00:23:10 +0800 Subject: [PATCH] Fix a v2.8.1 regression bug, error on duplicate rows, if conditional formatting or data validation has multiple cell range reference - Update unit tests --- adjust_test.go | 2 +- cell.go | 2 +- rows.go | 67 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 45 insertions(+), 26 deletions(-) diff --git a/adjust_test.go b/adjust_test.go index cde12fb..4f42e51 100644 --- a/adjust_test.go +++ b/adjust_test.go @@ -1114,7 +1114,7 @@ func TestAdjustDataValidations(t *testing.T) { // The double quote symbol in none formula data validation rules will be escaped in the Kingsoft WPS Office formula := strings.ReplaceAll(fmt.Sprintf("\"option1, %s", strings.Repeat("\"", 9)), "\"", """) ws.(*xlsxWorksheet).DataValidations.DataValidation[0].Formula1.Content = formula - f.RemoveCol("Sheet2", "A") + assert.NoError(t, f.RemoveCol("Sheet2", "A")) dvs, err := f.GetDataValidations("Sheet1") assert.NoError(t, err) assert.Equal(t, formula, dvs[0].Formula1) diff --git a/cell.go b/cell.go index 3b712c6..a13313a 100644 --- a/cell.go +++ b/cell.go @@ -506,7 +506,7 @@ func trimCellValue(value string, escape bool) (v string, ns xml.Attr) { if escape { var buf bytes.Buffer enc := xml.NewEncoder(&buf) - enc.EncodeToken(xml.CharData(value)) + _ = enc.EncodeToken(xml.CharData(value)) enc.Flush() value = buf.String() } diff --git a/rows.go b/rows.go index bf22d0c..d43a015 100644 --- a/rows.go +++ b/rows.go @@ -691,26 +691,46 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error { return err } +// duplicateSQRefHelper provides a function to adjust conditional formatting and +// data validations cell reference when duplicate rows. +func duplicateSQRefHelper(row, row2 int, ref string) (string, error) { + if !strings.Contains(ref, ":") { + ref += ":" + ref + } + abs := strings.Contains(ref, "$") + coordinates, err := rangeRefToCoordinates(ref) + if err != nil { + return "", err + } + x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3] + if y1 == y2 && y1 == row { + if ref, err = coordinatesToRangeRef([]int{x1, row2, x2, row2}, abs); err != nil { + return "", err + } + return ref, err + } + return "", err +} + // duplicateConditionalFormat create conditional formatting for the destination // row if there are conditional formats in the copied row. func (f *File) duplicateConditionalFormat(ws *xlsxWorksheet, sheet string, row, row2 int) error { var cfs []*xlsxConditionalFormatting for _, cf := range ws.ConditionalFormatting { if cf != nil { - if !strings.Contains(cf.SQRef, ":") { - cf.SQRef += ":" + cf.SQRef - } - abs := strings.Contains(cf.SQRef, "$") - coordinates, err := rangeRefToCoordinates(cf.SQRef) - if err != nil { - return err - } - x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3] - if y1 == y2 && y1 == row { - cfCopy := deepcopy.Copy(*cf).(xlsxConditionalFormatting) - if cfCopy.SQRef, err = coordinatesToRangeRef([]int{x1, row2, x2, row2}, abs); err != nil { + var SQRef []string + for _, ref := range strings.Split(cf.SQRef, " ") { + coordinates, err := duplicateSQRefHelper(row, row2, ref) + if err != nil { return err } + if coordinates != "" { + SQRef = append(SQRef, coordinates) + } + } + if len(SQRef) > 0 { + cfCopy := deepcopy.Copy(*cf).(xlsxConditionalFormatting) + cfCopy.SQRef = strings.Join(SQRef, " ") cfs = append(cfs, &cfCopy) } } @@ -728,20 +748,19 @@ func (f *File) duplicateDataValidations(ws *xlsxWorksheet, sheet string, row, ro var dvs []*xlsxDataValidation for _, dv := range ws.DataValidations.DataValidation { if dv != nil { - if !strings.Contains(dv.Sqref, ":") { - dv.Sqref += ":" + dv.Sqref - } - abs := strings.Contains(dv.Sqref, "$") - coordinates, err := rangeRefToCoordinates(dv.Sqref) - if err != nil { - return err - } - x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3] - if y1 == y2 && y1 == row { - dvCopy := deepcopy.Copy(*dv).(xlsxDataValidation) - if dvCopy.Sqref, err = coordinatesToRangeRef([]int{x1, row2, x2, row2}, abs); err != nil { + var SQRef []string + for _, ref := range strings.Split(dv.Sqref, " ") { + coordinates, err := duplicateSQRefHelper(row, row2, ref) + if err != nil { return err } + if coordinates != "" { + SQRef = append(SQRef, coordinates) + } + } + if len(SQRef) > 0 { + dvCopy := deepcopy.Copy(*dv).(xlsxDataValidation) + dvCopy.Sqref = strings.Join(SQRef, " ") dvs = append(dvs, &dvCopy) } }