excel文档读取不到字体颜色的解决方式

153 阅读4分钟

事情是这样开始的-公司有一个需求,读取excel文档,并要求读取到表格的格式字体等。 本次使用语言:golang + 第三方包 github.com/xuri/excelize/v2 代码贴在最后(只截取读字体部分) 其他语言思路相同

1、发现问题

在程序执行解析的过程中却没有解析到字体的颜色而表格明明对字体进行了颜色设置成白色。如下图

image.png 代码执行解析却没有读出颜色,tnd真是奇了怪了 image.png

(执行读取结果)

2、分析问题

折腾了好一会儿还是没有发现问题出在哪里就开始看这个使用到的第三方包的源码,发现fond对象的结构如下:

image.png 发现了有其他color字段,不妨先看看各自代表的是什么

Color 颜色
ColorIndexed 颜色索引
ColorTheme 颜色主题
ColorTint 色彩

进行输出看看具体输出什么内容:如下

style.Font.Color :=  
style.Font.ColorIndexed :=  0
style.Font.ColorTheme :=  0
style.Font.ColorTint :=  0
style.Font.Color :=  
style.Font.ColorIndexed :=  0
style.Font.ColorTheme :=  1
style.Font.ColorTint :=  0
style.Font.Color :=  
style.Font.ColorIndexed :=  0
style.Font.ColorTheme :=  2
style.Font.ColorTint :=  0
style.Font.Color :=  
style.Font.ColorIndexed :=  0
style.Font.ColorTheme :=  3
style.Font.ColorTint :=  0
style.Font.Color :=  
style.Font.ColorIndexed :=  0
style.Font.ColorTheme :=  4
style.Font.ColorTint :=  0

这些奇奇怪怪的数字又代表的什么呢,以下是我查询的资料

ColorIndexed

image.png

ColorTheme 则是按照你选择的颜色顺序(从0开始)

image.png

结论-解决

现在结论已经很明显了,程序读到的是主题的颜色而不是字体的颜色,所以就导致了字体的颜色读不到。 那么我就想要读取到字体的颜色应该怎么做呢。好家伙原来直接点击次数:如下。设置的是主题颜色

image.png 实际上设置的是主题颜色,想要设置字体颜色需要这么做

image.png 点击下拉标识,选择标准色,如果标准色没有自己想要的颜色,直接点击其他颜色即可。再一次运行

style.Font.Color :=  C00000
style.Font.ColorIndexed :=  0
style.Font.ColorTint :=  0
style.Font.Color :=  FF0000
style.Font.ColorIndexed :=  0
style.Font.ColorTint :=  0
style.Font.Color :=  FFC000
style.Font.ColorIndexed :=  0
style.Font.ColorTint :=  0
style.Font.Color :=  FFFF00
style.Font.ColorIndexed :=  0
style.Font.ColorTint :=  0
style.Font.Color :=  92D050
style.Font.ColorIndexed :=  0
style.Font.ColorTint :=  0

综合解决方案:如果字体颜色取不到,那么就取主题的颜色;根据主题颜色的下标和颜色的偏离度进行计算得出最终的颜色。

字体颜色就出来了。tnd

go代码

import (
    "fmt"
    "github.com/xuri/excelize/v2"
    "log"
    "math"
    "strconv"
    "testing"
)

func TestReadExcel(t *testing.T) {
    ImportSystemTemp()
}

func ImportSystemTemp() {

    path := "C:\Users\wurho\Desktop\你好.xlsx"
    // 打开 Excel 文件
    f, err := excelize.OpenFile(path)
    if err != nil {
       log.Fatalf("无法打开文件: %v", err)
    }
    // 获取第一个工作表的名称
    sheetName := f.GetSheetName(0)
    // 获取所有行
    rows, err := f.GetRows(sheetName)
    if err != nil {
       log.Fatalf("无法获取行: %v", err)
    }

    colMap := make(map[string]interface{})
    // 获取单元格的合并信息
    for rowIndex, row := range rows {

       for colIndex, _ := range row {

          columnLetter := ToAlphaString(colIndex + 1)
          colMap[columnLetter] = 1

          // 获取单元格样式
          GetCssStyle(f, sheetName, rowIndex, columnLetter)

       }
    }

}

func GetCssStyle(f *excelize.File, sheetName string, rowIndex int, columnLetter string) map[string]string {
    // 获取单元格样式
    styleID, err := f.GetCellStyle(sheetName, columnLetter+strconv.Itoa(rowIndex+1))
    if err != nil {
       log.Fatalf("无法获取单元格样式: %v", err)
    }

    // 获取样式对象
    style, err := f.GetStyle(styleID)
    if err != nil {
       log.Fatalf("无法获取样式对象: %v", err)
    }

    cssStyle := make(map[string]string)

    // 处理字体样式
    if style.Font != nil {

       if style.Font.Color != "" {
          cssStyle["color"] = "#" + style.Font.Color
       }
       if style.Font.ColorTheme != nil {
          cssStyle["color"] = "#" + GetColor(*style.Font.ColorTheme, style.Font.ColorTint)
       }
    }
    fmt.Println(cssStyle["color"])
    return cssStyle
}

func ToAlphaString(n int) string {
    var result string
    for n > 0 {
       n--
       result = string(rune('A'+n%26)) + result
       n /= 26
    }
    return result
}

func GetColor(theme int, tint float64) string {
    color := ""
    switch theme {
    case 0:
       color = "ffffff"
    case 1:
       color = "000000"
    case 2:
       color = "eeece1"
    case 3:
       color = "1f497d"
    case 4:
       color = "4f81bd"
    case 5:
       color = "c0504d"
    case 6:
       color = "9bbb59"
    case 7:
       color = "8064a1"
    case 8:
       color = "4bacc6"
    case 9:
       color = "f79646"
    default:
       color = "000000"
    }
    if tint != 0 {
       // 2. 将十六进制转为 RGB 分量
       r, g, b := hexToRGB(color)
       // 3. 应用亮度调整公式
       if tint < 0 {
          // 变暗:RGB = RGB * (1 + tint)
          factor := 1 + tint
          r *= factor
          g *= factor
          b *= factor
       } else if tint > 0 {
          // 变亮:RGB = RGB + (255 - RGB) * tint
          r += (255 - r) * tint
          g += (255 - g) * tint
          b += (255 - b) * tint
       }

       // 4. 四舍五入并限制范围(0-255)
       r = clamp(r)
       g = clamp(g)
       b = clamp(b)

       // 5. 转回十六进制
       return fmt.Sprintf("%02X%02X%02X", int(r), int(g), int(b))
    }

    return color
}

// 辅助函数:十六进制转 RGB(返回浮点数)
func hexToRGB(hex string) (r, g, b float64) {
    if len(hex) != 6 {
       return 255, 255, 255 // 默认白色
    }
    parse := func(s string) float64 {
       var val uint8
       fmt.Sscanf(s, "%02X", &val)
       return float64(val)
    }
    r = parse(hex[0:2])
    g = parse(hex[2:4])
    b = parse(hex[4:6])
    return
}

// 限制颜色值在 0-255 范围内
func clamp(value float64) float64 {
    return math.Max(0, math.Min(255, math.Round(value)))
}