1
0
mirror of https://github.com/fumiama/go-docx.git synced 2026-06-12 11:40:28 +08:00

完善group

This commit is contained in:
源文雨
2023-03-05 23:02:07 +08:00
parent ff131af5fa
commit 50aa6e005e
6 changed files with 257 additions and 141 deletions

View File

@@ -36,7 +36,8 @@ func (p *Paragraph) AddInlineDrawing(pic []byte) (*Run, error) {
return nil, err return nil, err
} }
idn := int(atomic.AddUintptr(&p.file.docID, 1)) idn := int(atomic.AddUintptr(&p.file.docID, 1))
id := strconv.Itoa(int(p.file.IncreaseID("图片"))) id := int(p.file.IncreaseID("图片"))
ids := strconv.Itoa(id)
rid := p.file.addImage(format, pic) rid := p.file.addImage(format, pic)
w, h := int64(sz.Width), int64(sz.Height) w, h := int64(sz.Width), int64(sz.Height)
if float64(w)/float64(h) > 1.2 { if float64(w)/float64(h) > 1.2 {
@@ -58,7 +59,7 @@ func (p *Paragraph) AddInlineDrawing(pic []byte) (*Run, error) {
EffectExtent: &WPEffectExtent{}, EffectExtent: &WPEffectExtent{},
DocPr: &WPDocPr{ DocPr: &WPDocPr{
ID: idn, ID: idn,
Name: "图片 " + id, Name: "图片 " + ids,
}, },
CNvGraphicFramePr: &WPCNvGraphicFramePr{ CNvGraphicFramePr: &WPCNvGraphicFramePr{
Locks: AGraphicFrameLocks{ Locks: AGraphicFrameLocks{
@@ -72,9 +73,9 @@ func (p *Paragraph) AddInlineDrawing(pic []byte) (*Run, error) {
Pic: &Picture{ Pic: &Picture{
XMLPIC: XMLNS_DRAWINGML_PICTURE, XMLPIC: XMLNS_DRAWINGML_PICTURE,
NonVisualPicProperties: &PICNonVisualPicProperties{ NonVisualPicProperties: &PICNonVisualPicProperties{
NonVisualDrawingProperties: PICNonVisualDrawingProperties{ NonVisualDrawingProperties: NonVisualProperties{
ID: id, ID: id,
Name: "图片 " + id, Name: "图片 " + ids,
}, },
}, },
BlipFill: &PICBlipFill{ BlipFill: &PICBlipFill{
@@ -137,7 +138,8 @@ func (p *Paragraph) AddAnchorDrawing(pic []byte) (*Run, error) {
return nil, err return nil, err
} }
idn := int(atomic.AddUintptr(&p.file.docID, 1)) idn := int(atomic.AddUintptr(&p.file.docID, 1))
id := strconv.Itoa(int(p.file.IncreaseID("图片"))) id := int(p.file.IncreaseID("图片"))
ids := strconv.Itoa(id)
rid := p.file.addImage(format, pic) rid := p.file.addImage(format, pic)
w, h := int64(sz.Width), int64(sz.Height) w, h := int64(sz.Width), int64(sz.Height)
if float64(w)/float64(h) > 1.2 { if float64(w)/float64(h) > 1.2 {
@@ -168,7 +170,7 @@ func (p *Paragraph) AddAnchorDrawing(pic []byte) (*Run, error) {
WrapNone: &struct{}{}, WrapNone: &struct{}{},
DocPr: &WPDocPr{ DocPr: &WPDocPr{
ID: idn, ID: idn,
Name: "图片 " + id, Name: "图片 " + ids,
}, },
CNvGraphicFramePr: &WPCNvGraphicFramePr{ CNvGraphicFramePr: &WPCNvGraphicFramePr{
Locks: AGraphicFrameLocks{ Locks: AGraphicFrameLocks{
@@ -182,9 +184,9 @@ func (p *Paragraph) AddAnchorDrawing(pic []byte) (*Run, error) {
Pic: &Picture{ Pic: &Picture{
XMLPIC: XMLNS_DRAWINGML_PICTURE, XMLPIC: XMLNS_DRAWINGML_PICTURE,
NonVisualPicProperties: &PICNonVisualPicProperties{ NonVisualPicProperties: &PICNonVisualPicProperties{
NonVisualDrawingProperties: PICNonVisualDrawingProperties{ NonVisualDrawingProperties: NonVisualProperties{
ID: id, ID: id,
Name: "图片 " + id, Name: "图片 " + ids,
}, },
}, },
BlipFill: &PICBlipFill{ BlipFill: &PICBlipFill{

View File

@@ -49,7 +49,7 @@ func (p *Paragraph) AddInlineShape(w, h int64, name, bwMode, prst string, ln *AL
CNvCnPr: &WPSCNvCnPr{ CNvCnPr: &WPSCNvCnPr{
ConnShapeLocks: &struct{}{}, ConnShapeLocks: &struct{}{},
}, },
SpPr: &WPSSpPr{ SpPr: &ShapeProperties{
BWMode: bwMode, BWMode: bwMode,
Xfrm: AXfrm{ Xfrm: AXfrm{
@@ -116,7 +116,7 @@ func (p *Paragraph) AddAnchorShape(w, h int64, name, bwMode, prst string, ln *AL
CNvCnPr: &WPSCNvCnPr{ CNvCnPr: &WPSCNvCnPr{
ConnShapeLocks: &struct{}{}, ConnShapeLocks: &struct{}{},
}, },
SpPr: &WPSSpPr{ SpPr: &ShapeProperties{
BWMode: bwMode, BWMode: bwMode,
Xfrm: AXfrm{ Xfrm: AXfrm{

View File

@@ -417,15 +417,25 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type AGraphicData struct { type AGraphicData struct {
XMLName xml.Name `xml:"a:graphicData,omitempty"` XMLName xml.Name `xml:"a:graphicData,omitempty"`
URI string `xml:"uri,attr"` URI string `xml:"uri,attr"`
Pic *Picture
Shape *WordprocessingShape Pic *Picture
Canvas *WordprocessingCanvas Shape *WordprocessingShape
Canvas *WordprocessingCanvas
Group *WordprocessingGroup
file *Docx file *Docx
} }
// UnmarshalXML ... // UnmarshalXML ...
func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "uri":
a.URI = attr.Value
default:
// ignore other attributes
}
}
for { for {
t, err := d.Token() t, err := d.Token()
if err == io.EOF { if err == io.EOF {
@@ -461,6 +471,14 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
return err return err
} }
a.Canvas = &value a.Canvas = &value
case "wgp":
var value WordprocessingGroup
value.file = a.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
a.Group = &value
default: default:
err = d.Skip() // skip unsupported tags err = d.Skip() // skip unsupported tags
if err != nil { if err != nil {
@@ -530,8 +548,8 @@ func (p *Picture) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// PICNonVisualPicProperties represents the non-visual properties of a picture in a Word document. // PICNonVisualPicProperties represents the non-visual properties of a picture in a Word document.
type PICNonVisualPicProperties struct { type PICNonVisualPicProperties struct {
XMLName xml.Name `xml:"pic:nvPicPr,omitempty"` XMLName xml.Name `xml:"pic:nvPicPr,omitempty"`
NonVisualDrawingProperties PICNonVisualDrawingProperties NonVisualDrawingProperties NonVisualProperties `xml:"pic:cNvPr,omitempty"`
CNvPicPr PicCNvPicPr CNvPicPr PicCNvPicPr
} }
@@ -549,7 +567,14 @@ func (p *PICNonVisualPicProperties) UnmarshalXML(d *xml.Decoder, start xml.Start
if tt, ok := t.(xml.StartElement); ok { if tt, ok := t.(xml.StartElement); ok {
switch tt.Name.Local { switch tt.Name.Local {
case "cNvPr": case "cNvPr":
p.NonVisualDrawingProperties.ID = getAtt(tt.Attr, "id") v := getAtt(tt.Attr, "id")
if v == "" {
continue
}
p.NonVisualDrawingProperties.ID, err = strconv.Atoi(v)
if err != nil {
return err
}
p.NonVisualDrawingProperties.Name = getAtt(tt.Attr, "name") p.NonVisualDrawingProperties.Name = getAtt(tt.Attr, "name")
case "cNvPicPr": case "cNvPicPr":
err = d.DecodeElement(&p.CNvPicPr, &tt) err = d.DecodeElement(&p.CNvPicPr, &tt)
@@ -618,13 +643,6 @@ type APicLocks struct {
NoChangeAspect int `xml:"noChangeAspect,attr"` NoChangeAspect int `xml:"noChangeAspect,attr"`
} }
// PICNonVisualDrawingProperties represents the non-visual drawing properties of a picture in a Word document.
type PICNonVisualDrawingProperties struct {
XMLName xml.Name `xml:"pic:cNvPr,omitempty"`
ID string `xml:"id,attr"`
Name string `xml:"name,attr"`
}
// PICBlipFill represents the blip fill of a picture in a Word document. // PICBlipFill represents the blip fill of a picture in a Word document.
type PICBlipFill struct { type PICBlipFill struct {
XMLName xml.Name `xml:"pic:blipFill,omitempty"` XMLName xml.Name `xml:"pic:blipFill,omitempty"`

View File

@@ -20,7 +20,12 @@
package docx package docx
import "encoding/xml" import (
"encoding/xml"
"io"
"strconv"
"strings"
)
// RunStyle contains styling for a run // RunStyle contains styling for a run
type RunStyle struct { type RunStyle struct {
@@ -162,3 +167,107 @@ type OverflowPunct struct {
XMLName xml.Name `xml:"w:overflowPunct,omitempty"` XMLName xml.Name `xml:"w:overflowPunct,omitempty"`
Val int `xml:"w:val,attr"` Val int `xml:"w:val,attr"`
} }
// ShapeProperties is a container element that represents the visual properties of a shape.
type ShapeProperties struct {
BWMode string `xml:"bwMode,attr"`
Xfrm AXfrm
PrstGeom APrstGeom
SolidFill *ASolidFill
BlipFill *ABlipFill
NoFill *struct{} `xml:"a:noFill,omitempty"`
Line *ALine
// EffectList struct{} `xml:"a:effectLst"`
// ExtList struct{} `xml:"a:extLst"`
}
// UnmarshalXML ...
func (w *ShapeProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "bwMode":
w.BWMode = attr.Value
default:
// ignore other attributes
}
}
for {
t, err := d.Token()
if err == io.EOF {
break
}
if err != nil {
return err
}
if tt, ok := t.(xml.StartElement); ok {
switch tt.Name.Local {
case "xfrm":
err = d.DecodeElement(&w.Xfrm, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
case "prstGeom":
w.PrstGeom.Prst = getAtt(tt.Attr, "prst")
case "solidFill":
var value ASolidFill
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.SolidFill = &value
case "blipFill":
var value ABlipFill
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.BlipFill = &value
case "noFill":
w.NoFill = &struct{}{}
case "ln":
var ln ALine
err = d.DecodeElement(&ln, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.Line = &ln
default:
err = d.Skip() // skip unsupported tags
if err != nil {
return err
}
continue
}
}
}
return nil
}
// NonVisualProperties is an element that represents the non-visual properties of a content control.
type NonVisualProperties struct {
ID int `xml:"id,attr"`
Name string `xml:"name,attr"`
}
// UnmarshalXML ...
func (r *NonVisualProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "id":
r.ID, err = strconv.Atoi(attr.Value)
if err != nil {
return
}
case "name":
r.Name = attr.Value
default:
// ignore other attributes
}
}
// Consume the end element
_, err = d.Token()
return
}

View File

@@ -30,8 +30,10 @@ import (
type WordprocessingGroup struct { type WordprocessingGroup struct {
XMLName xml.Name `xml:"wpg:wgp,omitempty"` XMLName xml.Name `xml:"wpg:wgp,omitempty"`
CNvGrpSpPr *WPGcNvGrpSpPr CNvGrpSpPr *WPGcNvGrpSpPr
GroupShapeProperties *WPGGroupShapeProperties GroupShapeProperties *ShapeProperties `xml:"wpg:grpSpPr,omitempty"`
Elems []interface{} Elems []interface{}
file *Docx
} }
// UnmarshalXML ... // UnmarshalXML ...
@@ -55,7 +57,7 @@ func (w *WordprocessingGroup) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
} }
w.CNvGrpSpPr = &value w.CNvGrpSpPr = &value
case "grpSpPr": case "grpSpPr":
var value WPGGroupShapeProperties var value ShapeProperties
err = d.DecodeElement(&value, &tt) err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") { if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err return err
@@ -70,6 +72,23 @@ func (w *WordprocessingGroup) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
w.Elems = append(w.Elems, &value) w.Elems = append(w.Elems, &value)
case "wsp": case "wsp":
var value WordprocessingShape var value WordprocessingShape
value.file = w.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.Elems = append(w.Elems, &value)
case "wpc":
var value WordprocessingCanvas
value.file = w.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.Elems = append(w.Elems, &value)
case "grpSp":
var value WPGGroupShape
value.file = w.file
err = d.DecodeElement(&value, &tt) err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") { if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err return err
@@ -129,8 +148,82 @@ type AGroupShapeLocks struct {
XMLName xml.Name `xml:"a:grpSpLocks,omitempty"` XMLName xml.Name `xml:"a:grpSpLocks,omitempty"`
} }
// WPGGroupShapeProperties represents the properties applied to a group shape. // WPGGroupShape ...
type WPGGroupShapeProperties struct { type WPGGroupShape struct {
XMLName xml.Name `xml:"wpg:grpSpPr,omitempty"` XMLName xml.Name `xml:"wpg:grpSp,omitempty"`
Xfrm *AXfrm CNvPr *NonVisualProperties `xml:"wpg:cNvPr,omitempty"`
CNvGrpSpPr *WPGcNvGrpSpPr
GroupShapeProperties *ShapeProperties `xml:"wpg:grpSpPr,omitempty"`
Elems []interface{}
file *Docx
}
// UnmarshalXML ...
func (w *WPGGroupShape) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
break
}
if err != nil {
return err
}
if tt, ok := t.(xml.StartElement); ok {
switch tt.Name.Local {
case "cNvPr":
var value NonVisualProperties
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.CNvPr = &value
case "cNvGrpSpPr":
var value WPGcNvGrpSpPr
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.CNvGrpSpPr = &value
case "grpSpPr":
var value ShapeProperties
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.GroupShapeProperties = &value
case "pic":
var value Picture
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.Elems = append(w.Elems, &value)
case "wsp":
var value WordprocessingShape
value.file = w.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.Elems = append(w.Elems, &value)
case "wpc":
var value WordprocessingCanvas
value.file = w.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.Elems = append(w.Elems, &value)
default:
err = d.Skip() // skip unsupported tags
if err != nil {
return err
}
continue
}
}
}
return nil
} }

View File

@@ -29,11 +29,11 @@ import (
// WordprocessingShape is a container for a WordprocessingML DrawingML shape. // WordprocessingShape is a container for a WordprocessingML DrawingML shape.
type WordprocessingShape struct { type WordprocessingShape struct {
XMLName xml.Name `xml:"wps:wsp,omitempty"` XMLName xml.Name `xml:"wps:wsp,omitempty"`
CNvPr *WPSCNvPr CNvPr *NonVisualProperties `xml:"wps:cNvPr,omitempty"`
CNvCnPr *WPSCNvCnPr CNvCnPr *WPSCNvCnPr
CNvSpPr *WPSCNvSpPr CNvSpPr *WPSCNvSpPr
SpPr *WPSSpPr SpPr *ShapeProperties `xml:"wps:spPr,omitempty"`
TextBox *WPSTextBox TextBox *WPSTextBox
BodyPr *WPSBodyPr BodyPr *WPSBodyPr
@@ -54,7 +54,7 @@ func (w *WordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
if tt, ok := t.(xml.StartElement); ok { if tt, ok := t.(xml.StartElement); ok {
switch tt.Name.Local { switch tt.Name.Local {
case "cNvPr": case "cNvPr":
w.CNvPr = new(WPSCNvPr) w.CNvPr = new(NonVisualProperties)
err = d.DecodeElement(w.CNvPr, &tt) err = d.DecodeElement(w.CNvPr, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") { if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err return err
@@ -72,7 +72,7 @@ func (w *WordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
return err return err
} }
case "spPr": case "spPr":
w.SpPr = new(WPSSpPr) w.SpPr = new(ShapeProperties)
err = d.DecodeElement(w.SpPr, &tt) err = d.DecodeElement(w.SpPr, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") { if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err return err
@@ -102,33 +102,6 @@ func (w *WordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
return nil return nil
} }
// WPSCNvPr is an element that represents the non-visual properties of a content control.
type WPSCNvPr struct {
XMLName xml.Name `xml:"wps:cNvPr,omitempty"`
ID int `xml:"id,attr"`
Name string `xml:"name,attr"`
}
// UnmarshalXML ...
func (r *WPSCNvPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "id":
r.ID, err = strconv.Atoi(attr.Value)
if err != nil {
return
}
case "name":
r.Name = attr.Value
default:
// ignore other attributes
}
}
// Consume the end element
_, err = d.Token()
return
}
// WPSCNvCnPr represents the non-visual drawing properties of a connector. // WPSCNvCnPr represents the non-visual drawing properties of a connector.
type WPSCNvCnPr struct { type WPSCNvCnPr struct {
XMLName xml.Name `xml:"wps:cNvCnPr,omitempty"` XMLName xml.Name `xml:"wps:cNvCnPr,omitempty"`
@@ -237,85 +210,6 @@ func (l *ASPLocks) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
return err return err
} }
// WPSSpPr is a container element that represents the visual properties of a shape.
type WPSSpPr struct {
XMLName xml.Name `xml:"wps:spPr,omitempty"`
BWMode string `xml:"bwMode,attr"`
Xfrm AXfrm
PrstGeom APrstGeom
SolidFill *ASolidFill
BlipFill *ABlipFill
NoFill *struct{} `xml:"a:noFill,omitempty"`
Line *ALine
// EffectList struct{} `xml:"a:effectLst"`
// ExtList struct{} `xml:"a:extLst"`
}
// UnmarshalXML ...
func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "bwMode":
w.BWMode = attr.Value
default:
// ignore other attributes
}
}
for {
t, err := d.Token()
if err == io.EOF {
break
}
if err != nil {
return err
}
if tt, ok := t.(xml.StartElement); ok {
switch tt.Name.Local {
case "xfrm":
err = d.DecodeElement(&w.Xfrm, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
case "prstGeom":
w.PrstGeom.Prst = getAtt(tt.Attr, "prst")
case "solidFill":
var value ASolidFill
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.SolidFill = &value
case "blipFill":
var value ABlipFill
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.BlipFill = &value
case "noFill":
w.NoFill = &struct{}{}
case "ln":
var ln ALine
err = d.DecodeElement(&ln, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
w.Line = &ln
default:
err = d.Skip() // skip unsupported tags
if err != nil {
return err
}
continue
}
}
}
return nil
}
// ABlipFill represents a fill that contains a reference to an image. // ABlipFill represents a fill that contains a reference to an image.
type ABlipFill struct { type ABlipFill struct {
XMLName xml.Name `xml:"a:blipFill,omitempty"` XMLName xml.Name `xml:"a:blipFill,omitempty"`