Files
go-dockit/document/numbering.go
2025-04-16 16:12:33 +08:00

376 lines
9.5 KiB
Go

package document
import (
"fmt"
)
// Numbering 表示Word文档中的编号集合
type Numbering struct {
AbstractNums []*AbstractNum
Nums []*Num
}
// AbstractNum 表示抽象编号
type AbstractNum struct {
ID int
Levels []*NumberingLevel
}
// Num 表示具体编号
type Num struct {
ID int
AbstractNumID int
LevelOverrides []*LevelOverride
}
// LevelOverride 表示级别覆盖
type LevelOverride struct {
Level int
StartAt int
NumberingLevel *NumberingLevel
}
// NumberingLevel 表示编号级别
type NumberingLevel struct {
Level int
Start int
NumberingFormat string // decimal, upperRoman, lowerRoman, upperLetter, lowerLetter, bullet, etc.
Text string // 编号文本,如 "%1."
Justification string // left, center, right
ParagraphStyle string // 段落样式ID
Font string // 字体
Indent int // 缩进
HangingIndent int // 悬挂缩进
TabStop int // 制表位
Suffix string // tab, space, nothing
}
// NewNumbering 创建一个新的编号集合
func NewNumbering() *Numbering {
return &Numbering{
AbstractNums: make([]*AbstractNum, 0),
Nums: make([]*Num, 0),
}
}
// AddAbstractNum 添加一个抽象编号
func (n *Numbering) AddAbstractNum() *AbstractNum {
abstractNum := &AbstractNum{
ID: len(n.AbstractNums) + 1,
Levels: make([]*NumberingLevel, 0),
}
n.AbstractNums = append(n.AbstractNums, abstractNum)
return abstractNum
}
// AddNum 添加一个具体编号
func (n *Numbering) AddNum(abstractNumID int) *Num {
num := &Num{
ID: len(n.Nums) + 1,
AbstractNumID: abstractNumID,
LevelOverrides: make([]*LevelOverride, 0),
}
n.Nums = append(n.Nums, num)
return num
}
// AddLevel 向抽象编号添加一个级别
func (a *AbstractNum) AddLevel(level int) *NumberingLevel {
numberingLevel := &NumberingLevel{
Level: level,
Start: 1,
NumberingFormat: "decimal",
Text: "%" + fmt.Sprintf("%d", level+1) + ".",
Justification: "left",
Indent: 720 * (level + 1), // 720 twip = 0.5 inch
HangingIndent: 360, // 360 twip = 0.25 inch
TabStop: 720 * (level + 1),
Suffix: "tab",
}
a.Levels = append(a.Levels, numberingLevel)
return numberingLevel
}
// AddLevelOverride 向具体编号添加一个级别覆盖
func (n *Num) AddLevelOverride(level int) *LevelOverride {
levelOverride := &LevelOverride{
Level: level,
StartAt: 1,
}
n.LevelOverrides = append(n.LevelOverrides, levelOverride)
return levelOverride
}
// SetStart 设置编号级别的起始值
func (l *NumberingLevel) SetStart(start int) *NumberingLevel {
l.Start = start
return l
}
// SetNumberingFormat 设置编号级别的格式
func (l *NumberingLevel) SetNumberingFormat(format string) *NumberingLevel {
l.NumberingFormat = format
return l
}
// SetText 设置编号级别的文本
func (l *NumberingLevel) SetText(text string) *NumberingLevel {
l.Text = text
return l
}
// SetJustification 设置编号级别的对齐方式
func (l *NumberingLevel) SetJustification(justification string) *NumberingLevel {
l.Justification = justification
return l
}
// SetParagraphStyle 设置编号级别的段落样式
func (l *NumberingLevel) SetParagraphStyle(style string) *NumberingLevel {
l.ParagraphStyle = style
return l
}
// SetFont 设置编号级别的字体
func (l *NumberingLevel) SetFont(font string) *NumberingLevel {
l.Font = font
return l
}
// SetIndent 设置编号级别的缩进
func (l *NumberingLevel) SetIndent(indent int) *NumberingLevel {
l.Indent = indent
return l
}
// SetHangingIndent 设置编号级别的悬挂缩进
func (l *NumberingLevel) SetHangingIndent(hangingIndent int) *NumberingLevel {
l.HangingIndent = hangingIndent
return l
}
// SetTabStop 设置编号级别的制表位
func (l *NumberingLevel) SetTabStop(tabStop int) *NumberingLevel {
l.TabStop = tabStop
return l
}
// SetSuffix 设置编号级别的后缀
func (l *NumberingLevel) SetSuffix(suffix string) *NumberingLevel {
l.Suffix = suffix
return l
}
// SetStartAt 设置级别覆盖的起始值
func (l *LevelOverride) SetStartAt(startAt int) *LevelOverride {
l.StartAt = startAt
return l
}
// SetNumberingLevel 设置级别覆盖的编号级别
func (l *LevelOverride) SetNumberingLevel(level *NumberingLevel) *LevelOverride {
l.NumberingLevel = level
return l
}
// CreateBulletList 创建一个项目符号列表
func (n *Numbering) CreateBulletList() int {
// 创建抽象编号
abstractNum := n.AddAbstractNum()
// 添加9个级别
for i := 0; i < 9; i++ {
level := abstractNum.AddLevel(i)
level.SetNumberingFormat("bullet")
// 根据级别设置不同的项目符号
switch i % 3 {
case 0:
level.SetText("•")
level.SetFont("Symbol")
case 1:
level.SetText("○")
level.SetFont("Courier New")
case 2:
level.SetText("▪")
level.SetFont("Wingdings")
}
}
// 创建具体编号
num := n.AddNum(abstractNum.ID)
return num.ID
}
// CreateNumberList 创建一个数字列表
func (n *Numbering) CreateNumberList() int {
// 创建抽象编号
abstractNum := n.AddAbstractNum()
// 添加9个级别
for i := 0; i < 9; i++ {
level := abstractNum.AddLevel(i)
// 根据级别设置不同的编号格式
switch i % 3 {
case 0:
level.SetNumberingFormat("decimal")
level.SetText("%" + fmt.Sprintf("%d", i+1) + ".")
case 1:
level.SetNumberingFormat("lowerLetter")
level.SetText("%" + fmt.Sprintf("%d", i+1) + ").")
case 2:
level.SetNumberingFormat("lowerRoman")
level.SetText("%" + fmt.Sprintf("%d", i+1) + ").")
}
}
// 创建具体编号
num := n.AddNum(abstractNum.ID)
return num.ID
}
// ToXML 将编号集合转换为XML
func (n *Numbering) ToXML() string {
xml := "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
xml += "<w:numbering xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">"
// 添加所有抽象编号
for _, abstractNum := range n.AbstractNums {
xml += "<w:abstractNum w:abstractNumId=\"" + fmt.Sprintf("%d", abstractNum.ID) + "\">"
// 添加所有级别
for _, level := range abstractNum.Levels {
xml += "<w:lvl w:ilvl=\"" + fmt.Sprintf("%d", level.Level) + "\">"
// 起始值
xml += "<w:start w:val=\"" + fmt.Sprintf("%d", level.Start) + "\" />"
// 编号格式
xml += "<w:numFmt w:val=\"" + level.NumberingFormat + "\" />"
// 编号文本
xml += "<w:lvlText w:val=\"" + level.Text + "\" />"
// 对齐方式
xml += "<w:lvlJc w:val=\"" + level.Justification + "\" />"
// 段落属性
xml += "<w:pPr>"
// 缩进
xml += "<w:ind w:left=\"" + fmt.Sprintf("%d", level.Indent) + "\""
xml += " w:hanging=\"" + fmt.Sprintf("%d", level.HangingIndent) + "\" />"
// 制表位
if level.TabStop > 0 {
xml += "<w:tabs>"
xml += "<w:tab w:val=\"num\" w:pos=\"" + fmt.Sprintf("%d", level.TabStop) + "\" />"
xml += "</w:tabs>"
}
xml += "</w:pPr>"
// 文本运行属性
xml += "<w:rPr>"
// 字体
if level.Font != "" {
xml += "<w:rFonts w:ascii=\"" + level.Font + "\""
xml += " w:hAnsi=\"" + level.Font + "\""
xml += " w:hint=\"default\" />"
}
xml += "</w:rPr>"
// 后缀
if level.Suffix != "" {
xml += "<w:suff w:val=\"" + level.Suffix + "\" />"
}
xml += "</w:lvl>"
}
xml += "</w:abstractNum>"
}
// 添加所有具体编号
for _, num := range n.Nums {
xml += "<w:num w:numId=\"" + fmt.Sprintf("%d", num.ID) + "\">"
// 抽象编号ID
xml += "<w:abstractNumId w:val=\"" + fmt.Sprintf("%d", num.AbstractNumID) + "\" />"
// 添加所有级别覆盖
for _, levelOverride := range num.LevelOverrides {
xml += "<w:lvlOverride w:ilvl=\"" + fmt.Sprintf("%d", levelOverride.Level) + "\">"
// 起始值
if levelOverride.StartAt > 0 {
xml += "<w:startOverride w:val=\"" + fmt.Sprintf("%d", levelOverride.StartAt) + "\" />"
}
// 编号级别
if levelOverride.NumberingLevel != nil {
xml += "<w:lvl w:ilvl=\"" + fmt.Sprintf("%d", levelOverride.NumberingLevel.Level) + "\">"
// 起始值
xml += "<w:start w:val=\"" + fmt.Sprintf("%d", levelOverride.NumberingLevel.Start) + "\" />"
// 编号格式
xml += "<w:numFmt w:val=\"" + levelOverride.NumberingLevel.NumberingFormat + "\" />"
// 编号文本
xml += "<w:lvlText w:val=\"" + levelOverride.NumberingLevel.Text + "\" />"
// 对齐方式
xml += "<w:lvlJc w:val=\"" + levelOverride.NumberingLevel.Justification + "\" />"
// 段落属性
xml += "<w:pPr>"
// 缩进
xml += "<w:ind w:left=\"" + fmt.Sprintf("%d", levelOverride.NumberingLevel.Indent) + "\""
xml += " w:hanging=\"" + fmt.Sprintf("%d", levelOverride.NumberingLevel.HangingIndent) + "\" />"
// 制表位
if levelOverride.NumberingLevel.TabStop > 0 {
xml += "<w:tabs>"
xml += "<w:tab w:val=\"num\" w:pos=\"" + fmt.Sprintf("%d", levelOverride.NumberingLevel.TabStop) + "\" />"
xml += "</w:tabs>"
}
xml += "</w:pPr>"
// 文本运行属性
xml += "<w:rPr>"
// 字体
if levelOverride.NumberingLevel.Font != "" {
xml += "<w:rFonts w:ascii=\"" + levelOverride.NumberingLevel.Font + "\""
xml += " w:hAnsi=\"" + levelOverride.NumberingLevel.Font + "\""
xml += " w:hint=\"default\" />"
}
xml += "</w:rPr>"
// 后缀
if levelOverride.NumberingLevel.Suffix != "" {
xml += "<w:suff w:val=\"" + levelOverride.NumberingLevel.Suffix + "\" />"
}
xml += "</w:lvl>"
}
xml += "</w:lvlOverride>"
}
xml += "</w:num>"
}
xml += "</w:numbering>"
return xml
}