diff --git a/_examples/document/hyperlink/hyperlink.docx b/_examples/document/hyperlink/hyperlink.docx new file mode 100644 index 00000000..93c95940 Binary files /dev/null and b/_examples/document/hyperlink/hyperlink.docx differ diff --git a/_examples/document/hyperlink/main.go b/_examples/document/hyperlink/main.go new file mode 100644 index 00000000..586c905d --- /dev/null +++ b/_examples/document/hyperlink/main.go @@ -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") +} diff --git a/document/document.go b/document/document.go index 7c8d8091..4300fd85 100644 --- a/document/document.go +++ b/document/document.go @@ -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) +} diff --git a/document/hyperlink.go b/document/hyperlink.go new file mode 100644 index 00000000..1e08fc6e --- /dev/null +++ b/document/hyperlink.go @@ -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} +} diff --git a/document/paragraph.go b/document/paragraph.go index 06fbe0bc..b21270dc 100644 --- a/document/paragraph.go +++ b/document/paragraph.go @@ -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() - p.x.EG_PContent = append(p.x.EG_PContent, pc) - } + 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} +} diff --git a/document/run.go b/document/run.go index 770c87b8..8eabb446 100644 --- a/document/run.go +++ b/document/run.go @@ -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 } diff --git a/document/runstyleproperties.go b/document/runstyleproperties.go index 1b3c0721..0b8f4c5f 100644 --- a/document/runstyleproperties.go +++ b/document/runstyleproperties.go @@ -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 + } +}