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
This commit is contained in:
xuri 2024-04-26 00:23:10 +08:00
parent f8487a68a8
commit 055349d8a6
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
3 changed files with 45 additions and 26 deletions

View File

@ -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 // 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)), "\"", """) formula := strings.ReplaceAll(fmt.Sprintf("\"option1, %s", strings.Repeat("\"", 9)), "\"", """)
ws.(*xlsxWorksheet).DataValidations.DataValidation[0].Formula1.Content = formula ws.(*xlsxWorksheet).DataValidations.DataValidation[0].Formula1.Content = formula
f.RemoveCol("Sheet2", "A") assert.NoError(t, f.RemoveCol("Sheet2", "A"))
dvs, err := f.GetDataValidations("Sheet1") dvs, err := f.GetDataValidations("Sheet1")
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, formula, dvs[0].Formula1) assert.Equal(t, formula, dvs[0].Formula1)

View File

@ -506,7 +506,7 @@ func trimCellValue(value string, escape bool) (v string, ns xml.Attr) {
if escape { if escape {
var buf bytes.Buffer var buf bytes.Buffer
enc := xml.NewEncoder(&buf) enc := xml.NewEncoder(&buf)
enc.EncodeToken(xml.CharData(value)) _ = enc.EncodeToken(xml.CharData(value))
enc.Flush() enc.Flush()
value = buf.String() value = buf.String()
} }

67
rows.go
View File

@ -691,26 +691,46 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
return err 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 // duplicateConditionalFormat create conditional formatting for the destination
// row if there are conditional formats in the copied row. // row if there are conditional formats in the copied row.
func (f *File) duplicateConditionalFormat(ws *xlsxWorksheet, sheet string, row, row2 int) error { func (f *File) duplicateConditionalFormat(ws *xlsxWorksheet, sheet string, row, row2 int) error {
var cfs []*xlsxConditionalFormatting var cfs []*xlsxConditionalFormatting
for _, cf := range ws.ConditionalFormatting { for _, cf := range ws.ConditionalFormatting {
if cf != nil { if cf != nil {
if !strings.Contains(cf.SQRef, ":") { var SQRef []string
cf.SQRef += ":" + cf.SQRef for _, ref := range strings.Split(cf.SQRef, " ") {
} coordinates, err := duplicateSQRefHelper(row, row2, ref)
abs := strings.Contains(cf.SQRef, "$") if err != nil {
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 {
return err 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) cfs = append(cfs, &cfCopy)
} }
} }
@ -728,20 +748,19 @@ func (f *File) duplicateDataValidations(ws *xlsxWorksheet, sheet string, row, ro
var dvs []*xlsxDataValidation var dvs []*xlsxDataValidation
for _, dv := range ws.DataValidations.DataValidation { for _, dv := range ws.DataValidations.DataValidation {
if dv != nil { if dv != nil {
if !strings.Contains(dv.Sqref, ":") { var SQRef []string
dv.Sqref += ":" + dv.Sqref for _, ref := range strings.Split(dv.Sqref, " ") {
} coordinates, err := duplicateSQRefHelper(row, row2, ref)
abs := strings.Contains(dv.Sqref, "$") if err != nil {
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 {
return err 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) dvs = append(dvs, &dvCopy)
} }
} }