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,18 +237,19 @@ func (f *File) adjustSingleRowFormulas(sheet, sheetN string, r *xlsxRow, num, of
} }
// adjustCellRef provides a function to adjust cell reference. // adjustCellRef provides a function to adjust cell reference.
func (f *File) adjustCellRef(ref string, dir adjustDirection, num, offset int) (string, bool, error) { 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, ":") { if !strings.Contains(ref, ":") {
ref += ":" + ref ref += ":" + ref
} }
var delete bool
coordinates, err := rangeRefToCoordinates(ref) coordinates, err := rangeRefToCoordinates(ref)
if err != nil { if err != nil {
return ref, delete, err return "", err
} }
if dir == columns { if dir == columns {
if offset < 0 && coordinates[0] == coordinates[2] { if offset < 0 && coordinates[0] == coordinates[2] {
delete = true continue
} }
if coordinates[0] >= num { if coordinates[0] >= num {
coordinates[0] += offset coordinates[0] += offset
@ -258,7 +259,7 @@ func (f *File) adjustCellRef(ref string, dir adjustDirection, num, offset int) (
} }
} else { } else {
if offset < 0 && coordinates[1] == coordinates[3] { if offset < 0 && coordinates[1] == coordinates[3] {
delete = true continue
} }
if coordinates[1] >= num { if coordinates[1] >= num {
coordinates[1] += offset coordinates[1] += offset
@ -267,8 +268,12 @@ func (f *File) adjustCellRef(ref string, dir adjustDirection, num, offset int) (
coordinates[3] += offset coordinates[3] += offset
} }
} }
ref, err = coordinatesToRangeRef(coordinates) if ref, err = coordinatesToRangeRef(coordinates); err != nil {
return ref, delete, err return "", err
}
SQRef = append(SQRef, ref)
}
return strings.Join(SQRef, " "), nil
} }
// adjustFormula provides a function to adjust formula reference and shared // 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 return nil
} }
if cell.F.Ref != "" && sheet == sheetN { 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 return err
} }
if si && cell.F.Si != nil { if si && cell.F.Si != nil {
@ -932,11 +937,11 @@ func (f *File) adjustConditionalFormats(ws *xlsxWorksheet, sheet string, dir adj
if cf == nil { if cf == nil {
continue continue
} }
ref, del, err := f.adjustCellRef(cf.SQRef, dir, num, offset) ref, err := f.adjustCellRef(cf.SQRef, dir, num, offset)
if err != nil { if err != nil {
return err return err
} }
if del { if ref == "" {
ws.ConditionalFormatting = append(ws.ConditionalFormatting[:i], ws.ConditionalFormatting = append(ws.ConditionalFormatting[:i],
ws.ConditionalFormatting[i+1:]...) ws.ConditionalFormatting[i+1:]...)
i-- i--
@ -967,11 +972,11 @@ func (f *File) adjustDataValidations(ws *xlsxWorksheet, sheet string, dir adjust
continue continue
} }
if sheet == sheetN { 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 { if err != nil {
return err return err
} }
if del { if ref == "" {
worksheet.DataValidations.DataValidation = append(worksheet.DataValidations.DataValidation[:i], worksheet.DataValidations.DataValidation = append(worksheet.DataValidations.DataValidation[:i],
worksheet.DataValidations.DataValidation[i+1:]...) worksheet.DataValidations.DataValidation[i+1:]...)
i-- i--

View File

@ -1059,6 +1059,16 @@ func TestAdjustDataValidations(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "\"A<,B>,C\",D\t,E',F\"", dvs[2].Formula1) 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 = NewDataValidation(true)
dv.Sqref = "C5:D6" dv.Sqref = "C5:D6"
assert.NoError(t, dv.SetRange("Sheet1!A1048576", "Sheet1!XFD1", DataValidationTypeWhole, DataValidationOperatorBetween)) 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") return newErrorFormulaArg(formulaErrorVALUE, "DATE requires 3 number arguments")
} }
d := makeDate(int(year.Number), time.Month(month.Number), int(day.Number)) 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, // 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", "=XOR(1>0,0>1,INT(0),INT(1),A1:A4,2)": "FALSE",
// Date and Time Functions // Date and Time Functions
// DATE // DATE
"=DATE(2020,10,21)": "2020-10-21 00:00:00 +0000 UTC", "=DATE(2020,10,21)": "44125",
"=DATE(1900,1,1)": "1899-12-31 00:00:00 +0000 UTC", "=DATE(2020,10,21)+1": "44126",
"=DATE(1900,1,1)": "1",
// DATEDIF // DATEDIF
"=DATEDIF(43101,43101,\"D\")": "0", "=DATEDIF(43101,43101,\"D\")": "0",
"=DATEDIF(43101,43891,\"d\")": "790", "=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) filterRange := fmt.Sprintf("'%s'!%s", sheet, ref)
d := xlsxDefinedName{ d := xlsxDefinedName{
Name: builtInDefinedNames[2], Name: builtInDefinedNames[3],
Hidden: true, Hidden: true,
LocalSheetID: intPtr(sheetID), LocalSheetID: intPtr(sheetID),
Data: filterRange, Data: filterRange,
@ -490,7 +490,7 @@ func (f *File) AutoFilter(sheet, rangeRef string, opts []AutoFilterOptions) erro
if definedName.LocalSheetID != nil { if definedName.LocalSheetID != nil {
localSheetID = *definedName.LocalSheetID 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 wb.DefinedNames.DefinedName[idx].Data = filterRange
definedNameExists = true 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") 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 // Test add auto filter with empty local sheet ID
f = NewFile() 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)) assert.NoError(t, f.AutoFilter("Sheet1", "A1:B1", nil))
} }