Documentation
¶
Overview ¶
Package docx 提供生成 OOXML WordprocessingML(.docx)所需的最小子集。
本包只负责写出,不解析 docx。结构体的字段按 ECMA-376 的 schema sequence 顺序声明,配合 encoding/xml 按字段顺序输出的行为,使生成顺序自动合法; order.go 的顺序常量表与 order_test.go 的反射断言共同保证这一点。
Index ¶
- Constants
- func EMU(mm float64) int
- func HalfPoints(pt float64) int
- func RowListMarker(row []textdoc.Entry) (string, bool)
- func StripListMarker(text string) string
- func Twips(mm float64) int
- func TwipsFromPoints(pt float64) int
- func Write(output io.Writer, options Options, build func(*Writer) error) error
- type AbstractNumbering
- type AdjustValueList
- type Blip
- type Block
- type BlockAnchor
- type BlockKind
- type Border
- type Columns
- type DocDefaults
- type DocProperties
- type Drawing
- type EffectExtent
- type Extent
- type FillRect
- type Graphic
- type GraphicData
- type GraphicFrameLocks
- type GraphicFramePr
- type GridColumn
- type Indent
- type Inline
- type Level
- type ListItem
- type Measure
- type NonVisualProperties
- type NumberInstance
- type NumberingProps
- type NumberingRoot
- type Offset
- type Options
- type PageMargin
- type PageOptions
- type PageSize
- type Paragraph
- type ParagraphProperties
- type Picture
- type PictureBlipFill
- type PictureNonVisual
- type PictureProperties
- type PresetShape
- type Run
- type RunFonts
- type RunProperties
- type SectionProperties
- type ShapeProperties
- type Spacing
- type Stretch
- type Style
- type Styles
- type Table
- type TableBorders
- type TableCell
- type TableCellProperties
- type TableGrid
- type TableProperties
- type TableRow
- type TableRowProperties
- type Text
- type Transform
- type TypeVal
- type Val
- type VerticalMerge
- type Writer
Constants ¶
const MaxImagesPerPage = 64
MaxImagesPerPage 限制单页内嵌的图片数量。整版图片类的 OFD(例如把每页当成 一张扫描图)会在这里被截断,避免长篇扫描件产出体量失控的 docx。
Variables ¶
This section is empty.
Functions ¶
func HalfPoints ¶
HalfPoints 把磅换算成 w:sz 使用的半磅单位。字号与长度不同,w:sz 取 2×pt, 直接传 twip 会让字号放大 10 倍(实测标题变成 160pt,一行放不下就竖排换行)。
func RowListMarker ¶
RowListMarker 返回行内第一个非空文字对象的文本。OFD 常把序号与正文拆成同一行 的多个文字对象,条目文字此时在第二个对象上,所以判定要看整行而不是单个对象。
func StripListMarker ¶
StripListMarker 去掉条目行首的序号或项目符号,只保留正文。真实列表里序号由 Word 自动渲染,留在正文里会显示两遍。
Types ¶
type AbstractNumbering ¶
type AbstractNumbering struct {
AbstractID int `xml:"w:abstractNumId,attr"`
Levels []*Level `xml:"w:lvl"`
}
AbstractNumbering 是 CT_AbstractNum。
type Blip ¶
type Blip struct {
Embed string `xml:"r:embed,attr"`
}
Blip 是 a:blip。Embed 带 r 前缀,指向 OPC 关系。
type Block ¶
type Block struct {
// Kind 决定用哪种写入方法渲染。
Kind BlockKind
// Image 是图片块携带的图片条目,其他块为 nil。
Image *textdoc.Image
// contains filtered or unexported fields
}
Block 是一个待写入 DOCX 的块。
func BlockSequence ¶
func BlockSequence(entries []textdoc.Entry, pageHeight float64, options PageOptions, images []textdoc.Image) []Block
BlockSequence 返回一页的块序列,图片按纵向锚点穿插在文字块之间。
type BlockAnchor ¶
type BlockAnchor float64
BlockAnchor 是块的纵向锚点(毫米,原点在页面左上角)。文字块取首行的 y,图片块取图片左上角的 y。块之间按该锚点排序,从而把图片穿插到页面上大致 相同的高度,而不是统统堆在文末。
type Border ¶
type Border struct {
Val string `xml:"w:val,attr"`
Size int `xml:"w:sz,attr"`
Color string `xml:"w:color,attr"`
}
Border 是 CT_Border。Color 是不带 # 的 RRGGBB。
type Columns ¶
type Columns struct {
Num int `xml:"w:num,attr,omitempty"`
Space int `xml:"w:space,attr,omitempty"`
}
Columns 是 CT_Columns。Num 为栏数,Space 为栏间距(twip)。
type DocDefaults ¶
type DocDefaults struct {
Runs *RunProperties `xml:"w:rPrDefault>w:rPr"`
}
DocDefaults 是 CT_DocDefaults,设定整篇的默认字号与中西文字体。
type DocProperties ¶
DocProperties 是 wp:docPr。ID 在全文唯一,Name 供辅助功能与替换图片时使用。
type EffectExtent ¶
type EffectExtent struct {
Left int `xml:"l,attr"`
Top int `xml:"t,attr"`
Right int `xml:"r,attr"`
Bottom int `xml:"b,attr"`
}
EffectExtent 是 wp:effectExtent,表示图片超出 extent 的部分。四项全为 0。
type Graphic ¶
type Graphic struct {
Data *GraphicData `xml:"a:graphicData"`
}
Graphic 是 a:graphic,graphicData 的 uri 声明这里放的是图片而不是图表或形状。
type GraphicData ¶
GraphicData 是 a:graphicData。
type GraphicFrameLocks ¶
type GraphicFrameLocks struct {
NoChangeAspect string `xml:"noChangeAspect,attr"`
}
GraphicFrameLocks 是 a:graphicFrameLocks。NoChangeAspect 是 ST_OnOff, 这里写 "1" 而不是 "true":两者在 Transitional 词法下都合法,但 Word 自己 写的是 "1",照抄可以少一类差异。
type GraphicFramePr ¶
type GraphicFramePr struct {
Locks *GraphicFrameLocks `xml:"a:graphicFrameLocks"`
}
GraphicFramePr 是 wp:cNvGraphicFramePr。锁定宽高比使 Word 缩放时不变形。
type GridColumn ¶
type GridColumn struct {
Width int `xml:"w:w,attr"`
}
GridColumn 是 CT_TblGridCol。宽度是 w:w 属性,不是元素文本。
type Indent ¶
type Indent struct {
Left *int `xml:"w:left,attr,omitempty"`
Right *int `xml:"w:right,attr,omitempty"`
FirstLine *int `xml:"w:firstLine,attr,omitempty"`
Hanging *int `xml:"w:hanging,attr,omitempty"`
}
Indent 是 CT_Ind,单位同样是 twip。FirstLine 与 Hanging 互斥。
type Inline ¶
type Inline struct {
DistanceTop int `xml:"distT,attr"`
DistanceBottom int `xml:"distB,attr"`
DistanceLeft int `xml:"distL,attr"`
DistanceRight int `xml:"distR,attr"`
Extent *Extent `xml:"wp:extent"`
EffectExtent *EffectExtent `xml:"wp:effectExtent"`
DocProperties *DocProperties `xml:"wp:docPr"`
FramePr *GraphicFramePr `xml:"wp:cNvGraphicFramePr"`
Graphic *Graphic `xml:"a:graphic"`
}
Inline 是 wp:inline。距离文档正文的距离用 EMU,图片不做浮雕等效果时全为 0。
type Level ¶
type Level struct {
Index int `xml:"w:ilvl,attr"`
Start *Val `xml:"w:start,omitempty"`
Format *Val `xml:"w:numFmt,omitempty"`
Text *Val `xml:"w:lvlText,omitempty"`
Justify *Val `xml:"w:lvlJc,omitempty"`
Properties *ParagraphProperties `xml:"w:pPr,omitempty"`
Runs *RunProperties `xml:"w:rPr,omitempty"`
}
Level 是 CT_Lvl。
type ListItem ¶
type ListItem struct {
// contains filtered or unexported fields
}
ListItem 是识别出的一个列表条目。
func DetectListItem ¶
DetectListItem 判断一行文字是否是列表条目,是则返回条目信息。
只看行首标记:条目序号一定出现在行首,而行内的顿号、括号、引号都不该被 当成序号。序号从 0 起的(「0.1mm」)在行级即可排除;「必须从 1 开始」是段级 要求,由 FilterCredibleListItems 校验。
func FilterCredibleListItems ¶
FilterCredibleListItems 只保留可信连续段里的条目,其余清空。
按段筛选而不是整页一刀切:一页里可能只有部分行构成列表,其余是巧合。实测 项目立项报告首页的「一、」「二、」与紧随其后的「1. 2. 3.」就是两个独立列表。
type NonVisualProperties ¶
NonVisualProperties 是 pic:cNvPr。
type NumberInstance ¶
type NumberInstance struct {
NumID int `xml:"w:numId,attr"`
AbstractID int `xml:"w:abstractNumId,attr"`
}
NumberInstance 是 CT_Num。
type NumberingProps ¶
type NumberingProps struct {
Level *Val `xml:"w:ilvl,omitempty"`
NumID *Val `xml:"w:numId,omitempty"`
}
NumberingProps 是 CT_NumPr,引用 numbering.xml 中某个 numId 的指定层级。
type NumberingRoot ¶
type NumberingRoot struct {
XMLName xml.Name `xml:"w:numbering"`
Namespace string `xml:"xmlns:w,attr"`
Abstract []*AbstractNumbering `xml:"w:abstractNum"`
Numbers []*NumberInstance `xml:"w:num"`
}
NumberingRoot 是 numbering.xml 的根。
type Options ¶
type Options struct {
// Title 与 Author 写入 docProps/core.xml。
Title string
Author string
PageWidth int
PageHeight int
// Landscape 为 true 时交换页宽页高并写入 w:orient="landscape"。
Landscape bool
MarginTop int
MarginRight int
MarginBottom int
MarginLeft int
// Columns 是分栏数,1 或 0 表示不分栏。
Columns int
}
Options 控制文档级设置。零值表示使用 A4 纵向与默认页边距。
type PageMargin ¶
type PageMargin struct {
Top int `xml:"w:top,attr"`
Right int `xml:"w:right,attr"`
Bottom int `xml:"w:bottom,attr"`
Left int `xml:"w:left,attr"`
Header int `xml:"w:header,attr,omitempty"`
Gutter int `xml:"w:gutter,attr,omitempty"`
}
PageMargin 是 CT_PageMar,单位 twip。
type PageOptions ¶
type PageOptions struct {
// Tables 决定是否按位置识别表格。
Tables bool
// Annotations 决定是否保留批注层文字。批注承载的是叠加在正文上的标记
// ——整页水印、电子印章、签章位置——默认应当剔除。
Annotations bool
}
PageOptions 是一页 DOCX 输出的开关。
type PageSize ¶
type PageSize struct {
Width int `xml:"w:w,attr"`
Height int `xml:"w:h,attr"`
Orient string `xml:"w:orient,attr,omitempty"`
}
PageSize 是 CT_PageSz,单位 twip。Orient 取 "portrait"/"landscape"。
type Paragraph ¶
type Paragraph struct {
Properties *ParagraphProperties `xml:"w:pPr,omitempty"`
Runs []Run `xml:"w:r"`
}
Paragraph 是 w:p。
type ParagraphProperties ¶
type ParagraphProperties struct {
Style *Val `xml:"w:pStyle,omitempty"`
Numbering *NumberingProps `xml:"w:numPr,omitempty"`
Spacing *Spacing `xml:"w:spacing,omitempty"`
Indent *Indent `xml:"w:ind,omitempty"`
Justification *Val `xml:"w:jc,omitempty"`
OutlineLevel *Val `xml:"w:outlineLvl,omitempty"`
}
ParagraphProperties 是 CT_PPr。
type Picture ¶
type Picture struct {
NonVisual *PictureNonVisual `xml:"pic:nvPicPr"`
Fill *PictureBlipFill `xml:"pic:blipFill"`
Properties *ShapeProperties `xml:"pic:spPr"`
}
Picture 是 pic:pic。
type PictureBlipFill ¶
PictureBlipFill 是 pic:blipFill。Embed 是指向 word/media 条目的关系 ID。
type PictureNonVisual ¶
type PictureNonVisual struct {
Properties *NonVisualProperties `xml:"pic:cNvPr"`
PictureProps *PictureProperties `xml:"pic:cNvPicPr"`
}
PictureNonVisual 是 pic:nvPicPr。
type PresetShape ¶
type PresetShape struct {
Preset string `xml:"prst,attr"`
List *AdjustValueList `xml:"a:avLst"`
}
PresetShape 是 a:prstGeom。图片一律是矩形。
type Run ¶
type Run struct {
Properties *RunProperties `xml:"w:rPr,omitempty"`
Text *Text `xml:"w:t,omitempty"`
Drawing *Drawing `xml:"w:drawing,omitempty"`
}
Run 是 w:r。一段 run 要么承载文字,要么承载图片,两者互斥,所以两个子元素 都是指针:只写一个才是合法形状。
type RunFonts ¶
type RunFonts struct {
ASCII string `xml:"w:ascii,attr,omitempty"`
EastAsia string `xml:"w:eastAsia,attr,omitempty"`
}
RunFonts 是 CT_Fonts,只用 ascii 与 eastAsia 两个槽位:西文与中日韩分别交给 打开方的系统字体解析。OFD 侧的 FontName 直接写入这里,不嵌入字体文件。
type RunProperties ¶
type RunProperties struct {
Fonts *RunFonts `xml:"w:rFonts,omitempty"`
Bold *Val `xml:"w:b,omitempty"`
Italic *Val `xml:"w:i,omitempty"`
Color *Val `xml:"w:color,omitempty"`
// Size 是半磅(half-point)为单位的字号,即 2×pt。
Size *Val `xml:"w:sz,omitempty"`
}
RunProperties 是 CT_RPr。
type SectionProperties ¶
type SectionProperties struct {
PageSize *PageSize `xml:"w:pgSz,omitempty"`
PageMargin *PageMargin `xml:"w:pgMar,omitempty"`
Columns *Columns `xml:"w:cols,omitempty"`
}
SectionProperties 是 CT_SectPr,描述最后一节的页面设置。
type ShapeProperties ¶
type ShapeProperties struct {
Transform *Transform `xml:"a:xfrm"`
Geometry *PresetShape `xml:"a:prstGeom"`
}
ShapeProperties 是 pic:spPr。
type Spacing ¶
type Spacing struct {
Before *int `xml:"w:before,attr,omitempty"`
After *int `xml:"w:after,attr,omitempty"`
Line *int `xml:"w:line,attr,omitempty"`
// LineRule 取 "auto"(行距倍数)或 "exact"/"atLeast"(绝对行高)。
LineRule string `xml:"w:lineRule,attr,omitempty"`
}
Spacing 是 CT_Spacing,单位为二十分之一磅(twip)。
type Stretch ¶
type Stretch struct {
Rect *FillRect `xml:"a:fillRect"`
}
Stretch 是 a:stretch,FillRect 让图片填满 extent。
type Style ¶
type Style struct {
Type string `xml:"w:type,attr"`
StyleID string `xml:"w:styleId,attr"`
Name *Val `xml:"w:name,omitempty"`
BasedOn *Val `xml:"w:basedOn,omitempty"`
Next *Val `xml:"w:next,omitempty"`
Properties *ParagraphProperties `xml:"w:pPr,omitempty"`
Runs *RunProperties `xml:"w:rPr,omitempty"`
// Default 标记该类型的默认样式,同一类型只能有一个。
Default bool `xml:"w:default,attr,omitempty"`
// Custom 标记自定义样式,避免 Word 把它当未知内置样式丢弃。
Custom bool `xml:"w:customStyle,attr,omitempty"`
}
Style 是 CT_Style。Type 与 StyleID 是本元素的属性,而 w:name、w:basedOn、 w:next 都是子元素(<w:basedOn w:val="Normal"/>),形状相似容易写反。
type Styles ¶
type Styles struct {
XMLName xml.Name `xml:"w:styles"`
Namespace string `xml:"xmlns:w,attr"`
Defaults *DocDefaults `xml:"w:docDefaults,omitempty"`
List []Style `xml:"w:style"`
}
Styles 是 CT_Styles。XMLName 与 Namespace 让本类型可作为独立 part 序列化。
type Table ¶
type Table struct {
Properties *TableProperties `xml:"w:tblPr,omitempty"`
Grid *TableGrid `xml:"w:tblGrid,omitempty"`
Rows []TableRow `xml:"w:tr"`
}
Table 是 w:tbl。Grid 给出各列宽度(twip),必须与每行的单元格数一致。
type TableBorders ¶
type TableBorders struct {
Top *Border `xml:"w:top,omitempty"`
Left *Border `xml:"w:left,omitempty"`
Bottom *Border `xml:"w:bottom,omitempty"`
Right *Border `xml:"w:right,omitempty"`
InsideH *Border `xml:"w:insideH,omitempty"`
InsideV *Border `xml:"w:insideV,omitempty"`
}
TableBorders 是 CT_TblBorders。Size 单位是八分之一磅,Val 取边框样式名。
type TableCell ¶
type TableCell struct {
Properties *TableCellProperties `xml:"w:tcPr,omitempty"`
Paragraphs []Paragraph `xml:"w:p"`
}
TableCell 是 w:tc。ColumnSpan 与 RowSpan 输出为 w:gridSpan 与 w:vMerge。
type TableCellProperties ¶
type TableCellProperties struct {
Width *Measure `xml:"w:tcW,omitempty"`
ColumnSpan *Val `xml:"w:gridSpan,omitempty"`
RowSpan *VerticalMerge `xml:"w:vMerge,omitempty"`
Vertical *Val `xml:"w:vAlign,omitempty"`
}
TableCellProperties 是 CT_TcPr。
type TableGrid ¶
type TableGrid struct {
Columns []GridColumn `xml:"w:gridCol"`
}
TableGrid 是 w:tblGrid,声明各列宽度。OOXML 的列宽同时出现在 w:tblGrid 的 w:gridCol/@w:w 和 w:tc/w:tcPr/w:tcW/@w:w 两处,Word 以 tblGrid 为准。
func NewTableGrid ¶
NewTableGrid 由各列宽度(twip)构造 w:tblGrid。
type TableProperties ¶
type TableProperties struct {
Style string `xml:"w:tblStyle,attr,omitempty"`
Width *Measure `xml:"w:tblW"`
Borders *TableBorders `xml:"w:tblBorders,omitempty"`
// Layout 取 "fixed" 时严格按 w:tblGrid 分列,"autofit" 时由 Word 重算列宽。
Layout *TypeVal `xml:"w:tblLayout,omitempty"`
// Look 是 CT_TblLook 的十六进制开关位串,例如 "04A0" 表示首行与带状行开启。
Look *Val `xml:"w:tblLook,omitempty"`
}
TableProperties 是 CT_TblPr。
注意 w:tblStyle 是本元素的属性,而 w:tblLayout 与 w:tblLook 是子元素 (<w:tblLayout w:type="fixed"/>)。实测踩过:把 w:tblLayout 写成属性后 LibreOffice 会输出 <w:tblPr w:tblLayout="fixed">,表格之后的分页符随之失效。
type TableRow ¶
type TableRow struct {
Properties *TableRowProperties `xml:"w:trPr,omitempty"`
Cells []TableCell `xml:"w:tc"`
}
TableRow 是 w:tr。
type TableRowProperties ¶
type TableRowProperties struct {
TableHeader *Val `xml:"w:tblHeader,omitempty"`
}
TableRowProperties 是 CT_TrPr 的最小子集:只用到「跨页重复表头」。
type Text ¶
Text 是 w:t 的内容模型。固定带 xml:space="preserve",否则 Word 会吞掉 OFD 文本里行首行尾的有意义空格。不能直接写成 Run 里的 string 字段——Go 会把属性 提升到外层元素,变成 <w:r xml:space="preserve">,位置就错了。
type TypeVal ¶
type TypeVal struct {
Value string `xml:"w:type,attr"`
}
TypeVal 是「元素 + 单个 w:type 属性」的形态。多数简单类型用 w:val,但 w:tblLayout 用的是 w:type,两者不能互换,写错 Word 会忽略整个元素并退回 自动布局。
type Val ¶
type Val struct {
Value string `xml:"w:val,attr"`
}
Val 是「元素 + 单个 w:val 属性」的通用形态。OOXML 里 ST_String、 ST_DecimalNumber、ST_OnOff 都是把值原样写成文本,Go 不需要区分, 因此统一用字符串承载,由下面的构造函数在调用点转换。
type VerticalMerge ¶
type VerticalMerge struct {
Restart *Val `xml:"w:val,attr,omitempty"`
}
VerticalMerge 是 CT_VMerge。Restart 为 true 表示开启一段新的纵向合并区。
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer 逐块写出 word/document.xml。
.docx 是 ZIP 容器、需要中央目录,所以无法像 PDF 那样边生成边落盘, 由 Write 在内部管理 ZIP 生命周期,调用方通过 build 回调追加内容。
func (*Writer) AddImage ¶
AddImage 内嵌一张图片并返回一个只含该图片的段落。
data 是图片的原始编码字节(PNG/JPEG 等),extension 是不含点的扩展名, 决定 MIME 类型与 word/media 里的文件名;widthMM 与 heightMM 是显示尺寸 (毫米),由调用方按图片在页面上的 Boundary 给出。
部件在调用时立刻写入 ZIP,条目名与关系 ID 都按顺序确定,因此文档关系表 与 [Content_Types].xml 的图片声明都可以在 build 结束后一次性写完。
func (*Writer) AddParagraph ¶
AddParagraph 追加一个段落。
不含任何 w:r 的段落会被跳过:整行只有空白时 trim 后不剩内容,产出的是没有 文字的空段落,对版面没有贡献却会在 Word 里占一行。分页符段落自带 w:r, 不受影响。