🎨 Refactored XML generation logic and fixed content type override issues

This commit is contained in:
2025-04-16 17:29:40 +08:00
parent af9b26fa6c
commit 6b4be90900
8 changed files with 343 additions and 318 deletions

View File

@@ -130,7 +130,19 @@ func (b *Body) ToXML() string {
}
// 添加节属性
xml += "<w:sectPr>"
xml += "<w:sectPr xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
// 页眉引用
for _, headerRef := range b.SectionProperties.HeaderReference {
xml += fmt.Sprintf("<w:headerReference w:type=\"%s\" r:id=\"%s\" />",
headerRef.Type, headerRef.ID)
}
// 页脚引用
for _, footerRef := range b.SectionProperties.FooterReference {
xml += fmt.Sprintf("<w:footerReference w:type=\"%s\" r:id=\"%s\" />",
footerRef.Type, footerRef.ID)
}
// 页面大小
if b.SectionProperties.PageSize != nil {
@@ -165,18 +177,6 @@ func (b *Body) ToXML() string {
b.SectionProperties.DocGrid.LinePitch)
}
// 页眉引用
for _, headerRef := range b.SectionProperties.HeaderReference {
xml += fmt.Sprintf("<w:headerReference w:type=\"%s\" r:id=\"%s\" />",
headerRef.Type, headerRef.ID)
}
// 页脚引用
for _, footerRef := range b.SectionProperties.FooterReference {
xml += fmt.Sprintf("<w:footerReference w:type=\"%s\" r:id=\"%s\" />",
footerRef.Type, footerRef.ID)
}
xml += "</w:sectPr>"
xml += "</w:body>"

View File

@@ -59,7 +59,7 @@ func (f *Footer) AddTable(rows, cols int) *Table {
// ToXML 将页眉转换为XML
func (h *Header) ToXML() string {
xml := "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
xml += "<w:hdr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">"
xml += "<w:hdr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
// 添加所有内容元素的XML
for _, content := range h.Content {
@@ -78,7 +78,7 @@ func (h *Header) ToXML() string {
// ToXML 将页脚转换为XML
func (f *Footer) ToXML() string {
xml := "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
xml += "<w:ftr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">"
xml += "<w:ftr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"
// 添加所有内容元素的XML
for _, content := range f.Content {

View File

@@ -186,43 +186,12 @@ func (p *Paragraph) ToXML() string {
// 添加段落属性
xml += "<w:pPr>"
// 对齐方式
if p.Properties.Alignment != "" {
xml += "<w:jc w:val=\"" + p.Properties.Alignment + "\" />"
// 样式 (必须在最前面)
if p.Properties.StyleID != "" {
xml += fmt.Sprintf("<w:pStyle w:val=\"%s\" />", p.Properties.StyleID)
}
// 缩进
if p.Properties.IndentLeft > 0 || p.Properties.IndentRight > 0 || p.Properties.IndentFirstLine > 0 {
xml += "<w:ind"
if p.Properties.IndentLeft > 0 {
xml += " w:left=\"" + fmt.Sprintf("%d", p.Properties.IndentLeft) + "\""
}
if p.Properties.IndentRight > 0 {
xml += " w:right=\"" + fmt.Sprintf("%d", p.Properties.IndentRight) + "\""
}
if p.Properties.IndentFirstLine > 0 {
xml += " w:firstLine=\"" + fmt.Sprintf("%d", p.Properties.IndentFirstLine) + "\""
}
xml += " />"
}
// 间距
if p.Properties.SpacingBefore > 0 || p.Properties.SpacingAfter > 0 || p.Properties.SpacingLine > 0 {
xml += "<w:spacing"
if p.Properties.SpacingBefore > 0 {
xml += " w:before=\"" + fmt.Sprintf("%d", p.Properties.SpacingBefore) + "\""
}
if p.Properties.SpacingAfter > 0 {
xml += " w:after=\"" + fmt.Sprintf("%d", p.Properties.SpacingAfter) + "\""
}
if p.Properties.SpacingLine > 0 {
xml += " w:line=\"" + fmt.Sprintf("%d", p.Properties.SpacingLine) + "\""
xml += " w:lineRule=\"" + p.Properties.SpacingLineRule + "\""
}
xml += " />"
}
// 分页控制
// 分页控制 (必须在编号前面)
if p.Properties.KeepNext {
xml += "<w:keepNext />"
}
@@ -236,16 +205,11 @@ func (p *Paragraph) ToXML() string {
xml += "<w:widowControl />"
}
// 样式
if p.Properties.StyleID != "" {
xml += "<w:pStyle w:val=\"" + p.Properties.StyleID + "\" />"
}
// 编号
if p.Properties.NumID > 0 {
xml += "<w:numPr>"
xml += "<w:numId w:val=\"" + fmt.Sprintf("%d", p.Properties.NumID) + "\" />"
xml += "<w:ilvl w:val=\"" + fmt.Sprintf("%d", p.Properties.NumLevel) + "\" />"
xml += fmt.Sprintf("<w:ilvl w:val=\"%d\" />", p.Properties.NumLevel)
xml += fmt.Sprintf("<w:numId w:val=\"%d\" />", p.Properties.NumID)
xml += "</w:numPr>"
}
@@ -254,37 +218,78 @@ func (p *Paragraph) ToXML() string {
p.Properties.BorderLeft != nil || p.Properties.BorderRight != nil {
xml += "<w:pBdr>"
if p.Properties.BorderTop != nil {
xml += "<w:top w:val=\"" + p.Properties.BorderTop.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", p.Properties.BorderTop.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", p.Properties.BorderTop.Space) + "\""
xml += " w:color=\"" + p.Properties.BorderTop.Color + "\" />"
xml += fmt.Sprintf("<w:top w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
p.Properties.BorderTop.Style,
p.Properties.BorderTop.Size,
p.Properties.BorderTop.Space,
p.Properties.BorderTop.Color)
}
if p.Properties.BorderBottom != nil {
xml += "<w:bottom w:val=\"" + p.Properties.BorderBottom.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", p.Properties.BorderBottom.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", p.Properties.BorderBottom.Space) + "\""
xml += " w:color=\"" + p.Properties.BorderBottom.Color + "\" />"
xml += fmt.Sprintf("<w:bottom w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
p.Properties.BorderBottom.Style,
p.Properties.BorderBottom.Size,
p.Properties.BorderBottom.Space,
p.Properties.BorderBottom.Color)
}
if p.Properties.BorderLeft != nil {
xml += "<w:left w:val=\"" + p.Properties.BorderLeft.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", p.Properties.BorderLeft.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", p.Properties.BorderLeft.Space) + "\""
xml += " w:color=\"" + p.Properties.BorderLeft.Color + "\" />"
xml += fmt.Sprintf("<w:left w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
p.Properties.BorderLeft.Style,
p.Properties.BorderLeft.Size,
p.Properties.BorderLeft.Space,
p.Properties.BorderLeft.Color)
}
if p.Properties.BorderRight != nil {
xml += "<w:right w:val=\"" + p.Properties.BorderRight.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", p.Properties.BorderRight.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", p.Properties.BorderRight.Space) + "\""
xml += " w:color=\"" + p.Properties.BorderRight.Color + "\" />"
xml += fmt.Sprintf("<w:right w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
p.Properties.BorderRight.Style,
p.Properties.BorderRight.Size,
p.Properties.BorderRight.Space,
p.Properties.BorderRight.Color)
}
xml += "</w:pBdr>"
}
// 底纹
if p.Properties.Shading != nil {
xml += "<w:shd w:val=\"" + p.Properties.Shading.Pattern + "\""
xml += " w:fill=\"" + p.Properties.Shading.Fill + "\""
xml += " w:color=\"" + p.Properties.Shading.Color + "\" />"
xml += fmt.Sprintf("<w:shd w:val=\"%s\" w:fill=\"%s\" w:color=\"%s\" />",
p.Properties.Shading.Pattern,
p.Properties.Shading.Fill,
p.Properties.Shading.Color)
}
// 间距
if p.Properties.SpacingBefore > 0 || p.Properties.SpacingAfter > 0 || p.Properties.SpacingLine > 0 {
xml += "<w:spacing"
if p.Properties.SpacingBefore > 0 {
xml += fmt.Sprintf(" w:before=\"%d\"", p.Properties.SpacingBefore)
}
if p.Properties.SpacingAfter > 0 {
xml += fmt.Sprintf(" w:after=\"%d\"", p.Properties.SpacingAfter)
}
if p.Properties.SpacingLine > 0 {
xml += fmt.Sprintf(" w:line=\"%d\"", p.Properties.SpacingLine)
xml += fmt.Sprintf(" w:lineRule=\"%s\"", p.Properties.SpacingLineRule)
}
xml += " />"
}
// 缩进
if p.Properties.IndentLeft > 0 || p.Properties.IndentRight > 0 || p.Properties.IndentFirstLine > 0 {
xml += "<w:ind"
if p.Properties.IndentLeft > 0 {
xml += fmt.Sprintf(" w:left=\"%d\"", p.Properties.IndentLeft)
}
if p.Properties.IndentRight > 0 {
xml += fmt.Sprintf(" w:right=\"%d\"", p.Properties.IndentRight)
}
if p.Properties.IndentFirstLine > 0 {
xml += fmt.Sprintf(" w:firstLine=\"%d\"", p.Properties.IndentFirstLine)
}
xml += " />"
}
// 对齐方式
if p.Properties.Alignment != "" {
xml += fmt.Sprintf("<w:jc w:val=\"%s\" />", p.Properties.Alignment)
}
xml += "</w:pPr>"

View File

@@ -206,115 +206,130 @@ func (r *Run) AddPageNumber() *Run {
return r.AddField("begin", " PAGE ")
}
// ToXML 将文本运行转换为XML
// ToXML 将Run转换为XML
func (r *Run) ToXML() string {
xml := "<w:r>"
// 添加文本运行属性
// 添加运行属性 - 严格按照Word XML规范顺序
xml += "<w:rPr>"
// 字体
// 运行样式(缺失,预留位置)
// 1. 字体
if r.Properties.FontFamily != "" {
xml += "<w:rFonts w:ascii=\"" + r.Properties.FontFamily + "\""
xml += " w:eastAsia=\"" + r.Properties.FontFamily + "\""
xml += " w:hAnsi=\"" + r.Properties.FontFamily + "\""
xml += " w:cs=\"" + r.Properties.FontFamily + "\" />"
xml += fmt.Sprintf("<w:rFonts w:ascii=\"%s\" w:hAnsi=\"%s\" w:eastAsia=\"%s\" w:cs=\"%s\" />",
r.Properties.FontFamily,
r.Properties.FontFamily,
r.Properties.FontFamily,
r.Properties.FontFamily)
}
// 字号
if r.Properties.FontSize > 0 {
xml += "<w:sz w:val=\"" + fmt.Sprintf("%d", r.Properties.FontSize) + "\" />"
xml += "<w:szCs w:val=\"" + fmt.Sprintf("%d", r.Properties.FontSize) + "\" />"
}
// 颜色
if r.Properties.Color != "" {
xml += "<w:color w:val=\"" + r.Properties.Color + "\" />"
}
// 粗体
// 2. 加粗
if r.Properties.Bold {
xml += "<w:b />"
// 3. 复杂文本加粗
xml += "<w:bCs />"
}
// 斜体
// 4. 斜体
if r.Properties.Italic {
xml += "<w:i />"
// 5. 复杂文本斜体
xml += "<w:iCs />"
}
// 下划线
if r.Properties.Underline != "" {
xml += "<w:u w:val=\"" + r.Properties.Underline + "\" />"
}
// 删除线
if r.Properties.Strike {
xml += "<w:strike />"
}
// 双删除线
if r.Properties.DoubleStrike {
xml += "<w:dstrike />"
}
// 突出显示颜色
if r.Properties.Highlight != "" {
xml += "<w:highlight w:val=\"" + r.Properties.Highlight + "\" />"
}
// 全部大写
// 6. 全部大写
if r.Properties.Caps {
xml += "<w:caps />"
}
// 小型大写
// 7. 小型大写
if r.Properties.SmallCaps {
xml += "<w:smallCaps />"
}
// 字符间距
// 8. 删除线
if r.Properties.Strike {
xml += "<w:strike />"
}
// 9. 双删除线
if r.Properties.DoubleStrike {
xml += "<w:dstrike />"
}
// 10-18. 其他格式outline, shadow, emboss等缺失预留位置
// 19. 颜色
if r.Properties.Color != "" {
xml += fmt.Sprintf("<w:color w:val=\"%s\" />", r.Properties.Color)
}
// 20. 字符间距
if r.Properties.CharacterSpacing != 0 {
xml += "<w:spacing w:val=\"" + fmt.Sprintf("%d", r.Properties.CharacterSpacing) + "\" />"
xml += fmt.Sprintf("<w:spacing w:val=\"%d\" />", r.Properties.CharacterSpacing)
}
// 底纹
if r.Properties.Shading != nil {
xml += "<w:shd w:val=\"" + r.Properties.Shading.Pattern + "\""
xml += " w:fill=\"" + r.Properties.Shading.Fill + "\""
xml += " w:color=\"" + r.Properties.Shading.Color + "\" />"
// 21-23. 其他属性(缺失,预留位置)
// 24. 字号
if r.Properties.FontSize > 0 {
xml += fmt.Sprintf("<w:sz w:val=\"%d\" />", r.Properties.FontSize)
// 25. 复杂文本字号
xml += fmt.Sprintf("<w:szCs w:val=\"%d\" />", r.Properties.FontSize)
}
// 上标/下标
// 26. 突出显示
if r.Properties.Highlight != "" {
xml += fmt.Sprintf("<w:highlight w:val=\"%s\" />", r.Properties.Highlight)
}
// 27. 下划线
if r.Properties.Underline != "" {
xml += fmt.Sprintf("<w:u w:val=\"%s\" />", r.Properties.Underline)
}
// 28-31. 其他属性(缺失,预留位置)
// 32. 上标/下标
if r.Properties.Superscript {
xml += "<w:vertAlign w:val=\"superscript\" />"
} else if r.Properties.Subscript {
xml += "<w:vertAlign w:val=\"subscript\" />"
} else if r.Properties.VertAlign != "" {
xml += "<w:vertAlign w:val=\"" + r.Properties.VertAlign + "\" />"
xml += fmt.Sprintf("<w:vertAlign w:val=\"%s\" />", r.Properties.VertAlign)
}
// 从右到左文本方向
// 33. 从右到左文本方向
if r.Properties.RTL {
xml += "<w:rtl />"
}
// 语言
// 34-35. 其他属性(缺失,预留位置)
// 36. 语言
if r.Properties.Language != "" {
xml += "<w:lang w:val=\"" + r.Properties.Language + "\" />"
xml += fmt.Sprintf("<w:lang w:val=\"%s\" />", r.Properties.Language)
}
// 底纹shd应该在位置30
if r.Properties.Shading != nil {
xml += fmt.Sprintf("<w:shd w:val=\"%s\" w:fill=\"%s\" w:color=\"%s\" />",
r.Properties.Shading.Pattern,
r.Properties.Shading.Fill,
r.Properties.Shading.Color)
}
xml += "</w:rPr>"
// 添加分隔符
if r.BreakType != "" {
xml += "<w:br w:type=\"" + r.BreakType + "\" />"
xml += fmt.Sprintf("<w:br w:type=\"%s\" />", r.BreakType)
}
// 添加文本
if r.Text != "" {
xml += "<w:t xml:space=\"preserve\">" + r.Text + "</w:t>"
xml += fmt.Sprintf("<w:t xml:space=\"preserve\">%s</w:t>", r.Text)
}
// 添加图形

View File

@@ -387,108 +387,105 @@ func (t *Table) ToXML() string {
// 添加表格属性
xml += "<w:tblPr>"
// 表格宽度
if t.Properties.Width > 0 {
xml += "<w:tblW w:w=\"" + fmt.Sprintf("%d", t.Properties.Width) + "\""
xml += " w:type=\"" + t.Properties.WidthType + "\" />"
} else {
xml += "<w:tblW w:w=\"0\" w:type=\"auto\" />"
// 表格样式ID
if t.Properties.Style != "" {
xml += fmt.Sprintf("<w:tblStyle w:val=\"%s\" />", t.Properties.Style)
}
// 表格宽度
xml += fmt.Sprintf("<w:tblW w:w=\"%d\" w:type=\"%s\" />", t.Properties.Width, t.Properties.WidthType)
// 表格对齐方式
if t.Properties.Alignment != "" {
xml += "<w:jc w:val=\"" + t.Properties.Alignment + "\" />"
xml += fmt.Sprintf("<w:jc w:val=\"%s\" />", t.Properties.Alignment)
}
// 表格缩进
if t.Properties.Indent > 0 {
xml += "<w:tblInd w:w=\"" + fmt.Sprintf("%d", t.Properties.Indent) + "\""
xml += " w:type=\"dxa\" />"
xml += fmt.Sprintf("<w:tblInd w:w=\"%d\" w:type=\"dxa\" />", t.Properties.Indent)
}
// 表格边框
if t.Properties.Borders != nil {
xml += "<w:tblBorders>"
if t.Properties.Borders.Top != nil {
xml += "<w:top w:val=\"" + t.Properties.Borders.Top.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", t.Properties.Borders.Top.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", t.Properties.Borders.Top.Space) + "\""
xml += " w:color=\"" + t.Properties.Borders.Top.Color + "\" />"
}
if t.Properties.Borders.Bottom != nil {
xml += "<w:bottom w:val=\"" + t.Properties.Borders.Bottom.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", t.Properties.Borders.Bottom.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", t.Properties.Borders.Bottom.Space) + "\""
xml += " w:color=\"" + t.Properties.Borders.Bottom.Color + "\" />"
xml += fmt.Sprintf("<w:top w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
t.Properties.Borders.Top.Style,
t.Properties.Borders.Top.Size,
t.Properties.Borders.Top.Space,
t.Properties.Borders.Top.Color)
}
if t.Properties.Borders.Left != nil {
xml += "<w:left w:val=\"" + t.Properties.Borders.Left.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", t.Properties.Borders.Left.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", t.Properties.Borders.Left.Space) + "\""
xml += " w:color=\"" + t.Properties.Borders.Left.Color + "\" />"
xml += fmt.Sprintf("<w:left w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
t.Properties.Borders.Left.Style,
t.Properties.Borders.Left.Size,
t.Properties.Borders.Left.Space,
t.Properties.Borders.Left.Color)
}
if t.Properties.Borders.Bottom != nil {
xml += fmt.Sprintf("<w:bottom w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
t.Properties.Borders.Bottom.Style,
t.Properties.Borders.Bottom.Size,
t.Properties.Borders.Bottom.Space,
t.Properties.Borders.Bottom.Color)
}
if t.Properties.Borders.Right != nil {
xml += "<w:right w:val=\"" + t.Properties.Borders.Right.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", t.Properties.Borders.Right.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", t.Properties.Borders.Right.Space) + "\""
xml += " w:color=\"" + t.Properties.Borders.Right.Color + "\" />"
xml += fmt.Sprintf("<w:right w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
t.Properties.Borders.Right.Style,
t.Properties.Borders.Right.Size,
t.Properties.Borders.Right.Space,
t.Properties.Borders.Right.Color)
}
if t.Properties.Borders.InsideH != nil {
xml += "<w:insideH w:val=\"" + t.Properties.Borders.InsideH.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", t.Properties.Borders.InsideH.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", t.Properties.Borders.InsideH.Space) + "\""
xml += " w:color=\"" + t.Properties.Borders.InsideH.Color + "\" />"
xml += fmt.Sprintf("<w:insideH w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
t.Properties.Borders.InsideH.Style,
t.Properties.Borders.InsideH.Size,
t.Properties.Borders.InsideH.Space,
t.Properties.Borders.InsideH.Color)
}
if t.Properties.Borders.InsideV != nil {
xml += "<w:insideV w:val=\"" + t.Properties.Borders.InsideV.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", t.Properties.Borders.InsideV.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", t.Properties.Borders.InsideV.Space) + "\""
xml += " w:color=\"" + t.Properties.Borders.InsideV.Color + "\" />"
xml += fmt.Sprintf("<w:insideV w:val=\"%s\" w:sz=\"%d\" w:space=\"%d\" w:color=\"%s\" />",
t.Properties.Borders.InsideV.Style,
t.Properties.Borders.InsideV.Size,
t.Properties.Borders.InsideV.Space,
t.Properties.Borders.InsideV.Color)
}
xml += "</w:tblBorders>"
}
// 表格单元格边距
// 表格布局
if t.Properties.Layout != "" {
xml += fmt.Sprintf("<w:tblLayout w:type=\"%s\" />", t.Properties.Layout)
}
// 单元格边距
if t.Properties.CellMargin != nil {
xml += "<w:tblCellMar>"
if t.Properties.CellMargin.Top > 0 {
xml += "<w:top w:w=\"" + fmt.Sprintf("%d", t.Properties.CellMargin.Top) + "\""
xml += " w:type=\"dxa\" />"
}
if t.Properties.CellMargin.Bottom > 0 {
xml += "<w:bottom w:w=\"" + fmt.Sprintf("%d", t.Properties.CellMargin.Bottom) + "\""
xml += " w:type=\"dxa\" />"
xml += fmt.Sprintf("<w:top w:w=\"%d\" w:type=\"dxa\" />", t.Properties.CellMargin.Top)
}
if t.Properties.CellMargin.Left > 0 {
xml += "<w:left w:w=\"" + fmt.Sprintf("%d", t.Properties.CellMargin.Left) + "\""
xml += " w:type=\"dxa\" />"
xml += fmt.Sprintf("<w:left w:w=\"%d\" w:type=\"dxa\" />", t.Properties.CellMargin.Left)
}
if t.Properties.CellMargin.Bottom > 0 {
xml += fmt.Sprintf("<w:bottom w:w=\"%d\" w:type=\"dxa\" />", t.Properties.CellMargin.Bottom)
}
if t.Properties.CellMargin.Right > 0 {
xml += "<w:right w:w=\"" + fmt.Sprintf("%d", t.Properties.CellMargin.Right) + "\""
xml += " w:type=\"dxa\" />"
xml += fmt.Sprintf("<w:right w:w=\"%d\" w:type=\"dxa\" />", t.Properties.CellMargin.Right)
}
xml += "</w:tblCellMar>"
}
// 表格布局方式
if t.Properties.Layout != "" {
xml += "<w:tblLayout w:type=\"" + t.Properties.Layout + "\" />"
}
// 表格样式
if t.Properties.Style != "" {
xml += "<w:tblStyle w:val=\"" + t.Properties.Style + "\" />"
}
// 表格外观
if t.Properties.Look != "" {
xml += "<w:tblLook w:val=\"" + t.Properties.Look + "\""
xml += " w:firstRow=\"" + fmt.Sprintf("%d", boolToInt(t.Properties.FirstRow)) + "\""
xml += " w:lastRow=\"" + fmt.Sprintf("%d", boolToInt(t.Properties.LastRow)) + "\""
xml += " w:firstColumn=\"" + fmt.Sprintf("%d", boolToInt(t.Properties.FirstColumn)) + "\""
xml += " w:lastColumn=\"" + fmt.Sprintf("%d", boolToInt(t.Properties.LastColumn)) + "\""
xml += " w:noHBand=\"" + fmt.Sprintf("%d", boolToInt(t.Properties.NoHBand)) + "\""
xml += " w:noVBand=\"" + fmt.Sprintf("%d", boolToInt(t.Properties.NoVBand)) + "\" />"
xml += fmt.Sprintf("<w:tblLook w:val=\"%s\" w:firstRow=\"%v\" w:lastRow=\"%v\" w:firstColumn=\"%v\" w:lastColumn=\"%v\" w:noHBand=\"%v\" w:noVBand=\"%v\" />",
t.Properties.Look,
formatBoolToWXml(t.Properties.FirstRow),
formatBoolToWXml(t.Properties.LastRow),
formatBoolToWXml(t.Properties.FirstColumn),
formatBoolToWXml(t.Properties.LastColumn),
formatBoolToWXml(t.Properties.NoHBand),
formatBoolToWXml(t.Properties.NoVBand))
}
xml += "</w:tblPr>"
@@ -504,129 +501,133 @@ func (t *Table) ToXML() string {
// 添加所有行的XML
for _, row := range t.Rows {
xml += "<w:tr>"
// 添加行属性
xml += "<w:trPr>"
// 行高
if row.Properties.Height > 0 {
xml += "<w:trHeight w:val=\"" + fmt.Sprintf("%d", row.Properties.Height) + "\""
xml += " w:hRule=\"" + row.Properties.HeightRule + "\" />"
}
// 不允许跨页分割
if row.Properties.CantSplit {
xml += "<w:cantSplit />"
}
// 表头行
if row.Properties.IsHeader {
xml += "<w:tblHeader />"
}
xml += "</w:trPr>"
// 添加所有单元格的XML
for _, cell := range row.Cells {
xml += "<w:tc>"
// 添加单元格属性
xml += "<w:tcPr>"
// 单元格宽度
if cell.Properties.Width > 0 {
xml += "<w:tcW w:w=\"" + fmt.Sprintf("%d", cell.Properties.Width) + "\""
xml += " w:type=\"" + cell.Properties.WidthType + "\" />"
} else {
xml += "<w:tcW w:w=\"0\" w:type=\"auto\" />"
}
// 垂直对齐方式
if cell.Properties.VertAlign != "" {
xml += "<w:vAlign w:val=\"" + cell.Properties.VertAlign + "\" />"
}
// 单元格边框
if cell.Properties.Borders != nil {
xml += "<w:tcBorders>"
if cell.Properties.Borders.Top != nil {
xml += "<w:top w:val=\"" + cell.Properties.Borders.Top.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", cell.Properties.Borders.Top.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", cell.Properties.Borders.Top.Space) + "\""
xml += " w:color=\"" + cell.Properties.Borders.Top.Color + "\" />"
}
if cell.Properties.Borders.Bottom != nil {
xml += "<w:bottom w:val=\"" + cell.Properties.Borders.Bottom.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", cell.Properties.Borders.Bottom.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", cell.Properties.Borders.Bottom.Space) + "\""
xml += " w:color=\"" + cell.Properties.Borders.Bottom.Color + "\" />"
}
if cell.Properties.Borders.Left != nil {
xml += "<w:left w:val=\"" + cell.Properties.Borders.Left.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", cell.Properties.Borders.Left.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", cell.Properties.Borders.Left.Space) + "\""
xml += " w:color=\"" + cell.Properties.Borders.Left.Color + "\" />"
}
if cell.Properties.Borders.Right != nil {
xml += "<w:right w:val=\"" + cell.Properties.Borders.Right.Style + "\""
xml += " w:sz=\"" + fmt.Sprintf("%d", cell.Properties.Borders.Right.Size) + "\""
xml += " w:space=\"" + fmt.Sprintf("%d", cell.Properties.Borders.Right.Space) + "\""
xml += " w:color=\"" + cell.Properties.Borders.Right.Color + "\" />"
}
xml += "</w:tcBorders>"
}
// 底纹
if cell.Properties.Shading != nil {
xml += "<w:shd w:val=\"" + cell.Properties.Shading.Pattern + "\""
xml += " w:fill=\"" + cell.Properties.Shading.Fill + "\""
xml += " w:color=\"" + cell.Properties.Shading.Color + "\" />"
}
// 跨列数
if cell.Properties.GridSpan > 1 {
xml += "<w:gridSpan w:val=\"" + fmt.Sprintf("%d", cell.Properties.GridSpan) + "\" />"
}
// 垂直合并
if cell.Properties.VMerge != "" {
xml += "<w:vMerge w:val=\"" + cell.Properties.VMerge + "\" />"
}
// 不换行
if cell.Properties.NoWrap {
xml += "<w:noWrap />"
}
// 适应文本
if cell.Properties.FitText {
xml += "<w:fitText />"
}
xml += "</w:tcPr>"
// 添加所有内容元素的XML
for _, content := range cell.Content {
switch v := content.(type) {
case *Paragraph:
xml += v.ToXML()
case *Table:
xml += v.ToXML()
}
}
// 如果单元格没有内容,添加一个空段落
if len(cell.Content) == 0 {
xml += "<w:p><w:pPr></w:pPr></w:p>"
}
xml += "</w:tc>"
}
xml += "</w:tr>"
xml += row.ToXML()
}
xml += "</w:tbl>"
return xml
}
// formatBoolToWXml 将布尔值转换为Word XML中使用的字符串表示
func formatBoolToWXml(value bool) string {
if value {
return "1"
}
return "0"
}
// ToXML 将表格行转换为XML
func (r *TableRow) ToXML() string {
xml := "<w:tr>"
// 添加行属性
xml += "<w:trPr>"
// 行高
if r.Properties.Height > 0 {
xml += "<w:trHeight w:val=\"" + fmt.Sprintf("%d", r.Properties.Height) + "\" w:hRule=\"" + r.Properties.HeightRule + "\" />"
}
// 不允许跨页分割
if r.Properties.CantSplit {
xml += "<w:cantSplit />"
}
// 表头行
if r.Properties.IsHeader {
xml += "<w:tblHeader />"
}
xml += "</w:trPr>"
// 添加所有单元格的XML
for _, cell := range r.Cells {
xml += cell.ToXML()
}
xml += "</w:tr>"
return xml
}
// ToXML 将表格单元格转换为XML
func (c *TableCell) ToXML() string {
xml := "<w:tc>"
// 添加单元格属性
xml += "<w:tcPr>"
// 单元格宽度
if c.Properties.Width > 0 {
xml += "<w:tcW w:w=\"" + fmt.Sprintf("%d", c.Properties.Width) + "\" w:type=\"" + c.Properties.WidthType + "\" />"
} else {
xml += "<w:tcW w:w=\"0\" w:type=\"auto\" />"
}
// 垂直对齐方式
if c.Properties.VertAlign != "" {
xml += "<w:vAlign w:val=\"" + c.Properties.VertAlign + "\" />"
}
// 单元格边框
if c.Properties.Borders != nil {
xml += "<w:tcBorders>"
if c.Properties.Borders.Top != nil {
xml += "<w:top w:val=\"" + c.Properties.Borders.Top.Style + "\" w:sz=\"" + fmt.Sprintf("%d", c.Properties.Borders.Top.Size) + "\" w:space=\"" + fmt.Sprintf("%d", c.Properties.Borders.Top.Space) + "\" w:color=\"" + c.Properties.Borders.Top.Color + "\" />"
}
if c.Properties.Borders.Bottom != nil {
xml += "<w:bottom w:val=\"" + c.Properties.Borders.Bottom.Style + "\" w:sz=\"" + fmt.Sprintf("%d", c.Properties.Borders.Bottom.Size) + "\" w:space=\"" + fmt.Sprintf("%d", c.Properties.Borders.Bottom.Space) + "\" w:color=\"" + c.Properties.Borders.Bottom.Color + "\" />"
}
if c.Properties.Borders.Left != nil {
xml += "<w:left w:val=\"" + c.Properties.Borders.Left.Style + "\" w:sz=\"" + fmt.Sprintf("%d", c.Properties.Borders.Left.Size) + "\" w:space=\"" + fmt.Sprintf("%d", c.Properties.Borders.Left.Space) + "\" w:color=\"" + c.Properties.Borders.Left.Color + "\" />"
}
if c.Properties.Borders.Right != nil {
xml += "<w:right w:val=\"" + c.Properties.Borders.Right.Style + "\" w:sz=\"" + fmt.Sprintf("%d", c.Properties.Borders.Right.Size) + "\" w:space=\"" + fmt.Sprintf("%d", c.Properties.Borders.Right.Space) + "\" w:color=\"" + c.Properties.Borders.Right.Color + "\" />"
}
xml += "</w:tcBorders>"
}
// 底纹
if c.Properties.Shading != nil {
xml += "<w:shd w:val=\"" + c.Properties.Shading.Pattern + "\" w:fill=\"" + c.Properties.Shading.Fill + "\" w:color=\"" + c.Properties.Shading.Color + "\" />"
}
// 跨列数
if c.Properties.GridSpan > 1 {
xml += "<w:gridSpan w:val=\"" + fmt.Sprintf("%d", c.Properties.GridSpan) + "\" />"
}
// 垂直合并
if c.Properties.VMerge != "" {
xml += "<w:vMerge w:val=\"" + c.Properties.VMerge + "\" />"
}
// 不换行
if c.Properties.NoWrap {
xml += "<w:noWrap />"
}
// 适应文本
if c.Properties.FitText {
xml += "<w:fitText />"
}
xml += "</w:tcPr>"
// 添加所有内容元素的XML
for _, content := range c.Content {
switch v := content.(type) {
case *Paragraph:
xml += v.ToXML()
case *Table:
xml += v.ToXML()
}
}
// 如果单元格没有内容,添加一个空段落
if len(c.Content) == 0 {
xml += "<w:p><w:pPr></w:pPr></w:p>"
}
xml += "</w:tc>"
return xml
}

View File

@@ -40,7 +40,6 @@ func NewContentTypes() *ContentTypes {
ct.AddOverride("/xl/workbook.xml", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml")
ct.AddOverride("/xl/styles.xml", "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml")
ct.AddOverride("/xl/theme/theme1.xml", "application/vnd.openxmlformats-officedocument.theme+xml")
ct.AddOverride("/xl/worksheets/sheet1.xml", "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml")
ct.AddOverride("/xl/sharedStrings.xml", "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml")
return ct

View File

@@ -259,7 +259,7 @@ func main() {
})
// 保存Excel文件
err := wb.Save("sales_report.xlsx")
err := wb.Save("./workbook/examples/simple/sales_report.xlsx")
if err != nil {
fmt.Println("保存Excel文件时出错:", err)
return

View File

@@ -71,6 +71,11 @@ func (wb *Workbook) Save(filename string) error {
zipWriter := zip.NewWriter(file)
defer zipWriter.Close()
// 为每个工作表添加内容类型覆盖
for i := range wb.Worksheets {
wb.ContentTypes.AddWorksheetOverride(i + 1)
}
// 添加[Content_Types].xml
contentTypesWriter, err := zipWriter.Create("[Content_Types].xml")
if err != nil {