This closes #1770, fix incorrect multiple conditional formats rules priorities
- Rename variable name hCell to topLeftCell, and rename vCell to bottomRightCell - Update the unit tests
This commit is contained in:
parent
bb8e5dacd2
commit
f4e395137d
20
merge.go
20
merge.go
|
@ -49,16 +49,16 @@ func (mc *xlsxMergeCell) Rect() ([]int, error) {
|
|||
// | |
|
||||
// |A8(x3,y4) C8(x4,y4)|
|
||||
// +------------------------+
|
||||
func (f *File) MergeCell(sheet, hCell, vCell string) error {
|
||||
rect, err := rangeRefToCoordinates(hCell + ":" + vCell)
|
||||
func (f *File) MergeCell(sheet, topLeftCell, bottomRightCell string) error {
|
||||
rect, err := rangeRefToCoordinates(topLeftCell + ":" + bottomRightCell)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Correct the range reference, such correct C1:B3 to B1:C3.
|
||||
_ = sortCoordinates(rect)
|
||||
|
||||
hCell, _ = CoordinatesToCellName(rect[0], rect[1])
|
||||
vCell, _ = CoordinatesToCellName(rect[2], rect[3])
|
||||
topLeftCell, _ = CoordinatesToCellName(rect[0], rect[1])
|
||||
bottomRightCell, _ = CoordinatesToCellName(rect[2], rect[3])
|
||||
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
|
@ -66,7 +66,7 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error {
|
|||
}
|
||||
ws.mu.Lock()
|
||||
defer ws.mu.Unlock()
|
||||
ref := hCell + ":" + vCell
|
||||
ref := topLeftCell + ":" + bottomRightCell
|
||||
if ws.MergeCells != nil {
|
||||
ws.MergeCells.Cells = append(ws.MergeCells.Cells, &xlsxMergeCell{Ref: ref, rect: rect})
|
||||
} else {
|
||||
|
@ -82,14 +82,14 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error {
|
|||
// err := f.UnmergeCell("Sheet1", "D3", "E9")
|
||||
//
|
||||
// Attention: overlapped range will also be unmerged.
|
||||
func (f *File) UnmergeCell(sheet, hCell, vCell string) error {
|
||||
func (f *File) UnmergeCell(sheet, topLeftCell, bottomRightCell string) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.mu.Lock()
|
||||
defer ws.mu.Unlock()
|
||||
rect1, err := rangeRefToCoordinates(hCell + ":" + vCell)
|
||||
rect1, err := rangeRefToCoordinates(topLeftCell + ":" + bottomRightCell)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -265,9 +265,9 @@ func mergeCell(cell1, cell2 *xlsxMergeCell) *xlsxMergeCell {
|
|||
if rect1[3] < rect2[3] {
|
||||
rect1[3], rect2[3] = rect2[3], rect1[3]
|
||||
}
|
||||
hCell, _ := CoordinatesToCellName(rect1[0], rect1[1])
|
||||
vCell, _ := CoordinatesToCellName(rect1[2], rect1[3])
|
||||
return &xlsxMergeCell{rect: rect1, Ref: hCell + ":" + vCell}
|
||||
topLeftCell, _ := CoordinatesToCellName(rect1[0], rect1[1])
|
||||
bottomRightCell, _ := CoordinatesToCellName(rect1[2], rect1[3])
|
||||
return &xlsxMergeCell{rect: rect1, Ref: topLeftCell + ":" + bottomRightCell}
|
||||
}
|
||||
|
||||
// MergeCell define a merged cell data.
|
||||
|
|
|
@ -274,8 +274,8 @@ func (f *File) addPivotCache(opts *PivotTableOptions) error {
|
|||
}
|
||||
// data range has been checked
|
||||
order, _ := f.getTableFieldsOrder(opts)
|
||||
hCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
|
||||
vCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
|
||||
topLeftCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
|
||||
bottomRightCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
|
||||
pc := xlsxPivotCacheDefinition{
|
||||
SaveData: false,
|
||||
RefreshOnLoad: true,
|
||||
|
@ -285,7 +285,7 @@ func (f *File) addPivotCache(opts *PivotTableOptions) error {
|
|||
CacheSource: &xlsxCacheSource{
|
||||
Type: "worksheet",
|
||||
WorksheetSource: &xlsxWorksheetSource{
|
||||
Ref: hCell + ":" + vCell,
|
||||
Ref: topLeftCell + ":" + bottomRightCell,
|
||||
Sheet: dataSheet,
|
||||
},
|
||||
},
|
||||
|
@ -315,8 +315,8 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions)
|
|||
return newPivotTableRangeError(err.Error())
|
||||
}
|
||||
|
||||
hCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
|
||||
vCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
|
||||
topLeftCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
|
||||
bottomRightCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
|
||||
|
||||
pivotTableStyle := func() string {
|
||||
if opts.PivotTableStyleName == "" {
|
||||
|
@ -340,7 +340,7 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions)
|
|||
ShowError: &opts.ShowError,
|
||||
DataCaption: "Values",
|
||||
Location: &xlsxLocation{
|
||||
Ref: hCell + ":" + vCell,
|
||||
Ref: topLeftCell + ":" + bottomRightCell,
|
||||
FirstDataCol: 1,
|
||||
FirstDataRow: 1,
|
||||
FirstHeaderRow: 1,
|
||||
|
|
|
@ -484,16 +484,16 @@ func (sw *StreamWriter) SetPanes(panes *Panes) error {
|
|||
// MergeCell provides a function to merge cells by a given range reference for
|
||||
// the StreamWriter. Don't create a merged cell that overlaps with another
|
||||
// existing merged cell.
|
||||
func (sw *StreamWriter) MergeCell(hCell, vCell string) error {
|
||||
_, err := cellRefsToCoordinates(hCell, vCell)
|
||||
func (sw *StreamWriter) MergeCell(topLeftCell, bottomRightCell string) error {
|
||||
_, err := cellRefsToCoordinates(topLeftCell, bottomRightCell)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sw.mergeCellsCount++
|
||||
_, _ = sw.mergeCells.WriteString(`<mergeCell ref="`)
|
||||
_, _ = sw.mergeCells.WriteString(hCell)
|
||||
_, _ = sw.mergeCells.WriteString(topLeftCell)
|
||||
_, _ = sw.mergeCells.WriteString(`:`)
|
||||
_, _ = sw.mergeCells.WriteString(vCell)
|
||||
_, _ = sw.mergeCells.WriteString(bottomRightCell)
|
||||
_, _ = sw.mergeCells.WriteString(`"/>`)
|
||||
return nil
|
||||
}
|
||||
|
|
17
styles.go
17
styles.go
|
@ -2262,13 +2262,13 @@ func (f *File) GetCellStyle(sheet, cell string) (int, error) {
|
|||
// fmt.Println(err)
|
||||
// }
|
||||
// err = f.SetCellStyle("Sheet1", "H9", "H9", style)
|
||||
func (f *File) SetCellStyle(sheet, hCell, vCell string, styleID int) error {
|
||||
hCol, hRow, err := CellNameToCoordinates(hCell)
|
||||
func (f *File) SetCellStyle(sheet, topLeftCell, bottomRightCell string, styleID int) error {
|
||||
hCol, hRow, err := CellNameToCoordinates(topLeftCell)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vCol, vRow, err := CellNameToCoordinates(vCell)
|
||||
vCol, vRow, err := CellNameToCoordinates(bottomRightCell)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2759,19 +2759,20 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
|
|||
"iconSet",
|
||||
}
|
||||
)
|
||||
for p, v := range opts {
|
||||
for i, opt := range opts {
|
||||
var vt, ct string
|
||||
var ok bool
|
||||
// "type" is a required parameter, check for valid validation types.
|
||||
vt, ok = validType[v.Type]
|
||||
vt, ok = validType[opt.Type]
|
||||
if ok {
|
||||
// Check for valid criteria types.
|
||||
ct, ok = criteriaType[v.Criteria]
|
||||
ct, ok = criteriaType[opt.Criteria]
|
||||
if ok || inStrSlice(noCriteriaTypes, vt, true) != -1 {
|
||||
drawFunc, ok := drawContFmtFunc[vt]
|
||||
if ok {
|
||||
rule, x14rule := drawFunc(p, ct, strings.Split(rangeRef, ":")[0],
|
||||
fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), rules+p), &v)
|
||||
priority := rules + i
|
||||
rule, x14rule := drawFunc(priority, ct, strings.Split(rangeRef, ":")[0],
|
||||
fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), priority), &opt)
|
||||
if rule == nil {
|
||||
return ErrParameterInvalid
|
||||
}
|
||||
|
|
|
@ -193,6 +193,48 @@ func TestSetConditionalFormat(t *testing.T) {
|
|||
assert.Equal(t, ErrParameterInvalid, f.SetConditionalFormat("Sheet1", "A1:A2", []ConditionalFormatOptions{{Type: "icon_set", IconStyle: "unknown"}}))
|
||||
// Test unsupported conditional formatting rule types
|
||||
assert.Equal(t, ErrParameterInvalid, f.SetConditionalFormat("Sheet1", "A1", []ConditionalFormatOptions{{Type: "unsupported"}}))
|
||||
|
||||
t.Run("multi_conditional_formatting_rules_priority", func(t *testing.T) {
|
||||
f := NewFile()
|
||||
var condFmts []ConditionalFormatOptions
|
||||
for _, color := range []string{
|
||||
"#264B96", // Blue
|
||||
"#F9A73E", // Yellow
|
||||
"#006F3C", // Green
|
||||
} {
|
||||
condFmts = append(condFmts, ConditionalFormatOptions{
|
||||
Type: "data_bar",
|
||||
Criteria: "=",
|
||||
MinType: "num",
|
||||
MaxType: "num",
|
||||
MinValue: "0",
|
||||
MaxValue: "5",
|
||||
BarColor: color,
|
||||
BarSolid: true,
|
||||
})
|
||||
}
|
||||
assert.NoError(t, f.SetConditionalFormat("Sheet1", "A1:A5", condFmts))
|
||||
assert.NoError(t, f.SetConditionalFormat("Sheet1", "B1:B5", condFmts))
|
||||
for r := 1; r <= 20; r++ {
|
||||
cell, err := CoordinatesToCellName(1, r)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", cell, r))
|
||||
cell, err = CoordinatesToCellName(2, r)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", cell, r))
|
||||
}
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
var priorities []int
|
||||
expected := []int{1, 2, 3, 4, 5, 6}
|
||||
for _, condFmt := range ws.(*xlsxWorksheet).ConditionalFormatting {
|
||||
for _, rule := range condFmt.CfRule {
|
||||
priorities = append(priorities, rule.Priority)
|
||||
}
|
||||
}
|
||||
assert.Equal(t, expected, priorities)
|
||||
assert.NoError(t, f.Close())
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetConditionalFormats(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue