Skip to content
This repository was archived by the owner on Aug 13, 2025. It is now read-only.

Commit 9874921

Browse files
authored
Merge pull request #844 from Sajito/fix/parse-with-hyperlinks
Read relations when parsing a file
2 parents df122de + 2608549 commit 9874921

File tree

4 files changed

+76
-32
lines changed

4 files changed

+76
-32
lines changed

file_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,14 @@ func TestFile(t *testing.T) {
907907
c.Assert(cell1.Value, qt.Equals, "A cell!")
908908
})
909909

910+
csRunO(c, "OpenAndMarshalFileWithHyperlinks", func(c *qt.C, option FileOption) {
911+
f, err := OpenFile("./testdocs/file_with_hyperlinks.xlsx", option)
912+
c.Assert(err, qt.IsNil)
913+
parts, err := f.MakeStreamParts()
914+
c.Assert(err, qt.IsNil)
915+
c.Assert(parts["xl/worksheets/_rels/sheet1.xml.rels"], qt.Contains, `Target="https://www.google.com/" TargetMode="External"`)
916+
})
917+
910918
csRunO(c, "TestMarshalFileWithHyperlinks", func(c *qt.C, option FileOption) {
911919
f := NewFile(option)
912920
sheet1, _ := f.AddSheet("MySheet")

lib.go

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -637,9 +637,34 @@ type coord struct {
637637
y int
638638
}
639639

640+
func makeRelations(fi *File, rsheet *xlsxSheet) (*xlsxRels, error) {
641+
rels := new(xlsxRels)
642+
643+
wrap := func(err error) (*xlsxRels, error) {
644+
return nil, fmt.Errorf("makeRelations: %w", err)
645+
}
646+
647+
relsFile, ok := fi.worksheetRels["sheet"+rsheet.SheetId]
648+
if ok {
649+
rc, err := relsFile.Open()
650+
if err != nil {
651+
return wrap(fmt.Errorf("file.Open: %w", err))
652+
}
653+
defer rc.Close()
654+
655+
decoder := xml.NewDecoder(rc)
656+
err = decoder.Decode(rels)
657+
if err != nil {
658+
return wrap(fmt.Errorf("xml.Decoder.Decode: %w", err))
659+
}
660+
}
661+
662+
return rels, nil
663+
}
664+
640665
type hyperlinkTable map[coord]Hyperlink
641666

642-
func makeHyperlinkTable(worksheet *xlsxWorksheet, fi *File, rsheet *xlsxSheet) (hyperlinkTable, error) {
667+
func makeHyperlinkTable(worksheet *xlsxWorksheet, rels *xlsxRels) (hyperlinkTable, error) {
643668
wrap := func(err error) (hyperlinkTable, error) {
644669
return nil, fmt.Errorf("makeHyperlinkTable: %w", err)
645670
}
@@ -648,26 +673,10 @@ func makeHyperlinkTable(worksheet *xlsxWorksheet, fi *File, rsheet *xlsxSheet) (
648673

649674
// Convert xlsxHyperlinks to Hyperlinks
650675
if worksheet.Hyperlinks != nil {
651-
652-
worksheetRelsFile, ok := fi.worksheetRels["sheet"+rsheet.SheetId]
653-
worksheetRels := new(xlsxWorksheetRels)
654-
if ok {
655-
rc, err := worksheetRelsFile.Open()
656-
if err != nil {
657-
return wrap(fmt.Errorf("file.Open: %w", err))
658-
}
659-
defer rc.Close()
660-
661-
decoder := xml.NewDecoder(rc)
662-
err = decoder.Decode(worksheetRels)
663-
if err != nil {
664-
return wrap(fmt.Errorf("xml.Decoder.Decode: %w", err))
665-
}
666-
}
667676
for _, xlsxLink := range worksheet.Hyperlinks.HyperLinks {
668677
newHyperLink := Hyperlink{}
669678

670-
for _, rel := range worksheetRels.Relationships {
679+
for _, rel := range rels.Relationships {
671680
if rel.Id == xlsxLink.RelationshipId {
672681
newHyperLink.Link = rel.Target
673682
break
@@ -724,12 +733,24 @@ func readSheetFromFile(rsheet xlsxSheet, fi *File, sheetXMLMap map[string]string
724733
return wrap(err)
725734
}
726735

727-
linkTable, err := makeHyperlinkTable(worksheet, fi, &rsheet)
736+
sheet, err = NewSheetWithCellStore(rsheet.Name, fi.cellStoreConstructor)
728737
if err != nil {
729738
return wrap(err)
730739
}
731740

732-
sheet, err = NewSheetWithCellStore(rsheet.Name, fi.cellStoreConstructor)
741+
rels, err := makeRelations(fi, &rsheet)
742+
if err != nil {
743+
return wrap(err)
744+
}
745+
for _, rel := range rels.Relationships {
746+
sheet.Relations = append(sheet.Relations, Relation{
747+
Type: rel.Type,
748+
Target: rel.Target,
749+
TargetMode: rel.TargetMode,
750+
})
751+
}
752+
753+
linkTable, err := makeHyperlinkTable(worksheet, rels)
733754
if err != nil {
734755
return wrap(err)
735756
}

xlsxRelation.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package xlsx
2+
3+
import "encoding/xml"
4+
5+
type RelationshipType string
6+
7+
const (
8+
RelationshipTypeHyperlink RelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
9+
)
10+
11+
type RelationshipTargetMode string
12+
13+
const (
14+
RelationshipTargetModeExternal RelationshipTargetMode = "External"
15+
)
16+
17+
type xlsxRels struct {
18+
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/relationships Relationships"`
19+
Relationships []xlsxRelation `xml:"Relationship"`
20+
}
21+
22+
type xlsxRelation struct {
23+
Id string `xml:"Id,attr"`
24+
Type RelationshipType `xml:"Type,attr"`
25+
Target string `xml:"Target,attr"`
26+
TargetMode RelationshipTargetMode `xml:"TargetMode,attr,omitempty"`
27+
}

xmlWorksheet.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,6 @@ import (
1111
"github.com/shabbyrobe/xmlwriter"
1212
)
1313

14-
type RelationshipType string
15-
16-
const (
17-
RelationshipTypeHyperlink RelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
18-
)
19-
20-
type RelationshipTargetMode string
21-
22-
const (
23-
RelationshipTargetModeExternal RelationshipTargetMode = "External"
24-
)
25-
2614
// xlsxWorksheetRels contains xlsxWorksheetRelation
2715
type xlsxWorksheetRels struct {
2816
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/relationships Relationships"`

0 commit comments

Comments
 (0)