This closes #1830, closes #1831, and closes #1833

- Fix a v2.8.1 regression bug, auto filter does not work in the LibreOffice
- Fix a v2.8.1 regression bug, support to adjust data validation with multiple cell range
- Fix incorrect result data type of the DATE formula function
- Update the unit tests
This commit is contained in:
xuri 2024-03-04 21:40:27 +08:00
parent 963a058535
commit f20bbd1f1d
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
6 changed files with 58 additions and 42 deletions

View File

@ -237,38 +237,43 @@ func (f *File) adjustSingleRowFormulas(sheet, sheetN string, r *xlsxRow, num, of
}
// adjustCellRef provides a function to adjust cell reference.
func (f *File) adjustCellRef(ref string, dir adjustDirection, num, offset int) (string, bool, error) {
if !strings.Contains(ref, ":") {
ref += ":" + ref
func (f *File) adjustCellRef(cellRef string, dir adjustDirection, num, offset int) (string, error) {
var SQRef []string
for _, ref := range strings.Split(cellRef, " ") {
if !strings.Contains(ref, ":") {
ref += ":" + ref
}
coordinates, err := rangeRefToCoordinates(ref)
if err != nil {
return "", err
}
if dir == columns {
if offset < 0 && coordinates[0] == coordinates[2] {
continue
}
if coordinates[0] >= num {
coordinates[0] += offset
}
if coordinates[2] >= num {
coordinates[2] += offset
}
} else {
if offset < 0 && coordinates[1] == coordinates[3] {
continue
}
if coordinates[1] >= num {
coordinates[1] += offset
}
if coordinates[3] >= num {
coordinates[3] += offset
}
}
if ref, err = coordinatesToRangeRef(coordinates); err != nil {
return "", err
}
SQRef = append(SQRef, ref)
}
var delete bool
coordinates, err := rangeRefToCoordinates(ref)
if err != nil {
return ref, delete, err
}
if dir == columns {
if offset < 0 && coordinates[0] == coordinates[2] {
delete = true
}
if coordinates[0] >= num {
coordinates[0] += offset
}
if coordinates[2] >= num {
coordinates[2] += offset
}
} else {
if offset < 0 && coordinates[1] == coordinates[3] {
delete = true
}
if coordinates[1] >= num {
coordinates[1] += offset
}
if coordinates[3] >= num {
coordinates[3] += offset
}
}
ref, err = coordinatesToRangeRef(coordinates)
return ref, delete, err
return strings.Join(SQRef, " "), nil
}
// adjustFormula provides a function to adjust formula reference and shared
@ -284,7 +289,7 @@ func (f *File) adjustFormula(sheet, sheetN string, cell *xlsxC, dir adjustDirect
return nil
}
if cell.F.Ref != "" && sheet == sheetN {
if cell.F.Ref, _, err = f.adjustCellRef(cell.F.Ref, dir, num, offset); err != nil {
if cell.F.Ref, err = f.adjustCellRef(cell.F.Ref, dir, num, offset); err != nil {
return err
}
if si && cell.F.Si != nil {
@ -932,11 +937,11 @@ func (f *File) adjustConditionalFormats(ws *xlsxWorksheet, sheet string, dir adj
if cf == nil {
continue
}
ref, del, err := f.adjustCellRef(cf.SQRef, dir, num, offset)
ref, err := f.adjustCellRef(cf.SQRef, dir, num, offset)
if err != nil {
return err
}
if del {
if ref == "" {
ws.ConditionalFormatting = append(ws.ConditionalFormatting[:i],
ws.ConditionalFormatting[i+1:]...)
i--
@ -967,11 +972,11 @@ func (f *File) adjustDataValidations(ws *xlsxWorksheet, sheet string, dir adjust
continue
}
if sheet == sheetN {
ref, del, err := f.adjustCellRef(dv.Sqref, dir, num, offset)
ref, err := f.adjustCellRef(dv.Sqref, dir, num, offset)
if err != nil {
return err
}
if del {
if ref == "" {
worksheet.DataValidations.DataValidation = append(worksheet.DataValidations.DataValidation[:i],
worksheet.DataValidations.DataValidation[i+1:]...)
i--

View File

@ -1059,6 +1059,16 @@ func TestAdjustDataValidations(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "\"A<,B>,C\",D\t,E',F\"", dvs[2].Formula1)
// Test adjust data validation with multiple cell range
dv = NewDataValidation(true)
dv.Sqref = "G1:G3 H1:H3"
assert.NoError(t, dv.SetDropList([]string{"1", "2", "3"}))
assert.NoError(t, f.AddDataValidation("Sheet1", dv))
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
dvs, err = f.GetDataValidations("Sheet1")
assert.NoError(t, err)
assert.Equal(t, "G1:G4 H1:H4", dvs[3].Sqref)
dv = NewDataValidation(true)
dv.Sqref = "C5:D6"
assert.NoError(t, dv.SetRange("Sheet1!A1048576", "Sheet1!XFD1", DataValidationTypeWhole, DataValidationOperatorBetween))

View File

@ -12081,7 +12081,7 @@ func (fn *formulaFuncs) DATE(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorVALUE, "DATE requires 3 number arguments")
}
d := makeDate(int(year.Number), time.Month(month.Number), int(day.Number))
return newStringFormulaArg(timeFromExcelTime(daysBetween(excelMinTime1900.Unix(), d)+1, false).String())
return newNumberFormulaArg(daysBetween(excelMinTime1900.Unix(), d) + 1)
}
// calcDateDif is an implementation of the formula function DATEDIF,

View File

@ -1540,8 +1540,9 @@ func TestCalcCellValue(t *testing.T) {
"=XOR(1>0,0>1,INT(0),INT(1),A1:A4,2)": "FALSE",
// Date and Time Functions
// DATE
"=DATE(2020,10,21)": "2020-10-21 00:00:00 +0000 UTC",
"=DATE(1900,1,1)": "1899-12-31 00:00:00 +0000 UTC",
"=DATE(2020,10,21)": "44125",
"=DATE(2020,10,21)+1": "44126",
"=DATE(1900,1,1)": "1",
// DATEDIF
"=DATEDIF(43101,43101,\"D\")": "0",
"=DATEDIF(43101,43891,\"d\")": "790",

View File

@ -474,7 +474,7 @@ func (f *File) AutoFilter(sheet, rangeRef string, opts []AutoFilterOptions) erro
}
filterRange := fmt.Sprintf("'%s'!%s", sheet, ref)
d := xlsxDefinedName{
Name: builtInDefinedNames[2],
Name: builtInDefinedNames[3],
Hidden: true,
LocalSheetID: intPtr(sheetID),
Data: filterRange,
@ -490,7 +490,7 @@ func (f *File) AutoFilter(sheet, rangeRef string, opts []AutoFilterOptions) erro
if definedName.LocalSheetID != nil {
localSheetID = *definedName.LocalSheetID
}
if definedName.Name == builtInDefinedNames[2] && localSheetID == sheetID && definedName.Hidden {
if definedName.Name == builtInDefinedNames[3] && localSheetID == sheetID && definedName.Hidden {
wb.DefinedNames.DefinedName[idx].Data = filterRange
definedNameExists = true
}

View File

@ -174,7 +174,7 @@ func TestAutoFilter(t *testing.T) {
assert.EqualError(t, f.AutoFilter("Sheet1", "D4:B1", nil), "XML syntax error on line 1: invalid UTF-8")
// Test add auto filter with empty local sheet ID
f = NewFile()
f.WorkBook = &xlsxWorkbook{DefinedNames: &xlsxDefinedNames{DefinedName: []xlsxDefinedName{{Name: builtInDefinedNames[2], Hidden: true}}}}
f.WorkBook = &xlsxWorkbook{DefinedNames: &xlsxDefinedNames{DefinedName: []xlsxDefinedName{{Name: builtInDefinedNames[3], Hidden: true}}}}
assert.NoError(t, f.AutoFilter("Sheet1", "A1:B1", nil))
}