Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix AutoFilter not working in LibreOffice #798

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,41 @@ func addRelationshipNameSpaceToWorksheet(worksheetMarshal string) string {
return newSheetMarshall
}

func cellIDStringWithFixed(cellIDString string) string {
letterPart := strings.Map(letterOnlyMapF, cellIDString)
intPart := strings.Map(intOnlyMapF, cellIDString)

if letterPart != "" && intPart == "" {
return fixedCellRefChar + letterPart
} else if letterPart != "" && intPart != "" {
return fixedCellRefChar + letterPart + fixedCellRefChar + intPart
}

return ""
}

// 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
}

return &xlsxDefinedName{
Data: fmt.Sprintf(
"'%s'!%v:%v",
strings.ReplaceAll(sheet.Name, "'", "''"),
cellIDStringWithFixed(sheet.AutoFilter.TopLeftCell),
cellIDStringWithFixed(sheet.AutoFilter.BottomRightCell),
),
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 +405,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 +554,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: "D",
}

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:$D</definedName></definedNames>`)
c.Assert(parts["xl/worksheets/sheet1.xml"], qt.Contains, `<autoFilter ref="A1:D"></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
Loading