利用OpenXML获取Excel单元格背景色

利用OpenXML获取Excel单元格背景色

最近项目上遇到了关于Excel获取处理的问题,关于Excel单元格背景色的获取,水的文章都大同小异,都没注意到Excel单元格背景色是怎么赋值,这会导致出现有些背景色无法获取的情况。(PS:其实应该叫做前景色)

关于这点我们可以先来看一下,一个Excel文档的内部有关背景色样式代码。

Excel背景色样式解析

  • 这是一个样例Excel,我们给它赋上了一些背景色样式,如下图所示。
  • 但是在Excel的style.xml文件中,这些颜色的表现形式不尽相同。
xml 复制代码
-<fill>

<patternFill patternType="none"/>

</fill>


-<fill>

<patternFill patternType="gray125"/>

</fill>

这两种为excel自带的默认填充样式

  • 因此我们可以发现,前三种背景色,Excel中是直接赋予了RGB的色值。然而最后一种颜色却是使用了theme(主题色)和tint(插值)来表示。
    通过以上分析,我们可以得出Excel单元格背景色的两种表现方式:rgbtheme + tint。(PS:关于有的颜色为什么可以直接用rgb,有的颜色用theme加tint的方式表示,本人在微软官方下面提问了,但是没人鸟窝。)

代码实现

  • OK分析完了,上代码。
c# 复制代码
public string GetCellBackgroundColor(WorkbookPart workbookPart, Cell cell)
{
    if (cell == null || cell.StyleIndex == null) return null;
    CellFormat cellFormat = (CellFormat)workbookPart.WorkbookStylesPart.Stylesheet.CellFormats.ElementAt((int)cell.StyleIndex.Value);
    Fill fill = (Fill)workbookPart.WorkbookStylesPart.Stylesheet.Fills.ElementAt((int)cellFormat.FillId.Value);
    PatternFill patternFill = (PatternFill)fill.PatternFill;
    ThemePart themePart = workbookPart.ThemePart;
    Theme theme = themePart?.Theme;
    if (patternFill != null && patternFill.PatternType != null && patternFill.PatternType.Value == PatternValues.Solid)
    {
        if (patternFill.ForegroundColor != null)
        {
            if (patternFill.ForegroundColor.Rgb != null)
            {
                return "#" + patternFill.ForegroundColor.Rgb.Value;
            }
            else if (patternFill.ForegroundColor.Theme != null)
            {
                // 主题色获取
                string originalColor = ((Color2Type)theme.ThemeElements.ColorScheme.ElementAt((int)patternFill.ForegroundColor.Theme.Value)).RgbColorModelHex.Val;
                if (patternFill.ForegroundColor.Tint != null)
                {
                    // 颜色计算
                    return CalculateTintedColor(originalColor, patternFill.ForegroundColor.Tint);
                }
                else
                {
                    return "#" + originalColor;
                }
            }
        }
    }
    return null;
}

ublic static string CalculateTintedColor(string originalColor, double tint)
{
    // RGB转换
    int red = Convert.ToInt32(originalColor.Substring(0, 2), 16);
    int green = Convert.ToInt32(originalColor.Substring(2, 2), 16);
    int blue = Convert.ToInt32(originalColor.Substring(4, 2), 16);
    int interpolatedRed = 0;
    int interpolatedGreen = 0;
    int interpolatedBlue = 0;
    // 基于tint正负值的颜色计算
    if (tint > 0)
    {
        // 白色
        int white = 255;
        // 插值计算
        interpolatedRed = (int)Math.Round(red * (1 - tint) + white * tint);
        interpolatedGreen = (int)Math.Round(green * (1 - tint) + white * tint);
        interpolatedBlue = (int)Math.Round(blue * (1 - tint) + white * tint);
    }
    else
    {
        // 黑色
        int black = 0;
        // 插值计算
        interpolatedRed = (int)Math.Round(red * (1 + tint));
        interpolatedGreen = (int)Math.Round(green * (1 + tint));
        interpolatedBlue = (int)Math.Round(blue * (1 + tint));
        // 防止出现计算结果小于0的情况
        interpolatedRed = Math.Max(interpolatedRed, black);
        interpolatedGreen = Math.Max(interpolatedGreen, black);
        interpolatedBlue = Math.Max(interpolatedBlue, black);
    }
    // 计算结束后转化为16进制颜色
    string interpolatedColor = $"#{interpolatedRed:X2}{interpolatedGreen:X2}{interpolatedBlue:X2}";
    return interpolatedColor;
}

分享结束,如果这个分享对您有所帮助的话,请点个赞吧!

相关推荐
深澈Vincel2 小时前
我用 C# + WebView2 做了一个针对“流氓软件”的“一键清理工具“:架构实践与踩坑记录
c#
zlinear数据采集卡3 小时前
数据采集卡从入门到精通(7):流水线型ADC——级级接力,高速与高精的平衡术
开发语言·arm开发·嵌入式硬件·fpga开发·c#
阿部多瑞 ABU4 小时前
告别手工核图:基于 .NET + MuPDFCore 的 CAD 等轴测 PDF 材料表提取与新旧版本对比实战
后端·算法·ui·pdf·c#
条形码D5 小时前
DRG综合管理分析系统-目前已经支持CHS-DRG3.0
c#·drg·3.0分组器·drg分组器·chs-drg3.0分组器
Alex Gram1 天前
数据库同步工具PanguSync图文教程
java·mysql·postgresql·sqlserver·c#·数据库同步软件·数据库同步工具
头茬韭菜1 天前
第 10 篇:「Fluss 实战案例集」—— 完整解决方案与最佳实践
c#·linq·fluss
淡海水1 天前
01-05-运行时-JIT优化全景-内联去虚拟化边界检查消除
windows·c#·虚拟化·jit·内联·边界检查消除
波波0072 天前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
wujian83112 天前
怎么用千问生成word文档:从「格式崩」到「一键过」,AI导出鸭打通最后半厘米
人工智能·ai·c#·word·豆包·deepseek·ai导出鸭
zlinear数据采集卡2 天前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#