已验证 提交 f4e39513 编写于 作者: xurime's avatar xurime

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
上级 bb8e5dac
...@@ -49,16 +49,16 @@ func (mc *xlsxMergeCell) Rect() ([]int, error) { ...@@ -49,16 +49,16 @@ func (mc *xlsxMergeCell) Rect() ([]int, error) {
// | | // | |
// |A8(x3,y4) C8(x4,y4)| // |A8(x3,y4) C8(x4,y4)|
// +------------------------+ // +------------------------+
func (f *File) MergeCell(sheet, hCell, vCell string) error { func (f *File) MergeCell(sheet, topLeftCell, bottomRightCell string) error {
rect, err := rangeRefToCoordinates(hCell + ":" + vCell) rect, err := rangeRefToCoordinates(topLeftCell + ":" + bottomRightCell)
if err != nil { if err != nil {
return err return err
} }
// Correct the range reference, such correct C1:B3 to B1:C3. // Correct the range reference, such correct C1:B3 to B1:C3.
_ = sortCoordinates(rect) _ = sortCoordinates(rect)
hCell, _ = CoordinatesToCellName(rect[0], rect[1]) topLeftCell, _ = CoordinatesToCellName(rect[0], rect[1])
vCell, _ = CoordinatesToCellName(rect[2], rect[3]) bottomRightCell, _ = CoordinatesToCellName(rect[2], rect[3])
ws, err := f.workSheetReader(sheet) ws, err := f.workSheetReader(sheet)
if err != nil { if err != nil {
...@@ -66,7 +66,7 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error { ...@@ -66,7 +66,7 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error {
} }
ws.mu.Lock() ws.mu.Lock()
defer ws.mu.Unlock() defer ws.mu.Unlock()
ref := hCell + ":" + vCell ref := topLeftCell + ":" + bottomRightCell
if ws.MergeCells != nil { if ws.MergeCells != nil {
ws.MergeCells.Cells = append(ws.MergeCells.Cells, &xlsxMergeCell{Ref: ref, rect: rect}) ws.MergeCells.Cells = append(ws.MergeCells.Cells, &xlsxMergeCell{Ref: ref, rect: rect})
} else { } else {
...@@ -82,14 +82,14 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error { ...@@ -82,14 +82,14 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error {
// err := f.UnmergeCell("Sheet1", "D3", "E9") // err := f.UnmergeCell("Sheet1", "D3", "E9")
// //
// Attention: overlapped range will also be unmerged. // 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) ws, err := f.workSheetReader(sheet)
if err != nil { if err != nil {
return err return err
} }
ws.mu.Lock() ws.mu.Lock()
defer ws.mu.Unlock() defer ws.mu.Unlock()
rect1, err := rangeRefToCoordinates(hCell + ":" + vCell) rect1, err := rangeRefToCoordinates(topLeftCell + ":" + bottomRightCell)
if err != nil { if err != nil {
return err return err
} }
...@@ -265,9 +265,9 @@ func mergeCell(cell1, cell2 *xlsxMergeCell) *xlsxMergeCell { ...@@ -265,9 +265,9 @@ func mergeCell(cell1, cell2 *xlsxMergeCell) *xlsxMergeCell {
if rect1[3] < rect2[3] { if rect1[3] < rect2[3] {
rect1[3], rect2[3] = rect2[3], rect1[3] rect1[3], rect2[3] = rect2[3], rect1[3]
} }
hCell, _ := CoordinatesToCellName(rect1[0], rect1[1]) topLeftCell, _ := CoordinatesToCellName(rect1[0], rect1[1])
vCell, _ := CoordinatesToCellName(rect1[2], rect1[3]) bottomRightCell, _ := CoordinatesToCellName(rect1[2], rect1[3])
return &xlsxMergeCell{rect: rect1, Ref: hCell + ":" + vCell} return &xlsxMergeCell{rect: rect1, Ref: topLeftCell + ":" + bottomRightCell}
} }
// MergeCell define a merged cell data. // MergeCell define a merged cell data.
......
...@@ -274,8 +274,8 @@ func (f *File) addPivotCache(opts *PivotTableOptions) error { ...@@ -274,8 +274,8 @@ func (f *File) addPivotCache(opts *PivotTableOptions) error {
} }
// data range has been checked // data range has been checked
order, _ := f.getTableFieldsOrder(opts) order, _ := f.getTableFieldsOrder(opts)
hCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1]) topLeftCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
vCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3]) bottomRightCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
pc := xlsxPivotCacheDefinition{ pc := xlsxPivotCacheDefinition{
SaveData: false, SaveData: false,
RefreshOnLoad: true, RefreshOnLoad: true,
...@@ -285,7 +285,7 @@ func (f *File) addPivotCache(opts *PivotTableOptions) error { ...@@ -285,7 +285,7 @@ func (f *File) addPivotCache(opts *PivotTableOptions) error {
CacheSource: &xlsxCacheSource{ CacheSource: &xlsxCacheSource{
Type: "worksheet", Type: "worksheet",
WorksheetSource: &xlsxWorksheetSource{ WorksheetSource: &xlsxWorksheetSource{
Ref: hCell + ":" + vCell, Ref: topLeftCell + ":" + bottomRightCell,
Sheet: dataSheet, Sheet: dataSheet,
}, },
}, },
...@@ -315,8 +315,8 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions) ...@@ -315,8 +315,8 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions)
return newPivotTableRangeError(err.Error()) return newPivotTableRangeError(err.Error())
} }
hCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1]) topLeftCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
vCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3]) bottomRightCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
pivotTableStyle := func() string { pivotTableStyle := func() string {
if opts.PivotTableStyleName == "" { if opts.PivotTableStyleName == "" {
...@@ -340,7 +340,7 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions) ...@@ -340,7 +340,7 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions)
ShowError: &opts.ShowError, ShowError: &opts.ShowError,
DataCaption: "Values", DataCaption: "Values",
Location: &xlsxLocation{ Location: &xlsxLocation{
Ref: hCell + ":" + vCell, Ref: topLeftCell + ":" + bottomRightCell,
FirstDataCol: 1, FirstDataCol: 1,
FirstDataRow: 1, FirstDataRow: 1,
FirstHeaderRow: 1, FirstHeaderRow: 1,
......
...@@ -484,16 +484,16 @@ func (sw *StreamWriter) SetPanes(panes *Panes) error { ...@@ -484,16 +484,16 @@ func (sw *StreamWriter) SetPanes(panes *Panes) error {
// MergeCell provides a function to merge cells by a given range reference for // 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 // the StreamWriter. Don't create a merged cell that overlaps with another
// existing merged cell. // existing merged cell.
func (sw *StreamWriter) MergeCell(hCell, vCell string) error { func (sw *StreamWriter) MergeCell(topLeftCell, bottomRightCell string) error {
_, err := cellRefsToCoordinates(hCell, vCell) _, err := cellRefsToCoordinates(topLeftCell, bottomRightCell)
if err != nil { if err != nil {
return err return err
} }
sw.mergeCellsCount++ sw.mergeCellsCount++
_, _ = sw.mergeCells.WriteString(`<mergeCell ref="`) _, _ = sw.mergeCells.WriteString(`<mergeCell ref="`)
_, _ = sw.mergeCells.WriteString(hCell) _, _ = sw.mergeCells.WriteString(topLeftCell)
_, _ = sw.mergeCells.WriteString(`:`) _, _ = sw.mergeCells.WriteString(`:`)
_, _ = sw.mergeCells.WriteString(vCell) _, _ = sw.mergeCells.WriteString(bottomRightCell)
_, _ = sw.mergeCells.WriteString(`"/>`) _, _ = sw.mergeCells.WriteString(`"/>`)
return nil return nil
} }
......
...@@ -2262,13 +2262,13 @@ func (f *File) GetCellStyle(sheet, cell string) (int, error) { ...@@ -2262,13 +2262,13 @@ func (f *File) GetCellStyle(sheet, cell string) (int, error) {
// fmt.Println(err) // fmt.Println(err)
// } // }
// err = f.SetCellStyle("Sheet1", "H9", "H9", style) // err = f.SetCellStyle("Sheet1", "H9", "H9", style)
func (f *File) SetCellStyle(sheet, hCell, vCell string, styleID int) error { func (f *File) SetCellStyle(sheet, topLeftCell, bottomRightCell string, styleID int) error {
hCol, hRow, err := CellNameToCoordinates(hCell) hCol, hRow, err := CellNameToCoordinates(topLeftCell)
if err != nil { if err != nil {
return err return err
} }
vCol, vRow, err := CellNameToCoordinates(vCell) vCol, vRow, err := CellNameToCoordinates(bottomRightCell)
if err != nil { if err != nil {
return err return err
} }
...@@ -2759,19 +2759,20 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo ...@@ -2759,19 +2759,20 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
"iconSet", "iconSet",
} }
) )
for p, v := range opts { for i, opt := range opts {
var vt, ct string var vt, ct string
var ok bool var ok bool
// "type" is a required parameter, check for valid validation types. // "type" is a required parameter, check for valid validation types.
vt, ok = validType[v.Type] vt, ok = validType[opt.Type]
if ok { if ok {
// Check for valid criteria types. // Check for valid criteria types.
ct, ok = criteriaType[v.Criteria] ct, ok = criteriaType[opt.Criteria]
if ok || inStrSlice(noCriteriaTypes, vt, true) != -1 { if ok || inStrSlice(noCriteriaTypes, vt, true) != -1 {
drawFunc, ok := drawContFmtFunc[vt] drawFunc, ok := drawContFmtFunc[vt]
if ok { if ok {
rule, x14rule := drawFunc(p, ct, strings.Split(rangeRef, ":")[0], priority := rules + i
fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), rules+p), &v) rule, x14rule := drawFunc(priority, ct, strings.Split(rangeRef, ":")[0],
fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), priority), &opt)
if rule == nil { if rule == nil {
return ErrParameterInvalid return ErrParameterInvalid
} }
......
...@@ -193,6 +193,48 @@ func TestSetConditionalFormat(t *testing.T) { ...@@ -193,6 +193,48 @@ func TestSetConditionalFormat(t *testing.T) {
assert.Equal(t, ErrParameterInvalid, f.SetConditionalFormat("Sheet1", "A1:A2", []ConditionalFormatOptions{{Type: "icon_set", IconStyle: "unknown"}})) assert.Equal(t, ErrParameterInvalid, f.SetConditionalFormat("Sheet1", "A1:A2", []ConditionalFormatOptions{{Type: "icon_set", IconStyle: "unknown"}}))
// Test unsupported conditional formatting rule types // Test unsupported conditional formatting rule types
assert.Equal(t, ErrParameterInvalid, f.SetConditionalFormat("Sheet1", "A1", []ConditionalFormatOptions{{Type: "unsupported"}})) 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) { func TestGetConditionalFormats(t *testing.T) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册