New functions: SetDefinedName and GetDefinedName added

This commit is contained in:
xuri 2019-06-18 23:07:44 +08:00
parent 5cf1c05ed4
commit a335be7e4e
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
4 changed files with 135 additions and 20 deletions

View File

@ -182,6 +182,11 @@ func TestSaveAsWrongPath(t *testing.T) {
}
}
func TestOpenReader(t *testing.T) {
_, err := OpenReader(strings.NewReader(""))
assert.EqualError(t, err, "zip: not a valid zip file")
}
func TestBrokenFile(t *testing.T) {
// Test write file with broken file struct.
f := File{}
@ -1033,22 +1038,6 @@ func TestHSL(t *testing.T) {
t.Log(RGBToHSL(250, 50, 100))
}
func TestSearchSheet(t *testing.T) {
f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
if !assert.NoError(t, err) {
t.FailNow()
}
// Test search in a not exists worksheet.
t.Log(f.SearchSheet("Sheet4", ""))
// Test search a not exists value.
t.Log(f.SearchSheet("Sheet1", "X"))
t.Log(f.SearchSheet("Sheet1", "A"))
// Test search the coordinates where the numerical value in the range of
// "0-9" of Sheet1 is described by regular expression:
t.Log(f.SearchSheet("Sheet1", "[0-9]", true))
}
func TestProtectSheet(t *testing.T) {
f := NewFile()
f.ProtectSheet("Sheet1", nil)

View File

@ -704,18 +704,14 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
var (
regSearch bool
result []string
inElement string
r xlsxRow
)
for _, r := range reg {
regSearch = r
}
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return result, err
}
name, ok := f.sheetMap[trimSheetName(sheet)]
if !ok {
return result, nil
@ -724,6 +720,17 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
output, _ := xml.Marshal(f.Sheet[name])
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
}
return f.searchSheet(name, value, regSearch)
}
// searchSheet provides a function to get coordinates by given worksheet name,
// cell value, and regular expression.
func (f *File) searchSheet(name, value string, regSearch bool) ([]string, error) {
var (
inElement string
result []string
r xlsxRow
)
xml.NewDecoder(bytes.NewReader(f.readXML(name)))
d := f.sharedStringsReader()
@ -1213,6 +1220,71 @@ func (f *File) GetPageLayout(sheet string, opts ...PageLayoutOptionPtr) error {
return err
}
// SetDefinedName provides a function to set the defined names of the workbook
// or worksheet. If not specified scopr, the default scope is workbook.
// For example:
//
// f.SetDefinedName(&excelize.DefinedName{
// Name: "Amount",
// RefersTo: "Sheet1!$A$2:$D$5",
// Comment: "defined name comment",
// Scope: "Sheet2",
// })
//
func (f *File) SetDefinedName(definedName *DefinedName) error {
wb := f.workbookReader()
d := xlsxDefinedName{
Name: definedName.Name,
Comment: definedName.Comment,
Data: definedName.RefersTo,
}
if definedName.Scope != "" {
if sheetID := f.GetSheetIndex(definedName.Scope); sheetID != 0 {
sheetID--
d.LocalSheetID = &sheetID
}
}
if wb.DefinedNames != nil {
for _, dn := range wb.DefinedNames.DefinedName {
var scope string
if dn.LocalSheetID != nil {
scope = f.GetSheetName(*dn.LocalSheetID + 1)
}
if scope == definedName.Scope && dn.Name == definedName.Name {
return errors.New("the same name already exists on scope")
}
}
wb.DefinedNames.DefinedName = append(wb.DefinedNames.DefinedName, d)
return nil
}
wb.DefinedNames = &xlsxDefinedNames{
DefinedName: []xlsxDefinedName{d},
}
return nil
}
// GetDefinedName provides a function to get the defined names of the workbook
// or worksheet.
func (f *File) GetDefinedName() []DefinedName {
var definedNames []DefinedName
wb := f.workbookReader()
if wb.DefinedNames != nil {
for _, dn := range wb.DefinedNames.DefinedName {
definedName := DefinedName{
Name: dn.Name,
Comment: dn.Comment,
RefersTo: dn.Data,
Scope: "Workbook",
}
if dn.LocalSheetID != nil {
definedName.Scope = f.GetSheetName(*dn.LocalSheetID + 1)
}
definedNames = append(definedNames, definedName)
}
}
return definedNames
}
// workSheetRelsReader provides a function to get the pointer to the structure
// after deserialization of xl/worksheets/_rels/sheet%d.xml.rels.
func (f *File) workSheetRelsReader(path string) *xlsxWorkbookRels {

View File

@ -108,6 +108,29 @@ func TestPageLayoutOption(t *testing.T) {
}
}
func TestSearchSheet(t *testing.T) {
f, err := excelize.OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
if !assert.NoError(t, err) {
t.FailNow()
}
// Test search in a not exists worksheet.
_, err = f.SearchSheet("Sheet4", "")
assert.EqualError(t, err, "sheet Sheet4 is not exist")
var expected []string
// Test search a not exists value.
result, err := f.SearchSheet("Sheet1", "X")
assert.NoError(t, err)
assert.EqualValues(t, expected, result)
result, err = f.SearchSheet("Sheet1", "A")
assert.NoError(t, err)
assert.EqualValues(t, []string{"A1"}, result)
// Test search the coordinates where the numerical value in the range of
// "0-9" of Sheet1 is described by regular expression:
result, err = f.SearchSheet("Sheet1", "[0-9]", true)
assert.NoError(t, err)
assert.EqualValues(t, expected, result)
}
func TestSetPageLayout(t *testing.T) {
f := excelize.NewFile()
// Test set page layout on not exists worksheet.
@ -142,3 +165,25 @@ func TestSetHeaderFooter(t *testing.T) {
}))
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetHeaderFooter.xlsx")))
}
func TestDefinedName(t *testing.T) {
f := excelize.NewFile()
assert.NoError(t, f.SetDefinedName(&excelize.DefinedName{
Name: "Amount",
RefersTo: "Sheet1!$A$2:$D$5",
Comment: "defined name comment",
Scope: "Sheet1",
}))
assert.NoError(t, f.SetDefinedName(&excelize.DefinedName{
Name: "Amount",
RefersTo: "Sheet1!$A$2:$D$5",
Comment: "defined name comment",
}))
assert.EqualError(t, f.SetDefinedName(&excelize.DefinedName{
Name: "Amount",
RefersTo: "Sheet1!$A$2:$D$5",
Comment: "defined name comment",
}), "the same name already exists on scope")
assert.Exactly(t, "Sheet1!$A$2:$D$5", f.GetDefinedName()[1].RefersTo)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDefinedName.xlsx")))
}

View File

@ -288,3 +288,12 @@ type xlsxCustomWorkbookView struct {
XWindow *int `xml:"xWindow,attr"`
YWindow *int `xml:"yWindow,attr"`
}
// DefinedName directly maps the name for a cell or cell range on a
// worksheet.
type DefinedName struct {
Name string
Comment string
RefersTo string
Scope string
}