make SetCellStyle quicker by skipping conversions in checkCellInArea, and skipping area checks when we are sure the cell can't be before or past the current row/col
Signed-off-by: Matthieu Bresson
This commit is contained in:
parent
50cdaed5a3
commit
317ef65381
25
cell.go
25
cell.go
|
@ -455,27 +455,16 @@ func (f *File) SetCellDefault(sheet, axis, value string) {
|
|||
// checkCellInArea provides function to determine if a given coordinate is
|
||||
// within an area.
|
||||
func checkCellInArea(cell, area string) bool {
|
||||
result := false
|
||||
cell = strings.ToUpper(cell)
|
||||
col := string(strings.Map(letterOnlyMapF, cell))
|
||||
row, _ := strconv.Atoi(strings.Map(intOnlyMapF, cell))
|
||||
xAxis := row - 1
|
||||
yAxis := TitleToNumber(col)
|
||||
area = strings.ToUpper(area)
|
||||
|
||||
ref := strings.Split(area, ":")
|
||||
hCol := string(strings.Map(letterOnlyMapF, ref[0]))
|
||||
hRow, _ := strconv.Atoi(strings.Map(intOnlyMapF, ref[0]))
|
||||
hyAxis := hRow - 1
|
||||
hxAxis := TitleToNumber(hCol)
|
||||
from := ref[0]
|
||||
to := ref[1]
|
||||
|
||||
vCol := string(strings.Map(letterOnlyMapF, ref[1]))
|
||||
vRow, _ := strconv.Atoi(strings.Map(intOnlyMapF, ref[1]))
|
||||
vyAxis := vRow - 1
|
||||
vxAxis := TitleToNumber(vCol)
|
||||
col, row := getCellColRow(cell)
|
||||
fromCol, fromRow := getCellColRow(from)
|
||||
toCol, toRow := getCellColRow(to)
|
||||
|
||||
if hxAxis <= yAxis && yAxis <= vxAxis && hyAxis <= xAxis && xAxis <= vyAxis {
|
||||
result = true
|
||||
}
|
||||
|
||||
return result
|
||||
return axisLowerOrEqualThan(fromCol, col) && axisLowerOrEqualThan(col, toCol) && axisLowerOrEqualThan(fromRow, row) && axisLowerOrEqualThan(row, toRow)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package excelize
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCheckCellInArea(t *testing.T) {
|
||||
expectedTrueCellInAreaList := [][2]string{
|
||||
[2]string{"c2", "A1:AAZ32"},
|
||||
[2]string{"AA0", "Z0:AB1"},
|
||||
[2]string{"B9", "A1:B9"},
|
||||
[2]string{"C2", "C2:C2"},
|
||||
}
|
||||
|
||||
for _, expectedTrueCellInArea := range expectedTrueCellInAreaList {
|
||||
cell := expectedTrueCellInArea[0]
|
||||
area := expectedTrueCellInArea[1]
|
||||
|
||||
cellInArea := checkCellInArea(cell, area)
|
||||
|
||||
if !cellInArea {
|
||||
t.Fatalf("Expected cell %v to be in area %v, got false\n", cell, area)
|
||||
}
|
||||
}
|
||||
|
||||
expectedFalseCellInAreaList := [][2]string{
|
||||
[2]string{"c2", "A4:AAZ32"},
|
||||
[2]string{"C4", "D6:A1"}, // weird case, but you never know
|
||||
[2]string{"AEF42", "BZ40:AEF41"},
|
||||
}
|
||||
|
||||
for _, expectedFalseCellInArea := range expectedFalseCellInAreaList {
|
||||
cell := expectedFalseCellInArea[0]
|
||||
area := expectedFalseCellInArea[1]
|
||||
|
||||
cellInArea := checkCellInArea(cell, area)
|
||||
|
||||
if cellInArea {
|
||||
t.Fatalf("Expected cell %v not to be inside of area %v, but got true\n", cell, area)
|
||||
}
|
||||
}
|
||||
}
|
41
lib.go
41
lib.go
|
@ -7,6 +7,7 @@ import (
|
|||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// ReadZipReader can be used to read an XLSX in memory without touching the
|
||||
|
@ -132,3 +133,43 @@ func defaultTrue(b *bool) bool {
|
|||
}
|
||||
return *b
|
||||
}
|
||||
|
||||
// axisLowerOrEqualThan returns true if axis1 <= axis2
|
||||
// axis1/axis2 can be either a column or a row axis, e.g. "A", "AAE", "42", "1", etc.
|
||||
//
|
||||
// For instance, the following comparisons are all true:
|
||||
//
|
||||
// "A" <= "B"
|
||||
// "A" <= "AA"
|
||||
// "B" <= "AA"
|
||||
// "BC" <= "ABCD" (in a XLSX sheet, the BC col comes before the ABCD col)
|
||||
// "1" <= "2"
|
||||
// "2" <= "11" (in a XLSX sheet, the row 2 comes before the row 11)
|
||||
// and so on
|
||||
func axisLowerOrEqualThan(axis1, axis2 string) bool {
|
||||
if len(axis1) < len(axis2) {
|
||||
return true
|
||||
} else if len(axis1) > len(axis2) {
|
||||
return false
|
||||
} else {
|
||||
return axis1 <= axis2
|
||||
}
|
||||
}
|
||||
|
||||
// getCellColRow returns the two parts of a cell identifier (its col and row) as strings
|
||||
//
|
||||
// For instance:
|
||||
//
|
||||
// "C220" => "C", "220"
|
||||
// "aaef42" => "aaef", "42"
|
||||
// "" => "", ""
|
||||
func getCellColRow(cell string) (col, row string) {
|
||||
for index, rune := range cell {
|
||||
if unicode.IsDigit(rune) {
|
||||
return cell[:index], cell[index:]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return cell, ""
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package excelize
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestAxisLowerOrEqualThan(t *testing.T) {
|
||||
trueExpectedInputList := [][2]string{
|
||||
[2]string{"A", "B"},
|
||||
[2]string{"A", "AA"},
|
||||
[2]string{"B", "AA"},
|
||||
[2]string{"BC", "ABCD"},
|
||||
[2]string{"1", "2"},
|
||||
[2]string{"2", "11"},
|
||||
}
|
||||
|
||||
for _, trueExpectedInput := range trueExpectedInputList {
|
||||
isLowerOrEqual := axisLowerOrEqualThan(trueExpectedInput[0], trueExpectedInput[1])
|
||||
if !isLowerOrEqual {
|
||||
t.Fatalf("Expected %v <= %v = true, got false\n", trueExpectedInput[0], trueExpectedInput[1])
|
||||
}
|
||||
}
|
||||
|
||||
falseExpectedInputList := [][2]string{
|
||||
[2]string{"B", "A"},
|
||||
[2]string{"AA", "A"},
|
||||
[2]string{"AA", "B"},
|
||||
[2]string{"ABCD", "AB"},
|
||||
[2]string{"2", "1"},
|
||||
[2]string{"11", "2"},
|
||||
}
|
||||
|
||||
for _, falseExpectedInput := range falseExpectedInputList {
|
||||
isLowerOrEqual := axisLowerOrEqualThan(falseExpectedInput[0], falseExpectedInput[1])
|
||||
if isLowerOrEqual {
|
||||
t.Fatalf("Expected %v <= %v = false, got true\n", falseExpectedInput[0], falseExpectedInput[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCellColRow(t *testing.T) {
|
||||
cellExpectedColRowList := map[string][2]string{
|
||||
"C220": [2]string{"C", "220"},
|
||||
"aaef42": [2]string{"aaef", "42"},
|
||||
"bonjour": [2]string{"bonjour", ""},
|
||||
"59": [2]string{"", "59"},
|
||||
"": [2]string{"", ""},
|
||||
}
|
||||
|
||||
for cell, expectedColRow := range cellExpectedColRowList {
|
||||
col, row := getCellColRow(cell)
|
||||
|
||||
if col != expectedColRow[0] {
|
||||
t.Fatalf("Expected cell %v to return col %v, got col %v\n", cell, expectedColRow[0], col)
|
||||
}
|
||||
|
||||
if row != expectedColRow[1] {
|
||||
t.Fatalf("Expected cell %v to return row %v, got row %v\n", cell, expectedColRow[1], row)
|
||||
}
|
||||
}
|
||||
}
|
12
styles.go
12
styles.go
|
@ -2327,7 +2327,19 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) {
|
|||
completeCol(xlsx, vyAxis+1, vxAxis+1)
|
||||
|
||||
for r, row := range xlsx.SheetData.Row {
|
||||
if r < hyAxis {
|
||||
continue
|
||||
} else if r > vyAxis {
|
||||
break
|
||||
}
|
||||
|
||||
for k, c := range row.C {
|
||||
if k < hxAxis {
|
||||
continue
|
||||
} else if k > vxAxis {
|
||||
break
|
||||
}
|
||||
|
||||
if checkCellInArea(c.R, hcell+":"+vcell) {
|
||||
xlsx.SheetData.Row[r].C[k].S = styleID
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue