New feature: the function `SearchSheet` now support regular expression, relate pull request #316

This commit is contained in:
xuri 2018-12-26 14:48:14 +08:00
parent 7b7ca99f5d
commit 9a6f66a996
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
3 changed files with 32 additions and 73 deletions

View File

@ -243,6 +243,8 @@ func (f *File) adjustRowDimensions(xlsx *xlsxWorksheet, rowIndex, offset int) {
} }
} }
// ajustSingleRowDimensions provides a function to ajust single row
// dimensions.
func (f *File) ajustSingleRowDimensions(r *xlsxRow, offset int) { func (f *File) ajustSingleRowDimensions(r *xlsxRow, offset int) {
r.R += offset r.R += offset
for i, col := range r.C { for i, col := range r.C {

View File

@ -1053,6 +1053,7 @@ func TestDuplicateRow(t *testing.T) {
xlsx.SetCellStr(sheet, b1, bnValue) xlsx.SetCellStr(sheet, b1, bnValue)
t.Run("FromSingleRow", func(t *testing.T) { t.Run("FromSingleRow", func(t *testing.T) {
xlsx.DuplicateRow(sheet, -1)
xlsx.DuplicateRow(sheet, 1) xlsx.DuplicateRow(sheet, 1)
xlsx.DuplicateRow(sheet, 2) xlsx.DuplicateRow(sheet, 2)
@ -1333,19 +1334,9 @@ func TestSearchSheet(t *testing.T) {
// Test search a not exists value. // Test search a not exists value.
t.Log(xlsx.SearchSheet("Sheet1", "X")) t.Log(xlsx.SearchSheet("Sheet1", "X"))
t.Log(xlsx.SearchSheet("Sheet1", "A")) t.Log(xlsx.SearchSheet("Sheet1", "A"))
} // Test search the coordinates where the numerical value in the range of
// "0-9" of Sheet1 is described by regular expression:
func TestRegSearchSheet(t *testing.T) { t.Log(xlsx.SearchSheet("Sheet1", "[0-9]", true))
xlsx, err := OpenFile("./test/Book1.xlsx")
if err != nil {
t.Error(err)
return
}
t.Log(xlsx.SearchSheet("Sheet1", "[0-9]"))
// Test search in a not exists worksheet.
t.Log(xlsx.SearchSheet("Sheet4", ""))
// Test search a not exists value.
t.Log(xlsx.SearchSheet("Sheet1", ""))
} }
func TestProtectSheet(t *testing.T) { func TestProtectSheet(t *testing.T) {

View File

@ -658,66 +658,26 @@ func (f *File) GetSheetVisible(name string) bool {
return visible return visible
} }
// SearchSheet provides a function to get coordinates by given worksheet name // SearchSheet provides a function to get coordinates by given worksheet name,
// and cell value. This function only supports exact match of strings and // cell value, and regular expression. The function doesn't support searching
// numbers, doesn't support the calculated result, formatted numbers and // on the calculated result, formatted numbers and conditional lookup
// conditional lookup currently. If it is a merged cell, it will return the // currently. If it is a merged cell, it will return the coordinates of the
// coordinates of the upper left corner of the merged area. For example, // upper left corner of the merged area.
// search the coordinates of the value of "100" on Sheet1: //
// An example of search the coordinates of the value of "100" on Sheet1:
// //
// xlsx.SearchSheet("Sheet1", "100") // xlsx.SearchSheet("Sheet1", "100")
// //
func (f *File) SearchSheet(sheet, value string) []string { // An example of search the coordinates where the numerical value in the range
xlsx := f.workSheetReader(sheet) // of "0-9" of Sheet1 is described:
result := []string{} //
name, ok := f.sheetMap[trimSheetName(sheet)] // xlsx.SearchSheet("Sheet1", "[0-9]", true)
if !ok { //
return result func (f *File) SearchSheet(sheet, value string, reg ...bool) []string {
} var regSearch bool
if xlsx != nil { for _, r := range reg {
output, _ := xml.Marshal(f.Sheet[name]) regSearch = r
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output)) }
}
xml.NewDecoder(bytes.NewReader(f.readXML(name)))
d := f.sharedStringsReader()
var inElement string
var r xlsxRow
decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
for {
token, _ := decoder.Token()
if token == nil {
break
}
switch startElement := token.(type) {
case xml.StartElement:
inElement = startElement.Name.Local
if inElement == "row" {
r = xlsxRow{}
_ = decoder.DecodeElement(&r, &startElement)
for _, colCell := range r.C {
val, _ := colCell.getValueFrom(f, d)
if val != value {
continue
}
result = append(result, fmt.Sprintf("%s%d", strings.Map(letterOnlyMapF, colCell.R), r.R))
}
}
default:
}
}
return result
}
// RegSearchSheet provides the ability to retrieve coordinates
// with the given worksheet name and regular expression
// For a merged cell, get the coordinates
// of the upper left corner of the merge area.
// :example)
// Search the coordinates where the numerical value in the range of "0-9" of Sheet 1 is described:
//
// xlsx.RegSearchSheet("Sheet1", "[0-9]")
//
func (f *File) RegSearchSheet(sheet, value string) []string {
xlsx := f.workSheetReader(sheet) xlsx := f.workSheetReader(sheet)
result := []string{} result := []string{}
name, ok := f.sheetMap[trimSheetName(sheet)] name, ok := f.sheetMap[trimSheetName(sheet)]
@ -746,10 +706,16 @@ func (f *File) RegSearchSheet(sheet, value string) []string {
_ = decoder.DecodeElement(&r, &startElement) _ = decoder.DecodeElement(&r, &startElement)
for _, colCell := range r.C { for _, colCell := range r.C {
val, _ := colCell.getValueFrom(f, d) val, _ := colCell.getValueFrom(f, d)
if regSearch {
regex := regexp.MustCompile(value) regex := regexp.MustCompile(value)
if !regex.MatchString(val) { if !regex.MatchString(val) {
continue continue
} }
} else {
if val != value {
continue
}
}
result = append(result, fmt.Sprintf("%s%d", strings.Map(letterOnlyMapF, colCell.R), r.R)) result = append(result, fmt.Sprintf("%s%d", strings.Map(letterOnlyMapF, colCell.R), r.R))
} }
} }