利用OpenXML獲取Excel單元格背景色 最近項目上遇到了關於Excel獲取處理的問題,關於Excel單元格背景色的獲取,水的文章都大同小異,都沒註意到Excel單元格背景色是怎麼賦值,這會導致出現有些背景色無法獲取的情況。(PS:其實應該叫做前景色) 關於這點我們可以先來看一下,一個Excel ...
利用OpenXML獲取Excel單元格背景色
最近項目上遇到了關於Excel獲取處理的問題,關於Excel單元格背景色的獲取,水的文章都大同小異,都沒註意到Excel單元格背景色是怎麼賦值,這會導致出現有些背景色無法獲取的情況。(PS:其實應該叫做前景色)
關於這點我們可以先來看一下,一個Excel文檔的內部有關背景色樣式代碼。
Excel背景色樣式解析
- 這是一個樣例Excel,我們給它賦上了一些背景色樣式,如下圖所示。
- 但是在Excel的style.xml文件中,這些顏色的表現形式不盡相同。
-<fill>
<patternFill patternType="none"/>
</fill>
-<fill>
<patternFill patternType="gray125"/>
</fill>
這兩種為excel自帶的預設填充樣式
- 因此我們可以發現,前三種背景色,Excel中是直接賦予了RGB的色值。然而最後一種顏色卻是使用了theme(主題色)和tint(插值)來表示。
通過以上分析,我們可以得出Excel單元格背景色的兩種表現方式:rgb
和theme + tint
。(PS:關於有的顏色為什麼可以直接用rgb,有的顏色用theme加tint的方式表示,本人在微軟官方下麵提問了,但是沒人鳥窩。)
代碼實現
- OK分析完了,上代碼。
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;
}
public 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;
}
分享結束,如果這個分享對您有所幫助的話,請點個贊吧!