document: support adding hyperlinks to a document

Fixes #113
This commit is contained in:
Todd 2017-10-10 12:40:02 -05:00
parent 35ff76f0f2
commit 6884ee78c3
7 changed files with 132 additions and 8 deletions

Binary file not shown.

View File

@ -0,0 +1,34 @@
package main
import (
"baliance.com/gooxml/color"
"baliance.com/gooxml/document"
"baliance.com/gooxml/schema/soo/wml"
)
func main() {
doc := document.New()
hlStyle := doc.Styles.AddStyle("Hyperlink", wml.ST_StyleTypeCharacter, false)
hlStyle.SetName("Hyperlink")
hlStyle.SetBasedOn("DefaultParagraphFont")
hlStyle.RunProperties().Color().SetThemeColor(wml.ST_ThemeColorHyperlink)
clr := color.FromHex("#0563C1")
hlStyle.RunProperties().Color().SetColor(clr)
hlStyle.RunProperties().SetUnderline(wml.ST_UnderlineSingle, clr)
para := doc.AddParagraph()
run := para.AddRun()
run.AddText("Hello World! ")
hl := para.AddHyperLink()
hl.SetTarget("http://www.google.com")
run = hl.AddRun()
run.SetStyle("Hyperlink")
run.AddText("Click Here to open google.com")
hl.SetToolTip("hover to see this")
doc.SaveToFile("hyperlink.docx")
}

View File

@ -696,3 +696,10 @@ func (d *Document) insertParagraph(relativeTo Paragraph, before bool) Paragraph
}
return d.AddParagraph()
}
// AddHyperlink adds a hyperlink to a document. Adding the hyperlink to a document
// and setting it on a cell is more efficient than setting hyperlinks directly
// on a cell.
func (d Document) AddHyperlink(url string) common.Hyperlink {
return d.docRels.AddHyperlink(url)
}

55
document/hyperlink.go Normal file
View File

@ -0,0 +1,55 @@
// Copyright 2017 Baliance. All rights reserved.
//
// Use of this source code is governed by the terms of the Affero GNU General
// Public License version 3.0 as published by the Free Software Foundation and
// appearing in the file LICENSE included in the packaging of this file. A
// commercial license can be purchased by contacting sales@baliance.com.
package document
import (
"baliance.com/gooxml"
"baliance.com/gooxml/common"
"baliance.com/gooxml/schema/soo/wml"
)
// HyperLink is a link within a document.
type HyperLink struct {
d *Document
x *wml.CT_Hyperlink
}
// X returns the inner wrapped XML type.
func (h HyperLink) X() *wml.CT_Hyperlink {
return h.x
}
// SetTargetByRef sets the URL target of the hyperlink and is more efficient if a link
// destination will be used many times.
func (h HyperLink) SetTargetByRef(link common.Hyperlink) {
h.x.IdAttr = gooxml.String(common.Relationship(link).ID())
}
// SetTarget sets the URL target of the hyperlink.
func (h HyperLink) SetTarget(url string) {
rel := h.d.AddHyperlink(url)
h.x.IdAttr = gooxml.String(common.Relationship(rel).ID())
}
// SetToolTip sets the tooltip text for a hyperlink.
func (h HyperLink) SetToolTip(text string) {
if text == "" {
h.x.TooltipAttr = nil
} else {
h.x.TooltipAttr = gooxml.String(text)
}
}
// AddRun adds a run of text to a hyperlink. This is the text that will be linked.
func (h HyperLink) AddRun() Run {
rc := wml.NewEG_ContentRunContent()
h.x.EG_ContentRunContent = append(h.x.EG_ContentRunContent, rc)
r := wml.NewCT_R()
rc.R = r
return Run{h.d, nil, r}
}

View File

@ -82,14 +82,8 @@ func (p Paragraph) SetStyle(s string) {
// AddRun adds a run to a paragraph.
func (p Paragraph) AddRun() Run {
var pc *wml.EG_PContent
// no need to add a new EG_PContent if we already have one
if len(p.x.EG_PContent) > 0 {
pc = p.x.EG_PContent[len(p.x.EG_PContent)-1]
} else {
pc = wml.NewEG_PContent()
pc := wml.NewEG_PContent()
p.x.EG_PContent = append(p.x.EG_PContent, pc)
}
rc := wml.NewEG_ContentRunContent()
pc.EG_ContentRunContent = append(pc.EG_ContentRunContent, rc)
@ -168,3 +162,11 @@ func (p Paragraph) insertRun(relativeTo Run, before bool) Run {
}
return p.AddRun()
}
func (p Paragraph) AddHyperLink() HyperLink {
pc := wml.NewEG_PContent()
p.x.EG_PContent = append(p.x.EG_PContent, pc)
pc.Hyperlink = wml.NewCT_Hyperlink()
return HyperLink{p.d, pc.Hyperlink}
}

View File

@ -130,8 +130,20 @@ func (r Run) SetFontFamily(family string) {
r.x.RPr.RFonts.HAnsiAttr = gooxml.String(family)
}
// SetStyle sets the font size.
func (r Run) SetStyle(style string) {
r.ensureRPR()
if style == "" {
r.x.RPr.RStyle = nil
} else {
r.x.RPr.RStyle = wml.NewCT_String()
r.x.RPr.RStyle.ValAttr = style
}
}
// SetFontSize sets the font size.
func (r Run) SetFontSize(sz measurement.Distance) {
r.ensureRPR()
r.x.RPr.Sz = wml.NewCT_HpsMeasure()
// size is measured in half points
r.x.RPr.Sz.ValAttr.ST_UnsignedDecimalNumber = gooxml.Uint64(uint64(sz / measurement.HalfPoint))
@ -141,6 +153,7 @@ func (r Run) SetFontSize(sz measurement.Distance) {
// IsBold returns true if the run has been set to bold.
func (r Run) IsBold() bool {
r.ensureRPR()
if r.x.RPr == nil {
return false
}

View File

@ -9,6 +9,7 @@ package document
import (
"baliance.com/gooxml"
"baliance.com/gooxml/color"
"baliance.com/gooxml/measurement"
"baliance.com/gooxml/schema/soo/wml"
)
@ -58,3 +59,15 @@ func (r RunStyleProperties) Color() Color {
}
return Color{r.x.Color}
}
// SetUnderline controls underline for a run style.
func (r RunStyleProperties) SetUnderline(style wml.ST_Underline, c color.Color) {
if style == wml.ST_UnderlineUnset {
r.x.U = nil
} else {
r.x.U = wml.NewCT_Underline()
r.x.U.ColorAttr = &wml.ST_HexColor{}
r.x.U.ColorAttr.ST_HexColorRGB = c.AsRGBString()
r.x.U.ValAttr = style
}
}