Skip to content

Commit

Permalink
This closes #1217, support update cell hyperlink
Browse files Browse the repository at this point in the history
Ref #1129, make `SetRowStyle` overwrite style of the cells
  • Loading branch information
xuri committed May 1, 2022
1 parent 856ee57 commit 773d4af
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 18 deletions.
24 changes: 17 additions & 7 deletions cell.go
Expand Up @@ -715,23 +715,30 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string, opts ...Hype
}

var linkData xlsxHyperlink

idx := -1
if ws.Hyperlinks == nil {
ws.Hyperlinks = new(xlsxHyperlinks)
}
for i, hyperlink := range ws.Hyperlinks.Hyperlink {
if hyperlink.Ref == axis {
idx = i
linkData = hyperlink
break
}
}

if len(ws.Hyperlinks.Hyperlink) > TotalSheetHyperlinks {
return ErrTotalSheetHyperlinks
}

switch linkType {
case "External":
sheetPath := f.sheetMap[trimSheetName(sheet)]
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
rID := f.setRels(linkData.RID, sheetRels, SourceRelationshipHyperLink, link, linkType)
linkData = xlsxHyperlink{
Ref: axis,
}
sheetPath := f.sheetMap[trimSheetName(sheet)]
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
rID := f.addRels(sheetRels, SourceRelationshipHyperLink, link, linkType)
linkData.RID = "rId" + strconv.Itoa(rID)
f.addSheetNameSpace(sheet, SourceRelationship)
case "Location":
Expand All @@ -751,9 +758,12 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string, opts ...Hype
linkData.Tooltip = *o.Tooltip
}
}

ws.Hyperlinks.Hyperlink = append(ws.Hyperlinks.Hyperlink, linkData)
return nil
if idx == -1 {
ws.Hyperlinks.Hyperlink = append(ws.Hyperlinks.Hyperlink, linkData)
return err
}
ws.Hyperlinks.Hyperlink[idx] = linkData
return err
}

// getCellRichText returns rich text of cell by given string item.
Expand Down
22 changes: 22 additions & 0 deletions excelize.go
Expand Up @@ -327,6 +327,28 @@ func checkSheetR0(ws *xlsxWorksheet, sheetData *xlsxSheetData, r0 *xlsxRow) {
ws.SheetData = *sheetData
}

// setRels provides a function to set relationships by given relationship ID,
// XML path, relationship type, target and target mode.
func (f *File) setRels(rID, relPath, relType, target, targetMode string) int {
rels := f.relsReader(relPath)
if rels == nil || rID == "" {
return f.addRels(relPath, relType, target, targetMode)
}
rels.Lock()
defer rels.Unlock()
var ID int
for i, rel := range rels.Relationships {
if rel.ID == rID {
rels.Relationships[i].Type = relType
rels.Relationships[i].Target = target
rels.Relationships[i].TargetMode = targetMode
ID, _ = strconv.Atoi(strings.TrimPrefix(rID, "rId"))
break
}
}
return ID
}

// addRels provides a function to add relationships by given XML path,
// relationship type, target and target mode.
func (f *File) addRels(relPath, relType, target, targetMode string) int {
Expand Down
16 changes: 11 additions & 5 deletions excelize_test.go
Expand Up @@ -336,18 +336,15 @@ func TestAddDrawingVML(t *testing.T) {

func TestSetCellHyperLink(t *testing.T) {
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
if err != nil {
t.Log(err)
}
assert.NoError(t, err)
// Test set cell hyperlink in a work sheet already have hyperlinks.
assert.NoError(t, f.SetCellHyperLink("Sheet1", "B19", "https://github.com/xuri/excelize", "External"))
// Test add first hyperlink in a work sheet.
assert.NoError(t, f.SetCellHyperLink("Sheet2", "C1", "https://github.com/xuri/excelize", "External"))
// Test add Location hyperlink in a work sheet.
assert.NoError(t, f.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location"))
// Test add Location hyperlink with display & tooltip in a work sheet.
display := "Display value"
tooltip := "Hover text"
display, tooltip := "Display value", "Hover text"
assert.NoError(t, f.SetCellHyperLink("Sheet2", "D7", "Sheet1!D9", "Location", HyperlinkOpts{
Display: &display,
Tooltip: &tooltip,
Expand Down Expand Up @@ -376,6 +373,15 @@ func TestSetCellHyperLink(t *testing.T) {
ws.(*xlsxWorksheet).MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}}
err = f.SetCellHyperLink("Sheet1", "A1", "https://github.com/xuri/excelize", "External")
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())

// Test update cell hyperlink
f = NewFile()
assert.NoError(t, f.SetCellHyperLink("Sheet1", "A1", "https://github.com", "External"))
assert.NoError(t, f.SetCellHyperLink("Sheet1", "A1", "https://github.com/xuri/excelize", "External"))
link, target, err := f.GetCellHyperLink("Sheet1", "A1")
assert.Equal(t, link, true)
assert.Equal(t, "https://github.com/xuri/excelize", target)
assert.NoError(t, err)
}

func TestGetCellHyperLink(t *testing.T) {
Expand Down
5 changes: 5 additions & 0 deletions rows.go
Expand Up @@ -841,6 +841,11 @@ func (f *File) SetRowStyle(sheet string, start, end, styleID int) error {
for row := start - 1; row < end; row++ {
ws.SheetData.Row[row].S = styleID
ws.SheetData.Row[row].CustomFormat = true
for i := range ws.SheetData.Row[row].C {
if _, rowNum, err := CellNameToCoordinates(ws.SheetData.Row[row].C[i].R); err == nil && rowNum-1 == row {
ws.SheetData.Row[row].C[i].S = styleID
}
}
}
return nil
}
Expand Down
15 changes: 9 additions & 6 deletions rows_test.go
Expand Up @@ -915,16 +915,19 @@ func TestCheckRow(t *testing.T) {

func TestSetRowStyle(t *testing.T) {
f := NewFile()
styleID, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
style1, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#63BE7B"],"pattern":1}}`)
assert.NoError(t, err)
assert.EqualError(t, f.SetRowStyle("Sheet1", 10, -1, styleID), newInvalidRowNumberError(-1).Error())
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, TotalRows+1, styleID), ErrMaxRows.Error())
style2, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
assert.NoError(t, err)
assert.NoError(t, f.SetCellStyle("Sheet1", "B2", "B2", style1))
assert.EqualError(t, f.SetRowStyle("Sheet1", 5, -1, style2), newInvalidRowNumberError(-1).Error())
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, TotalRows+1, style2), ErrMaxRows.Error())
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, 1, -1), newInvalidStyleID(-1).Error())
assert.EqualError(t, f.SetRowStyle("SheetN", 1, 1, styleID), "sheet SheetN is not exist")
assert.NoError(t, f.SetRowStyle("Sheet1", 10, 1, styleID))
assert.EqualError(t, f.SetRowStyle("SheetN", 1, 1, style2), "sheet SheetN is not exist")
assert.NoError(t, f.SetRowStyle("Sheet1", 5, 1, style2))
cellStyleID, err := f.GetCellStyle("Sheet1", "B2")
assert.NoError(t, err)
assert.Equal(t, styleID, cellStyleID)
assert.Equal(t, style2, cellStyleID)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetRowStyle.xlsx")))
}

Expand Down

0 comments on commit 773d4af

Please sign in to comment.