package workbook import ( "fmt" "strings" ) // Styles 表示Excel文档中的样式集合 type Styles struct { Fonts []*Font Fills []*Fill Borders []*Border NumberFormats []*NumberFormat CellStyles []*CellStyleDef CellStyleXfs []*CellStyleXf CellXfs []*CellXf } // NewStyles 创建一个新的样式集合 func NewStyles() *Styles { s := &Styles{ Fonts: make([]*Font, 0), Fills: make([]*Fill, 0), Borders: make([]*Border, 0), NumberFormats: make([]*NumberFormat, 0), CellStyles: make([]*CellStyleDef, 0), CellStyleXfs: make([]*CellStyleXf, 0), CellXfs: make([]*CellXf, 0), } // 添加默认字体 s.AddFont("Calibri", 11, false, false, false, "") // 添加默认填充 s.AddFill("none", "") s.AddFill("gray125", "") // 添加默认边框 s.AddBorder() // 添加默认数字格式 s.AddNumberFormat(0, "General") // 添加默认单元格样式XF s.AddCellStyleXf(0, 0, 0, 0, nil) // 添加默认单元格样式 // 第二个参数是XF ID,指向已创建的CellStyleXfs中的索引 s.AddCellStyle("Normal", 0, 0) // 添加默认单元格XF s.AddCellXf(0, 0, 0, 0, nil) return s } // Font 表示字体 type Font struct { Name string Size float64 Bold bool Italic bool Underline bool Color string } // AddFont 添加字体 func (s *Styles) AddFont(name string, size float64, bold, italic, underline bool, color string) *Font { font := &Font{ Name: name, Size: size, Bold: bold, Italic: italic, Underline: underline, Color: color, } s.Fonts = append(s.Fonts, font) return font } // Fill 表示填充 type Fill struct { PatternType string FgColor string BgColor string } // AddFill 添加填充 func (s *Styles) AddFill(patternType, fgColor string) *Fill { fill := &Fill{ PatternType: patternType, FgColor: fgColor, } s.Fills = append(s.Fills, fill) return fill } // Border 表示边框 type Border struct { Left *BorderStyle Right *BorderStyle Top *BorderStyle Bottom *BorderStyle } // BorderStyle 表示边框样式 type BorderStyle struct { Style string Color string } // AddBorder 添加边框 func (s *Styles) AddBorder() *Border { border := &Border{ Left: &BorderStyle{}, Right: &BorderStyle{}, Top: &BorderStyle{}, Bottom: &BorderStyle{}, } s.Borders = append(s.Borders, border) return border } // NumberFormat 表示数字格式 type NumberFormat struct { ID int Code string } // AddNumberFormat 添加数字格式 func (s *Styles) AddNumberFormat(id int, code string) *NumberFormat { nf := &NumberFormat{ ID: id, Code: code, } s.NumberFormats = append(s.NumberFormats, nf) return nf } // CellStyleDef 表示单元格样式定义 type CellStyleDef struct { Name string XfId int BuiltinId int CustomBuiltin bool } // AddCellStyle 添加单元格样式 func (s *Styles) AddCellStyle(name string, xfId int, builtinId int) *CellStyleDef { cs := &CellStyleDef{ Name: name, XfId: xfId, BuiltinId: builtinId, } s.CellStyles = append(s.CellStyles, cs) return cs } // CellStyleXf 表示单元格样式XF type CellStyleXf struct { FontId int FillId int BorderId int NumFmtId int Alignment *Alignment ApplyFont bool ApplyFill bool ApplyBorder bool ApplyNumberFormat bool ApplyAlignment bool } // AddCellStyleXf 添加单元格样式XF func (s *Styles) AddCellStyleXf(fontId, fillId, borderId, numFmtId int, alignment *Alignment) *CellStyleXf { csx := &CellStyleXf{ FontId: fontId, FillId: fillId, BorderId: borderId, NumFmtId: numFmtId, Alignment: alignment, ApplyFont: fontId > 0, ApplyFill: fillId > 0, ApplyBorder: borderId > 0, ApplyNumberFormat: numFmtId > 0, ApplyAlignment: alignment != nil, } s.CellStyleXfs = append(s.CellStyleXfs, csx) return csx } // CellXf 表示单元格XF type CellXf struct { FontId int FillId int BorderId int NumFmtId int Alignment *Alignment ApplyFont bool ApplyFill bool ApplyBorder bool ApplyNumberFormat bool ApplyAlignment bool } // AddCellXf 添加单元格XF func (s *Styles) AddCellXf(fontId, fillId, borderId, numFmtId int, alignment *Alignment) int { cx := &CellXf{ FontId: fontId, FillId: fillId, BorderId: borderId, NumFmtId: numFmtId, Alignment: alignment, ApplyFont: fontId > 0, ApplyFill: fillId > 0, ApplyBorder: borderId > 0, ApplyNumberFormat: numFmtId > 0, ApplyAlignment: alignment != nil, } s.CellXfs = append(s.CellXfs, cx) return len(s.CellXfs) - 1 } // CreateStyle 创建一个完整的单元格样式并返回样式ID func (s *Styles) CreateStyle(fontName string, fontSize float64, bold, italic, underline bool, fontColor string, fillPattern, fillColor string, borderStyle string, borderColor string, numFmtCode string, hAlign, vAlign string, wrapText bool) int { // 添加字体 fontId := 0 if fontName != "" || fontSize > 0 || bold || italic || underline || fontColor != "" { s.AddFont(fontName, fontSize, bold, italic, underline, fontColor) fontId = len(s.Fonts) - 1 } // 添加填充 fillId := 0 if fillPattern != "" { s.AddFill(fillPattern, fillColor) fillId = len(s.Fills) - 1 } // 添加边框 borderId := 0 if borderStyle != "" { border := s.AddBorder() border.Left.Style = borderStyle border.Left.Color = borderColor border.Right.Style = borderStyle border.Right.Color = borderColor border.Top.Style = borderStyle border.Top.Color = borderColor border.Bottom.Style = borderStyle border.Bottom.Color = borderColor borderId = len(s.Borders) - 1 } // 添加数字格式 - 改进 numFmtId := 0 if numFmtCode != "" { // 处理货币格式中的引号问题 if strings.Contains(numFmtCode, "\"¥\"") { // 人民币格式使用编号7 numFmtId = 7 } else if numFmtCode == "0.00E+00" || numFmtCode == "##0.0E+0" { // 使用Excel内置的科学计数格式ID numFmtId = 11 } else { // 检查是否是其他内置格式 builtinId := getBuiltinNumberFormatId(numFmtCode) if builtinId > 0 { numFmtId = builtinId } else { // 如果不是内置格式,创建自定义格式 // Excel自定义格式从164开始 numFmtId = 164 + len(s.NumberFormats) s.AddNumberFormat(numFmtId, numFmtCode) } } } var alignment *Alignment if hAlign != "" || vAlign != "" || wrapText { alignment = &Alignment{ Horizontal: hAlign, Vertical: vAlign, WrapText: wrapText, } } // 创建单元格XF并返回其索引 styleIndex := s.AddCellXf(fontId, fillId, borderId, numFmtId, alignment) return styleIndex } // 获取内置数字格式ID func getBuiltinNumberFormatId(format string) int { builtinFormats := map[string]int{ // 常规格式 "General": 0, // 数值格式 "0": 1, // 整数 "0.00": 2, // 小数 "#,##0": 3, // 千位分隔的整数 "#,##0.00": 4, // 千位分隔的小数 // 货币格式 "¥#,##0;¥\\-#,##0": 7, // 人民币格式 "¥#,##0;[Red]¥\\-#,##0": 8, // 人民币格式(负数为红色) "\"¥\"#,##0.00": 7, // 人民币格式带小数 - 这个格式有问题 "$#,##0.00": 44, // 美元格式 "$#,##0.00_);($#,##0.00)": 43, // 会计专用美元格式 "_(\"$\"* #,##0.00_)": 42, // 会计专用美元格式(负数带括号) "_-* #,##0.00_-": 4, // 会计专用格式 // 百分比格式 "0%": 9, // 整数百分比 "0.00%": 10, // 小数百分比 // 科学计数格式 "0.00E+00": 11, // 科学计数 - 确保正确提供此格式 "##0.0E+0": 11, // 科学计数 - 另一种写法 // 分数格式 "# ?/?": 12, // 分数 (例如:1/4) "# ??/??": 13, // 分数 (例如:3/16) // 日期格式 - 增加更多常见日期格式 "mm-dd-yy": 14, // 月-日-年 "d-mmm-yy": 15, // 日-月缩写-年 "d-mmm": 16, // 日-月缩写 "mmm-yy": 17, // 月缩写-年 "mm/dd/yy": 30, // 月/日/年 "mm/dd/yyyy": 22, // 月/日/完整年份 "yyyy/mm/dd": 20, // ISO 8601 格式 "dd/mm/yyyy": 21, // 欧洲日期格式 "yyyy-mm-dd": 22, // ISO 日期格式 "yyyy-mm-dd;@": 22, // ISO 日期格式(带文本) "yyyy/mm/dd;@": 22, // ISO 日期格式(带文本) "[$-804]yyyy\"年\"mm\"月\"dd\"日\"": 31, // 中文日期格式 // 时间格式 "h:mm AM/PM": 18, // 12小时制时间 "h:mm:ss AM/PM": 19, // 12小时制时间(带秒) "h:mm": 20, // 24小时制时间 "h:mm:ss": 21, // 24小时制时间(带秒) "m/d/yy h:mm": 22, // 日期和时间 "mm:ss": 45, // 分:秒 "[h]:mm:ss": 46, // 超过24小时的时间 "mmss.0": 47, // 分秒.毫秒 // 其他格式 "#,##0 ;(#,##0)": 37, // 带括号的负数 "#,##0 ;[Red](#,##0)": 38, // 红色负数 "#,##0.00;(#,##0.00)": 39, // 带括号的负小数 "#,##0.00;[Red](#,##0.00)": 40, // 红色负小数 "@": 49, // 文本 } if id, ok := builtinFormats[format]; ok { return id } return 0 } // ToXML 将样式转换为XML func (s *Styles) ToXML() string { xml := "\n" xml += "\n" // 数字格式 if len(s.NumberFormats) > 0 { xml += fmt.Sprintf(" \n", len(s.NumberFormats)) for _, nf := range s.NumberFormats { // 处理格式代码中的引号,将其转换为XML实体引用 formatCode := nf.Code formatCode = strings.Replace(formatCode, "\"", """, -1) xml += fmt.Sprintf(" \n", nf.ID, formatCode) } xml += " \n" } // 字体 xml += fmt.Sprintf(" \n", len(s.Fonts)) for _, font := range s.Fonts { xml += " \n" if font.Bold { xml += " \n" } if font.Italic { xml += " \n" } if font.Underline { xml += " \n" } xml += fmt.Sprintf(" \n", font.Size) if font.Color != "" { xml += fmt.Sprintf(" \n", font.Color) } xml += fmt.Sprintf(" \n", font.Name) xml += " \n" } xml += " \n" // 填充 xml += fmt.Sprintf(" \n", len(s.Fills)) for _, fill := range s.Fills { xml += " \n" xml += fmt.Sprintf(" \n", fill.PatternType) if fill.FgColor != "" { xml += fmt.Sprintf(" \n", fill.FgColor) } if fill.BgColor != "" { xml += fmt.Sprintf(" \n", fill.BgColor) } xml += " \n" xml += " \n" } xml += " \n" // 边框 xml += fmt.Sprintf(" \n", len(s.Borders)) for _, border := range s.Borders { xml += " \n" // 左边框 xml += " \n", border.Left.Color) } xml += " \n" // 右边框 xml += " \n", border.Right.Color) } xml += " \n" // 上边框 xml += " \n", border.Top.Color) } xml += " \n" // 下边框 xml += " \n", border.Bottom.Color) } xml += " \n" xml += " \n" } xml += " \n" // 单元格样式XF xml += fmt.Sprintf(" \n", len(s.CellStyleXfs)) for _, xf := range s.CellStyleXfs { xml += " 0 { xml += fmt.Sprintf(" fontId=\"%d\" applyFont=\"1\"", xf.FontId) } if xf.FillId > 0 { xml += fmt.Sprintf(" fillId=\"%d\" applyFill=\"1\"", xf.FillId) } if xf.BorderId > 0 { xml += fmt.Sprintf(" borderId=\"%d\" applyBorder=\"1\"", xf.BorderId) } if xf.NumFmtId > 0 { xml += fmt.Sprintf(" numFmtId=\"%d\" applyNumberFormat=\"1\"", xf.NumFmtId) } if xf.Alignment != nil { xml += " applyAlignment=\"1\"" } xml += ">\n" if xf.Alignment != nil { xml += " \n", len(s.CellXfs)) for _, xf := range s.CellXfs { xml += " 0 { xml += fmt.Sprintf(" fontId=\"%d\" applyFont=\"1\"", xf.FontId) } else { xml += " fontId=\"0\"" } // 设置填充 if xf.FillId > 0 { xml += fmt.Sprintf(" fillId=\"%d\" applyFill=\"1\"", xf.FillId) } else { xml += " fillId=\"0\"" } // 设置边框 if xf.BorderId > 0 { xml += fmt.Sprintf(" borderId=\"%d\" applyBorder=\"1\"", xf.BorderId) } else { xml += " borderId=\"0\"" } // 设置数字格式 if xf.NumFmtId > 0 { xml += fmt.Sprintf(" numFmtId=\"%d\" applyNumberFormat=\"1\"", xf.NumFmtId) } else { xml += " numFmtId=\"0\"" } // 设置对齐 if xf.Alignment != nil { xml += " applyAlignment=\"1\"" } xml += ">\n" // 添加对齐信息 if xf.Alignment != nil { xml += " \n", len(s.CellStyles)) for _, style := range s.CellStyles { xml += fmt.Sprintf("