mirror of
https://github.com/fumiama/go-docx.git
synced 2026-06-18 08:24:11 +08:00
add w:jc & w:tab
This commit is contained in:
16
apipara.go
16
apipara.go
@@ -11,3 +11,19 @@ func (f *Docx) AddParagraph() *Paragraph {
|
|||||||
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Justification allows to set para's horizonal alignment
|
||||||
|
//
|
||||||
|
// w:jc 属性的取值可以是以下之一:
|
||||||
|
// start:左对齐。
|
||||||
|
// center:居中对齐。
|
||||||
|
// end:右对齐。
|
||||||
|
// both:两端对齐。
|
||||||
|
// distribute:分散对齐。
|
||||||
|
func (p *Paragraph) Justification(val string) *Paragraph {
|
||||||
|
if p.Properties == nil {
|
||||||
|
p.Properties = &ParagraphProperties{}
|
||||||
|
}
|
||||||
|
p.Properties.Justification = &Justification{Val: val}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|||||||
34
apirun.go
34
apirun.go
@@ -1,5 +1,7 @@
|
|||||||
package docxlib
|
package docxlib
|
||||||
|
|
||||||
|
import "encoding/xml"
|
||||||
|
|
||||||
// Color allows to set run color
|
// Color allows to set run color
|
||||||
func (r *Run) Color(color string) *Run {
|
func (r *Run) Color(color string) *Run {
|
||||||
r.RunProperties.Color = &Color{
|
r.RunProperties.Color = &Color{
|
||||||
@@ -17,3 +19,35 @@ func (r *Run) Size(size string) *Run {
|
|||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Justification allows to set run's horizonal alignment
|
||||||
|
//
|
||||||
|
// w:jc 属性的取值可以是以下之一:
|
||||||
|
// start:左对齐。
|
||||||
|
// center:居中对齐。
|
||||||
|
// end:右对齐。
|
||||||
|
// both:两端对齐。
|
||||||
|
// distribute:分散对齐。
|
||||||
|
func (r *Run) Justification(val string) *Run {
|
||||||
|
r.RunProperties.Justification = &Justification{
|
||||||
|
Val: val,
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTab add a tab in front of the run
|
||||||
|
func (r *Run) AddTab() *Run {
|
||||||
|
r.FrontTab = append(r.FrontTab, struct {
|
||||||
|
XMLName xml.Name "xml:\"w:tab,omitempty\""
|
||||||
|
}{})
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendTab add a tab after the run
|
||||||
|
func (r *Run) AppendTab() *Run {
|
||||||
|
r.RearTab = append(r.RearTab, struct {
|
||||||
|
XMLName xml.Name "xml:\"w:tab,omitempty\""
|
||||||
|
}{})
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|||||||
18
apitext.go
18
apitext.go
@@ -1,7 +1,25 @@
|
|||||||
package docxlib
|
package docxlib
|
||||||
|
|
||||||
|
import "encoding/xml"
|
||||||
|
|
||||||
|
// AddTab adds tab to para
|
||||||
|
func (p *Paragraph) AddTab() *Run {
|
||||||
|
run := &Run{
|
||||||
|
RunProperties: &RunProperties{},
|
||||||
|
FrontTab: []struct {
|
||||||
|
XMLName xml.Name "xml:\"w:tab,omitempty\""
|
||||||
|
}{{}},
|
||||||
|
}
|
||||||
|
p.Children = append(p.Children, ParagraphChild{Run: run})
|
||||||
|
return run
|
||||||
|
}
|
||||||
|
|
||||||
// AddText adds text to paragraph
|
// AddText adds text to paragraph
|
||||||
func (p *Paragraph) AddText(text string) *Run {
|
func (p *Paragraph) AddText(text string) *Run {
|
||||||
|
if text == "\t" {
|
||||||
|
return p.AddTab()
|
||||||
|
}
|
||||||
|
|
||||||
t := &Text{
|
t := &Text{
|
||||||
Text: text,
|
Text: text,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,36 +19,41 @@ func main() {
|
|||||||
|
|
||||||
w := docxlib.NewA4()
|
w := docxlib.NewA4()
|
||||||
// add new paragraph
|
// add new paragraph
|
||||||
para1 := w.AddParagraph()
|
para1 := w.AddParagraph().Justification("distribute")
|
||||||
// add text
|
// add text
|
||||||
para1.AddText("test")
|
para1.AddText("test").Justification("distribute")
|
||||||
|
para1.AddText("test font size").Size("44").Justification("distribute")
|
||||||
|
para1.AddText("test color").Color("808080").Justification("distribute")
|
||||||
|
|
||||||
para1.AddText("test font size").Size("44")
|
para2 := w.AddParagraph().Justification("end")
|
||||||
para1.AddText("test color").Color("808080")
|
para2.AddText("test font size and color").Size("44").Color("ff0000").Justification("end")
|
||||||
para2 := w.AddParagraph()
|
|
||||||
para2.AddText("test font size and color").Size("44").Color("ff0000")
|
|
||||||
|
|
||||||
nextPara := w.AddParagraph()
|
nextPara := w.AddParagraph()
|
||||||
nextPara.AddLink("google", `http://google.com`)
|
nextPara.AddLink("google", `http://google.com`)
|
||||||
|
|
||||||
para3 := w.AddParagraph()
|
para3 := w.AddParagraph().Justification("center")
|
||||||
// add text
|
// add text
|
||||||
para3.AddText("直接粘贴 inline")
|
para3.AddText("一行2个 inline").Size("44").Justification("center")
|
||||||
|
|
||||||
para4 := w.AddParagraph()
|
para4 := w.AddParagraph().Justification("center")
|
||||||
r, err := para4.AddInlineDrawingFrom("testdata/fumiama.JPG")
|
r, err := para4.AddInlineDrawingFrom("testdata/fumiama.JPG")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
r.Drawing.Inline.Size(r.Drawing.Inline.Extent.CX/2, r.Drawing.Inline.Extent.CY/2)
|
r.Drawing.Inline.Size(r.Drawing.Inline.Extent.CX*4/5, r.Drawing.Inline.Extent.CY*4/5)
|
||||||
|
para4.AddTab().AddTab()
|
||||||
r, err = para4.AddInlineDrawingFrom("testdata/fumiama2x.webp")
|
r, err = para4.AddInlineDrawingFrom("testdata/fumiama2x.webp")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
r.Drawing.Inline.Size(r.Drawing.Inline.Extent.CX/2, r.Drawing.Inline.Extent.CY/2)
|
r.Drawing.Inline.Size(r.Drawing.Inline.Extent.CX*4/5, r.Drawing.Inline.Extent.CY*4/5)
|
||||||
|
|
||||||
para5 := w.AddParagraph()
|
para5 := w.AddParagraph().Justification("center")
|
||||||
_, err = para5.AddInlineDrawingFrom("testdata/fumiamayoko.png")
|
// add text
|
||||||
|
para5.AddText("一行1个 横向 inline").Size("44").Justification("center")
|
||||||
|
|
||||||
|
para6 := w.AddParagraph()
|
||||||
|
_, err = para6.AddInlineDrawingFrom("testdata/fumiamayoko.png")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,9 +40,6 @@ func TestUnmarshalPlainStructure(t *testing.T) {
|
|||||||
if child.Link == nil && child.Properties == nil && child.Run == nil {
|
if child.Link == nil && child.Properties == nil && child.Run == nil {
|
||||||
t.Fatalf("There are Paragraph children with all fields nil")
|
t.Fatalf("There are Paragraph children with all fields nil")
|
||||||
}
|
}
|
||||||
if child.Run != nil && child.Run.Text == nil && child.Run.InstrText == "" {
|
|
||||||
t.Fatalf("We have a run with no text")
|
|
||||||
}
|
|
||||||
if child.Link != nil && child.Link.ID == "" {
|
if child.Link != nil && child.Link.ID == "" {
|
||||||
t.Fatalf("We have a link without ID")
|
t.Fatalf("We have a link without ID")
|
||||||
}
|
}
|
||||||
@@ -572,10 +569,11 @@ func TestMarshalDrawingStructure(t *testing.T) {
|
|||||||
// add new paragraph
|
// add new paragraph
|
||||||
para1 := w.AddParagraph()
|
para1 := w.AddParagraph()
|
||||||
// add text
|
// add text
|
||||||
para1.AddText("直接粘贴 inline")
|
para1.AddText("直接粘贴 inline").AddTab().Justification("center")
|
||||||
|
|
||||||
para2 := w.AddParagraph()
|
para2 := w.AddParagraph().Justification("center")
|
||||||
para2.AddInlineDrawingFrom("testdata/fumiama.JPG")
|
para2.AddInlineDrawingFrom("testdata/fumiama.JPG")
|
||||||
|
para2.AddTab().AddTab().AppendTab().AppendTab()
|
||||||
para2.AddInlineDrawingFrom("testdata/fumiama2x.webp")
|
para2.AddInlineDrawingFrom("testdata/fumiama2x.webp")
|
||||||
|
|
||||||
para3 := w.AddParagraph()
|
para3 := w.AddParagraph()
|
||||||
|
|||||||
@@ -6,6 +6,35 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ParagraphProperties struct {
|
||||||
|
XMLName xml.Name `xml:"w:pPr,omitempty"`
|
||||||
|
Justification *Justification `xml:"w:jc,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ParagraphProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
for {
|
||||||
|
t, err := d.Token()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch tt := t.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
switch tt.Name.Local {
|
||||||
|
case "jc":
|
||||||
|
p.Justification = &Justification{Val: getAtt(tt.Attr, "val")}
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
type ParagraphChild struct {
|
type ParagraphChild struct {
|
||||||
Link *Hyperlink `xml:"w:hyperlink,omitempty"`
|
Link *Hyperlink `xml:"w:hyperlink,omitempty"`
|
||||||
Run *Run `xml:"w:r,omitempty"`
|
Run *Run `xml:"w:r,omitempty"`
|
||||||
@@ -13,8 +42,9 @@ type ParagraphChild struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Paragraph struct {
|
type Paragraph struct {
|
||||||
XMLName xml.Name `xml:"w:p,omitempty"`
|
XMLName xml.Name `xml:"w:p,omitempty"`
|
||||||
Children []ParagraphChild // Children will generate an unnecessary tag <Children> ... </Children> and we skip it by a self-defined xml.Marshaler
|
Properties *ParagraphProperties
|
||||||
|
Children []ParagraphChild // Children will generate an unnecessary tag <Children> ... </Children> and we skip it by a self-defined xml.Marshaler
|
||||||
|
|
||||||
file *Docx
|
file *Docx
|
||||||
}
|
}
|
||||||
@@ -51,6 +81,12 @@ func (p *Paragraph) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if p.Properties != nil {
|
||||||
|
err = e.Encode(p.Properties)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, c := range p.Children {
|
for _, c := range p.Children {
|
||||||
switch {
|
switch {
|
||||||
case c.Link != nil:
|
case c.Link != nil:
|
||||||
@@ -99,13 +135,15 @@ func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
var value Run
|
var value Run
|
||||||
d.DecodeElement(&value, &start)
|
d.DecodeElement(&value, &start)
|
||||||
elem.Run = &value
|
elem.Run = &value
|
||||||
if value.InstrText == "" && value.Text == nil && value.Drawing == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "rPr":
|
case "rPr":
|
||||||
var value RunProperties
|
var value RunProperties
|
||||||
d.DecodeElement(&value, &start)
|
d.DecodeElement(&value, &start)
|
||||||
elem.Properties = &value
|
elem.Properties = &value
|
||||||
|
case "pPr":
|
||||||
|
var value ParagraphProperties
|
||||||
|
d.DecodeElement(&value, &start)
|
||||||
|
p.Properties = &value
|
||||||
|
continue
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
50
structrun.go
50
structrun.go
@@ -10,9 +10,15 @@ import (
|
|||||||
type Run struct {
|
type Run struct {
|
||||||
XMLName xml.Name `xml:"w:r,omitempty"`
|
XMLName xml.Name `xml:"w:r,omitempty"`
|
||||||
RunProperties *RunProperties `xml:"w:rPr,omitempty"`
|
RunProperties *RunProperties `xml:"w:rPr,omitempty"`
|
||||||
InstrText string `xml:"w:instrText,omitempty"`
|
FrontTab []struct {
|
||||||
Text *Text
|
XMLName xml.Name `xml:"w:tab,omitempty"`
|
||||||
Drawing *Drawing
|
}
|
||||||
|
InstrText string `xml:"w:instrText,omitempty"`
|
||||||
|
Text *Text
|
||||||
|
Drawing *Drawing
|
||||||
|
RearTab []struct {
|
||||||
|
XMLName xml.Name `xml:"w:tab,omitempty"`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
@@ -44,6 +50,16 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
var value Drawing
|
var value Drawing
|
||||||
d.DecodeElement(&value, &start)
|
d.DecodeElement(&value, &start)
|
||||||
r.Drawing = &value
|
r.Drawing = &value
|
||||||
|
case "tab":
|
||||||
|
if r.InstrText == "" && r.Text == nil && r.Drawing == nil {
|
||||||
|
r.FrontTab = append(r.FrontTab, struct {
|
||||||
|
XMLName xml.Name "xml:\"w:tab,omitempty\""
|
||||||
|
}{})
|
||||||
|
} else {
|
||||||
|
r.RearTab = append(r.RearTab, struct {
|
||||||
|
XMLName xml.Name "xml:\"w:tab,omitempty\""
|
||||||
|
}{})
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -57,11 +73,12 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
|
|
||||||
// RunProperties encapsulates visual properties of a run
|
// RunProperties encapsulates visual properties of a run
|
||||||
type RunProperties struct {
|
type RunProperties struct {
|
||||||
XMLName xml.Name `xml:"w:rPr,omitempty"`
|
XMLName xml.Name `xml:"w:rPr,omitempty"`
|
||||||
Color *Color `xml:"w:color,omitempty"`
|
Color *Color `xml:"w:color,omitempty"`
|
||||||
Size *Size `xml:"w:sz,omitempty"`
|
Size *Size `xml:"w:sz,omitempty"`
|
||||||
RunStyle *RunStyle `xml:"w:rStyle,omitempty"`
|
RunStyle *RunStyle `xml:"w:rStyle,omitempty"`
|
||||||
Style *Style `xml:"w:pStyle,omitempty"`
|
Style *Style `xml:"w:pStyle,omitempty"`
|
||||||
|
Justification *Justification `xml:"w:jc,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
@@ -93,6 +110,10 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
|
|||||||
var value Style
|
var value Style
|
||||||
value.Val = getAtt(tt.Attr, "val")
|
value.Val = getAtt(tt.Attr, "val")
|
||||||
r.Style = &value
|
r.Style = &value
|
||||||
|
case "jc":
|
||||||
|
var value Justification
|
||||||
|
value.Val = getAtt(tt.Attr, "val")
|
||||||
|
r.Justification = &value
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -128,3 +149,16 @@ type Size struct {
|
|||||||
XMLName xml.Name `xml:"w:sz"`
|
XMLName xml.Name `xml:"w:sz"`
|
||||||
Val string `xml:"w:val,attr"`
|
Val string `xml:"w:val,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Justification contains the way of the horizonal alignment
|
||||||
|
//
|
||||||
|
// w:jc 属性的取值可以是以下之一:
|
||||||
|
// start:左对齐。
|
||||||
|
// center:居中对齐。
|
||||||
|
// end:右对齐。
|
||||||
|
// both:两端对齐。
|
||||||
|
// distribute:分散对齐。
|
||||||
|
type Justification struct {
|
||||||
|
XMLName xml.Name `xml:"w:jc"`
|
||||||
|
Val string `xml:"w:val,attr"`
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user