Skip to content

Commit 773d4af

Browse files
authored
This closes qax-os#1217, support update cell hyperlink
Ref qax-os#1129, make `SetRowStyle` overwrite style of the cells
1 parent 856ee57 commit 773d4af

File tree

5 files changed

+64
-18
lines changed

5 files changed

+64
-18
lines changed

cell.go

+17-7
Original file line numberDiff line numberDiff line change
@@ -715,23 +715,30 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string, opts ...Hype
715715
}
716716

717717
var linkData xlsxHyperlink
718-
718+
idx := -1
719719
if ws.Hyperlinks == nil {
720720
ws.Hyperlinks = new(xlsxHyperlinks)
721721
}
722+
for i, hyperlink := range ws.Hyperlinks.Hyperlink {
723+
if hyperlink.Ref == axis {
724+
idx = i
725+
linkData = hyperlink
726+
break
727+
}
728+
}
722729

723730
if len(ws.Hyperlinks.Hyperlink) > TotalSheetHyperlinks {
724731
return ErrTotalSheetHyperlinks
725732
}
726733

727734
switch linkType {
728735
case "External":
736+
sheetPath := f.sheetMap[trimSheetName(sheet)]
737+
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
738+
rID := f.setRels(linkData.RID, sheetRels, SourceRelationshipHyperLink, link, linkType)
729739
linkData = xlsxHyperlink{
730740
Ref: axis,
731741
}
732-
sheetPath := f.sheetMap[trimSheetName(sheet)]
733-
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
734-
rID := f.addRels(sheetRels, SourceRelationshipHyperLink, link, linkType)
735742
linkData.RID = "rId" + strconv.Itoa(rID)
736743
f.addSheetNameSpace(sheet, SourceRelationship)
737744
case "Location":
@@ -751,9 +758,12 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string, opts ...Hype
751758
linkData.Tooltip = *o.Tooltip
752759
}
753760
}
754-
755-
ws.Hyperlinks.Hyperlink = append(ws.Hyperlinks.Hyperlink, linkData)
756-
return nil
761+
if idx == -1 {
762+
ws.Hyperlinks.Hyperlink = append(ws.Hyperlinks.Hyperlink, linkData)
763+
return err
764+
}
765+
ws.Hyperlinks.Hyperlink[idx] = linkData
766+
return err
757767
}
758768

759769
// getCellRichText returns rich text of cell by given string item.

excelize.go

+22
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,28 @@ func checkSheetR0(ws *xlsxWorksheet, sheetData *xlsxSheetData, r0 *xlsxRow) {
327327
ws.SheetData = *sheetData
328328
}
329329

330+
// setRels provides a function to set relationships by given relationship ID,
331+
// XML path, relationship type, target and target mode.
332+
func (f *File) setRels(rID, relPath, relType, target, targetMode string) int {
333+
rels := f.relsReader(relPath)
334+
if rels == nil || rID == "" {
335+
return f.addRels(relPath, relType, target, targetMode)
336+
}
337+
rels.Lock()
338+
defer rels.Unlock()
339+
var ID int
340+
for i, rel := range rels.Relationships {
341+
if rel.ID == rID {
342+
rels.Relationships[i].Type = relType
343+
rels.Relationships[i].Target = target
344+
rels.Relationships[i].TargetMode = targetMode
345+
ID, _ = strconv.Atoi(strings.TrimPrefix(rID, "rId"))
346+
break
347+
}
348+
}
349+
return ID
350+
}
351+
330352
// addRels provides a function to add relationships by given XML path,
331353
// relationship type, target and target mode.
332354
func (f *File) addRels(relPath, relType, target, targetMode string) int {

excelize_test.go

+11-5
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,15 @@ func TestAddDrawingVML(t *testing.T) {
336336

337337
func TestSetCellHyperLink(t *testing.T) {
338338
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
339-
if err != nil {
340-
t.Log(err)
341-
}
339+
assert.NoError(t, err)
342340
// Test set cell hyperlink in a work sheet already have hyperlinks.
343341
assert.NoError(t, f.SetCellHyperLink("Sheet1", "B19", "https://github.com/xuri/excelize", "External"))
344342
// Test add first hyperlink in a work sheet.
345343
assert.NoError(t, f.SetCellHyperLink("Sheet2", "C1", "https://github.com/xuri/excelize", "External"))
346344
// Test add Location hyperlink in a work sheet.
347345
assert.NoError(t, f.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location"))
348346
// Test add Location hyperlink with display & tooltip in a work sheet.
349-
display := "Display value"
350-
tooltip := "Hover text"
347+
display, tooltip := "Display value", "Hover text"
351348
assert.NoError(t, f.SetCellHyperLink("Sheet2", "D7", "Sheet1!D9", "Location", HyperlinkOpts{
352349
Display: &display,
353350
Tooltip: &tooltip,
@@ -376,6 +373,15 @@ func TestSetCellHyperLink(t *testing.T) {
376373
ws.(*xlsxWorksheet).MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}}
377374
err = f.SetCellHyperLink("Sheet1", "A1", "https://github.com/xuri/excelize", "External")
378375
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
376+
377+
// Test update cell hyperlink
378+
f = NewFile()
379+
assert.NoError(t, f.SetCellHyperLink("Sheet1", "A1", "https://github.com", "External"))
380+
assert.NoError(t, f.SetCellHyperLink("Sheet1", "A1", "https://github.com/xuri/excelize", "External"))
381+
link, target, err := f.GetCellHyperLink("Sheet1", "A1")
382+
assert.Equal(t, link, true)
383+
assert.Equal(t, "https://github.com/xuri/excelize", target)
384+
assert.NoError(t, err)
379385
}
380386

381387
func TestGetCellHyperLink(t *testing.T) {

rows.go

+5
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,11 @@ func (f *File) SetRowStyle(sheet string, start, end, styleID int) error {
841841
for row := start - 1; row < end; row++ {
842842
ws.SheetData.Row[row].S = styleID
843843
ws.SheetData.Row[row].CustomFormat = true
844+
for i := range ws.SheetData.Row[row].C {
845+
if _, rowNum, err := CellNameToCoordinates(ws.SheetData.Row[row].C[i].R); err == nil && rowNum-1 == row {
846+
ws.SheetData.Row[row].C[i].S = styleID
847+
}
848+
}
844849
}
845850
return nil
846851
}

rows_test.go

+9-6
Original file line numberDiff line numberDiff line change
@@ -915,16 +915,19 @@ func TestCheckRow(t *testing.T) {
915915

916916
func TestSetRowStyle(t *testing.T) {
917917
f := NewFile()
918-
styleID, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
918+
style1, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#63BE7B"],"pattern":1}}`)
919919
assert.NoError(t, err)
920-
assert.EqualError(t, f.SetRowStyle("Sheet1", 10, -1, styleID), newInvalidRowNumberError(-1).Error())
921-
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, TotalRows+1, styleID), ErrMaxRows.Error())
920+
style2, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
921+
assert.NoError(t, err)
922+
assert.NoError(t, f.SetCellStyle("Sheet1", "B2", "B2", style1))
923+
assert.EqualError(t, f.SetRowStyle("Sheet1", 5, -1, style2), newInvalidRowNumberError(-1).Error())
924+
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, TotalRows+1, style2), ErrMaxRows.Error())
922925
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, 1, -1), newInvalidStyleID(-1).Error())
923-
assert.EqualError(t, f.SetRowStyle("SheetN", 1, 1, styleID), "sheet SheetN is not exist")
924-
assert.NoError(t, f.SetRowStyle("Sheet1", 10, 1, styleID))
926+
assert.EqualError(t, f.SetRowStyle("SheetN", 1, 1, style2), "sheet SheetN is not exist")
927+
assert.NoError(t, f.SetRowStyle("Sheet1", 5, 1, style2))
925928
cellStyleID, err := f.GetCellStyle("Sheet1", "B2")
926929
assert.NoError(t, err)
927-
assert.Equal(t, styleID, cellStyleID)
930+
assert.Equal(t, style2, cellStyleID)
928931
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetRowStyle.xlsx")))
929932
}
930933

0 commit comments

Comments
 (0)