Skip to content

Commit

Permalink
fix AutoFilter not working in LibreOffice
Browse files Browse the repository at this point in the history
  • Loading branch information
martoche committed Feb 12, 2024
1 parent b90be58 commit b715f2b
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 1 deletion.
48 changes: 48 additions & 0 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,38 @@ func addRelationshipNameSpaceToWorksheet(worksheetMarshal string) string {
return newSheetMarshall
}

// AutoFilter doesn't work in LibreOffice unless a special "FilterDatabase" tag
// is present in the "DefinedNames" array. See:
// - https://github.com/SheetJS/sheetjs/issues/1165
// - https://bugs.documentfoundation.org/show_bug.cgi?id=118592
func autoFilterDefinedName(sheet *Sheet, sheetIndex int) (*xlsxDefinedName, error) {
if sheet.AutoFilter == nil {
return nil, nil
}

x0, y0, err := GetCoordsFromCellIDString(sheet.AutoFilter.TopLeftCell)
if err != nil {
return nil, err
}

x1, y1, err := GetCoordsFromCellIDString(sheet.AutoFilter.BottomRightCell)
if err != nil {
return nil, err
}

return &xlsxDefinedName{
Data: fmt.Sprintf(
"'%s'!%v:%v",
strings.ReplaceAll(sheet.Name, "'", "''"),
GetCellIDStringFromCoordsWithFixed(x0, y0, true, true),
GetCellIDStringFromCoordsWithFixed(x1, y1, true, true),
),
Name: "_xlnm._FilterDatabase",
LocalSheetID: sheetIndex - 1,
Hidden: true,
}, nil
}

// MakeStreamParts constructs a map of file name to XML content
// representing the file in terms of the structure of an XLSX file.
func (f *File) MakeStreamParts() (map[string]string, error) {
Expand Down Expand Up @@ -370,6 +402,14 @@ func (f *File) MakeStreamParts() (map[string]string, error) {
return parts, err
}
}

definedName, err := autoFilterDefinedName(sheet, sheetIndex)
if err != nil {
return parts, err
} else if definedName != nil {
workbook.DefinedNames.DefinedName = append(workbook.DefinedNames.DefinedName, *definedName)
}

sheetIndex++
}

Expand Down Expand Up @@ -511,6 +551,14 @@ func (f *File) MarshallParts(zipWriter *zip.Writer) error {
return wrap(err)
}
}

definedName, err := autoFilterDefinedName(sheet, sheetIndex)
if err != nil {
return wrap(err)
} else if definedName != nil {
workbook.DefinedNames.DefinedName = append(workbook.DefinedNames.DefinedName, *definedName)
}

sheetIndex++
}

Expand Down
19 changes: 19 additions & 0 deletions file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,25 @@ func TestFile(t *testing.T) {
c.Assert(s.Hidden, qt.Equals, true)
})

csRunO(c, "TestMarshalFileWithAutoFilter", func(c *qt.C, option FileOption) {
var f *File
f = NewFile(option)
sheet1, _ := f.AddSheet("MySheet")
sheet1.AutoFilter = &AutoFilter{
TopLeftCell: "A1",
BottomRightCell: "A1",
}

row1 := sheet1.AddRow()
cell1 := row1.AddCell()
cell1.SetString("A cell!")

parts, err := f.MakeStreamParts()
c.Assert(err, qt.IsNil)
c.Assert(parts["xl/workbook.xml"], qt.Contains, `<definedNames><definedName name="_xlnm._FilterDatabase" localSheetId="0" hidden="true">&#39;MySheet&#39;!$A$1:$A$1</definedName></definedNames>`)
c.Assert(parts["xl/worksheets/sheet1.xml"], qt.Contains, `<autoFilter ref="A1:A1"></autoFilter>`)
})

// We can save a File as a valid XLSX file at a given path.
csRunO(c, "TestSaveFileWithHyperlinks", func(c *qt.C, option FileOption) {
tmpPath, err := ioutil.TempDir("", "testsavefilewithhyperlinks")
Expand Down
2 changes: 1 addition & 1 deletion xmlWorkbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ type xlsxDefinedName struct {
Help string `xml:"help,attr,omitempty"`
ShortcutKey string `xml:"shortcutKey,attr,omitempty"`
StatusBar string `xml:"statusBar,attr,omitempty"`
LocalSheetID int `xml:"localSheetId,attr,omitempty"`
LocalSheetID int `xml:"localSheetId,attr"`
FunctionGroupID int `xml:"functionGroupId,attr,omitempty"`
Function bool `xml:"function,attr,omitempty"`
Hidden bool `xml:"hidden,attr,omitempty"`
Expand Down

0 comments on commit b715f2b

Please sign in to comment.