- 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:
parent
963a058535
commit
f20bbd1f1d
77
adjust.go
77
adjust.go
|
@ -237,38 +237,43 @@ 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) {
|
||||||
if !strings.Contains(ref, ":") {
|
var SQRef []string
|
||||||
ref += ":" + ref
|
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
|
return strings.Join(SQRef, " "), nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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--
|
||||||
|
|
|
@ -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))
|
||||||
|
|
2
calc.go
2
calc.go
|
@ -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,
|
||||||
|
|
|
@ -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",
|
||||||
|
|
4
table.go
4
table.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue