diff --git a/apitable.go b/apitable.go index 4db86f4..8088136 100644 --- a/apitable.go +++ b/apitable.go @@ -2,11 +2,6 @@ package docxlib import "unsafe" -//nolint:revive,stylecheck -const ( - TABLE_STYLE = "a3" -) - // AddTable add a new table to body by col*row // // unit: twips (1/20 point) @@ -31,15 +26,14 @@ func (f *Docx) AddTable(row int, col int) *WTable { defer f.Document.Body.mu.Unlock() f.Document.Body.Items = append(f.Document.Body.Items, WTable{ TableProperties: &WTableProperties{ - Style: &WTableStyle{Val: TABLE_STYLE}, Width: &WTableWidth{Type: "auto"}, TableBorders: &WTableBorders{ - Top: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - Left: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - Bottom: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - Right: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - InsideH: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - InsideV: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, + Top: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + Left: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + Bottom: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + Right: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + InsideH: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + InsideV: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, }, Look: &WTableLook{ Val: "0000", @@ -57,7 +51,7 @@ func (f *Docx) AddTable(row int, col int) *WTable { // AddTableTwips add a new table to body by height and width // // unit: twips (1/20 point) -func (f *Docx) AddTableTwips(colWidths []int64, rowHeights []int64) *WTable { +func (f *Docx) AddTableTwips(rowHeights []int64, colWidths []int64) *WTable { grids := make([]*WGridCol, len(colWidths)) trs := make([]*WTableRow, len(rowHeights)) for i, w := range colWidths { @@ -69,10 +63,10 @@ func (f *Docx) AddTableTwips(colWidths []int64, rowHeights []int64) *WTable { } for i, h := range rowHeights { cells := make([]*WTableCell, len(colWidths)) - for i := range cells { + for i, w := range colWidths { cells[i] = &WTableCell{ TableCellProperties: &WTableCellProperties{ - TableCellWidth: &WTableCellWidth{Type: "auto"}, + TableCellWidth: &WTableCellWidth{W: w, Type: "dxa"}, }, file: f, } @@ -91,15 +85,14 @@ func (f *Docx) AddTableTwips(colWidths []int64, rowHeights []int64) *WTable { defer f.Document.Body.mu.Unlock() f.Document.Body.Items = append(f.Document.Body.Items, WTable{ TableProperties: &WTableProperties{ - Style: &WTableStyle{Val: TABLE_STYLE}, Width: &WTableWidth{Type: "auto"}, TableBorders: &WTableBorders{ - Top: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - Left: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - Bottom: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - Right: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - InsideH: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, - InsideV: &WTableBorder{Val: "single", Size: "4", Space: "0", Color: "000000"}, + Top: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + Left: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + Bottom: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + Right: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + InsideH: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, + InsideV: &WTableBorder{Val: "single", Size: 4, Space: 0, Color: "000000"}, }, Look: &WTableLook{ Val: "0000", diff --git a/cmd/main/main.go b/cmd/main/main.go index 198bb6a..a836c83 100644 --- a/cmd/main/main.go +++ b/cmd/main/main.go @@ -13,7 +13,6 @@ import ( func main() { fileLocation := flag.String("f", "new-file.docx", "file location") analyzeOnly := flag.Bool("a", false, "analyze file only") - verbose := flag.Bool("v", false, "verbose mode") unm := flag.Bool("u", false, "lease unmarshalled file") flag.Parse() var w *docxlib.Docx @@ -71,10 +70,20 @@ func main() { tbl1 := w.AddTable(3, 2) for x, r := range tbl1.TableRows { + for y, c := range r.TableCells { + c.AddParagraph().AddText(fmt.Sprintf("(%d, %d)", x, y)) + } + } + + w.AddParagraph() + + tbl2 := w.AddTableTwips([]int64{2333, 2333, 2333}, []int64{2333, 2333}) + for x, r := range tbl2.TableRows { for y, c := range r.TableCells { c.AddParagraph().Justification("center").AddText(fmt.Sprintf("(%d, %d)", x, y)) } } + f, err := os.Create(*fileLocation) if err != nil { panic(err) @@ -104,52 +113,6 @@ func main() { if err != nil { panic(err) } - if *verbose { - for _, it := range doc.Document.Body.Items { - switch para := it.(type) { - case docxlib.Paragraph: - fmt.Println("New paragraph") - for _, child := range para.Children { - switch o := child.(type) { - case *docxlib.Run: - if o.Text != nil { - fmt.Printf("\tWe've found a new run with the text ->%s\n", o.Text.Text) - } - if o.Drawing != nil { - if o.Drawing.Inline != nil { - fmt.Printf("\tWe've found a new run with the inline drawing ->%s\n", o.Drawing.Inline.DocPr.Name) - } - if o.Drawing.Anchor != nil { - fmt.Printf("\tWe've found a new run with the anchor drawing ->%s\n", o.Drawing.Anchor.DocPr.Name) - } - } - case *docxlib.Hyperlink: - id := o.ID - text := o.Run.InstrText - link, err := doc.ReferTarget(id) - if err != nil { - fmt.Printf("\tWe found a link with id %s and text %s without target\n", id, text) - } else { - fmt.Printf("\tWe've found a new hyperlink with ref %s and the text %s\n", link, text) - } - } - } - fmt.Print("End of paragraph\n\n") - case docxlib.WTable: - fmt.Println("New table") - for x, r := range para.TableRows { - fmt.Printf("[%d] ", x) - for y, c := range r.TableCells { - fmt.Printf("<%d> %s\t", y, c.Paragraphs[0].Children[0].(*docxlib.Run).Text.Text) - } - fmt.Print("\n") - } - fmt.Print("End of table\n\n") - } - - } - - } if *unm { i := strings.LastIndex(*fileLocation, "/") name := (*fileLocation)[:i+1] + "unmarshal_" + (*fileLocation)[i+1:] diff --git a/structpara.go b/structpara.go index ff1228c..9245211 100644 --- a/structpara.go +++ b/structpara.go @@ -77,28 +77,50 @@ func (p *Paragraph) String() string { case o.Text != nil: sb.WriteString(o.Text.Text) case o.Drawing != nil: - if o.Drawing.Inline != nil { - sb.WriteString("![inline image: ") - tgt, err := p.file.ReferTarget(o.Drawing.Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) - if err != nil { - sb.WriteString(err.Error()) - } else { - h := md5.Sum(p.file.Media(tgt[6:]).Data) - sb.WriteString(hex.EncodeToString(h[:])) + if o.Drawing.Inline != nil && o.Drawing.Inline.Graphic != nil && o.Drawing.Inline.Graphic.GraphicData != nil && o.Drawing.Inline.Graphic.GraphicData.Pic != nil { + sb.WriteString("![inlnim ") + switch { + case o.Drawing.Inline.DocPr != nil: + sb.WriteString(o.Drawing.Inline.DocPr.Name) + case o.Drawing.Inline.Graphic.GraphicData.Pic.NonVisualPicProperties != nil: + sb.WriteString(o.Drawing.Inline.Graphic.GraphicData.Pic.NonVisualPicProperties.NonVisualDrawingProperties.Name) + default: + sb.WriteString(o.Drawing.Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) } - sb.WriteString("]()") + sb.WriteString("](") + if o.Drawing.Inline.Graphic.GraphicData.Pic.BlipFill != nil { + tgt, err := p.file.ReferTarget(o.Drawing.Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) + if err != nil { + sb.WriteString(err.Error()) + } else { + h := md5.Sum(p.file.Media(tgt[6:]).Data) + sb.WriteString(hex.EncodeToString(h[:])) + } + } + sb.WriteByte(')') continue } - if o.Drawing.Anchor != nil { - sb.WriteString("![anchor image: ") - tgt, err := p.file.ReferTarget(o.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) - if err != nil { - sb.WriteString(err.Error()) - } else { - h := md5.Sum(p.file.Media(tgt[6:]).Data) - sb.WriteString(hex.EncodeToString(h[:])) + if o.Drawing.Anchor != nil && o.Drawing.Anchor.Graphic != nil && o.Drawing.Anchor.Graphic.GraphicData != nil && o.Drawing.Anchor.Graphic.GraphicData.Pic != nil { + sb.WriteString("![anchim ") + switch { + case o.Drawing.Anchor.DocPr != nil: + sb.WriteString(o.Drawing.Anchor.DocPr.Name) + case o.Drawing.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties != nil: + sb.WriteString(o.Drawing.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties.NonVisualDrawingProperties.Name) + default: + sb.WriteString(o.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) } - sb.WriteString("]()") + sb.WriteString("](") + if o.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill != nil { + tgt, err := p.file.ReferTarget(o.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) + if err != nil { + sb.WriteString(err.Error()) + } else { + h := md5.Sum(p.file.Media(tgt[6:]).Data) + sb.WriteString(hex.EncodeToString(h[:])) + } + } + sb.WriteByte(')') } } case *RunProperties: diff --git a/structtable.go b/structtable.go index 324f38c..1e323ba 100644 --- a/structtable.go +++ b/structtable.go @@ -265,7 +265,7 @@ func (t *WTableGrid) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error // WGridCol is a structure that represents a table grid column of a Word document. type WGridCol struct { XMLName xml.Name `xml:"w:gridCol,omitempty"` - W int64 `xml:"w,attr"` + W int64 `xml:"w:w,attr"` } // UnmarshalXML ... @@ -534,8 +534,8 @@ func (r *WTableCellProperties) UnmarshalXML(d *xml.Decoder, start xml.StartEleme // 不同的取值对应着不同的宽度计量单位和宽度定义方式。 type WTableCellWidth struct { XMLName xml.Name `xml:"w:tcW,omitempty"` - W int64 `xml:"w,attr"` - Type string `xml:"type,attr"` + W int64 `xml:"w:w,attr"` + Type string `xml:"w:type,attr"` } // WTableBorders is a structure representing the borders of a Word table. @@ -617,20 +617,49 @@ func (w *WTableBorders) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err // WTableBorder is a structure representing a single border of a Word table. type WTableBorder struct { - Val string `xml:"val,attr"` - Size string `xml:"sz,attr"` - Space string `xml:"space,attr"` - Color string `xml:"color,attr"` + Val string `xml:"w:val,attr"` + Size int `xml:"w:sz,attr"` + Space int `xml:"w:space,attr"` + Color string `xml:"w:color,attr"` +} + +func (t *WTableBorder) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + for _, attr := range start.Attr { + switch attr.Name.Local { + case "val": + t.Val = attr.Value + case "sz": + sz, err := strconv.Atoi(attr.Value) + if err != nil { + return err + } + t.Size = sz + case "space": + space, err := strconv.Atoi(attr.Value) + if err != nil { + return err + } + t.Space = space + case "color": + t.Color = attr.Value + } + } + // Consume the end element + _, err := d.Token() + if err != nil { + return err + } + return nil } // WGridSpan represents the number of grid columns this cell should span. type WGridSpan struct { XMLName xml.Name `xml:"w:gridSpan,omitempty"` - Val int `xml:"val,attr"` + Val int `xml:"w:val,attr"` } // WVerticalAlignment represents the vertical alignment of the content of a cell. type WVerticalAlignment struct { XMLName xml.Name `xml:"w:vAlign,omitempty"` - Val string `xml:"val,attr"` + Val string `xml:"w:val,attr"` }