[英]Getting cell-backgroundcolor in Excel with Open XML 2.0
我正在尝试在 excel 电子表格中获取单元格的背景颜色。 例如,我正在使用 Open XML 2.0 SDK,并且能够打开 *.xlsx 文件并获取单元格值。 我获取背景颜色的代码如下:
public BackgroundColor GetCellBackColor(Cell theCell, SpreadsheetDocument document)
{
BackgroundColor backGroundColor = null;
WorkbookStylesPart styles = SpreadsheetReader.GetWorkbookStyles(document);
int cellStyleIndex = (int)theCell.StyleIndex.Value;
CellFormat cellFormat = (CellFormat)styles.Stylesheet.CellFormats.ChildElements[cellStyleIndex];
Fill fill = (Fill)styles.Stylesheet.Fills.ChildElements[(int)cellFormat.FillId.Value];
backGroundColor = fill.PatternFill.BackgroundColor;
return backGroundColor;
}
我的问题是, PatternFill.BackgroundColor
只返回一个自然数,我认为它是样式的 id。 我的问题是,那行代码
DocumentFormat.OpenXml.Spreadsheet.Color c = (DocumentFormat.OpenXml.Spreadsheet.Color)styles.Stylesheet.Colors.ChildElements[Int32.Parse(backGroundColor.InnerText)];
返回错误,因为Stylesheet.Colors
为null
... ...可能是因为我在 excel 中使用了“内置”颜色 - 不是自定义颜色?!
有什么想法可以从“backGroundColor-Value”中“计算”出真实的颜色编号吗?
Excel电子表格中单元格的填充图案由两种颜色组成:背景色和前景色。 前景色一词在这里有点误导。 它不是字体的颜色,而是图案填充的前景色。
例如,如果您使用纯色填充单元格的背景,则单元格的相关PatternFill
对象的ForegroundColor
属性设置为选择的纯色值,其中BackgroundColor
对象设置为系统前景色。 PatternFill
对象的PatternType
属性设置为PatternValues.Solid
。
因此,要获取单元格背景的颜色值(实心填充),您必须分析相关PatternFill
对象的ForegroundColor
属性。 您必须确定实例代表的“颜色类型”:
有关不同“颜色类型”的更多信息,请参见以下链接。
请注意ForegroundColor
和BackgroundColor
类的InnerText
属性的含义取决于颜色类型。 例如,在基于主题的颜色的情况下, InnerText
属性设置为ColorScheme
集合的索引。
以下示例打印电子表格文档中所有单元格的所有背景颜色信息:
public static PatternFill GetCellPatternFill(Cell theCell, SpreadsheetDocument document)
{
WorkbookStylesPart styles = SpreadsheetReader.GetWorkbookStyles(document);
int cellStyleIndex;
if (theCell.StyleIndex == null) // I think (from testing) if the StyleIndex is null
{ // then this means use cell style index 0.
cellStyleIndex = 0; // However I did not found it in the open xml
} // specification.
else
{
cellStyleIndex = (int)theCell.StyleIndex.Value;
}
CellFormat cellFormat = (CellFormat)styles.Stylesheet.CellFormats.ChildElements[cellStyleIndex];
Fill fill = (Fill)styles.Stylesheet.Fills.ChildElements[(int)cellFormat.FillId.Value];
return fill.PatternFill;
}
private static void PrintColorType(SpreadsheetDocument sd, DocumentFormat.OpenXml.Spreadsheet.ColorType ct)
{
if (ct.Auto != null)
{
Console.Out.WriteLine("System auto color");
}
if (ct.Rgb != null)
{
Console.Out.WriteLine("RGB value -> {0}", ct.Rgb.Value);
}
if (ct.Indexed != null)
{
Console.Out.WriteLine("Indexed color -> {0}", ct.Indexed.Value);
//IndexedColors ic = (IndexedColors)styles.Stylesheet.Colors.IndexedColors.ChildElements[(int)bgc.Indexed.Value];
}
if (ct.Theme != null)
{
Console.Out.WriteLine("Theme -> {0}", ct.Theme.Value);
Color2Type c2t = (Color2Type)sd.WorkbookPart.ThemePart.Theme.ThemeElements.ColorScheme.ChildElements[(int)ct.Theme.Value];
Console.Out.WriteLine("RGB color model hex -> {0}", c2t.RgbColorModelHex.Val);
}
if (ct.Tint != null)
{
Console.Out.WriteLine("Tint value -> {0}", ct.Tint.Value);
}
}
static void ReadAllBackgroundColors()
{
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open("c:\\temp\\bgcolor.xlsx", false))
{
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
foreach(WorksheetPart worksheetPart in workbookPart.WorksheetParts)
{
SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
foreach (Row r in sheetData.Elements<Row>())
{
foreach (Cell c in r.Elements<Cell>())
{
Console.Out.WriteLine("----------------");
PatternFill pf = GetCellPatternFill(c, spreadsheetDocument);
Console.Out.WriteLine("Pattern fill type -> {0}", pf.PatternType.Value);
if (pf.PatternType == PatternValues.None)
{
Console.Out.WriteLine("No fill color specified");
continue;
}
Console.Out.WriteLine("Summary foreground color:");
PrintColorType(spreadsheetDocument, pf.ForegroundColor);
Console.Out.WriteLine("Summary background color:");
PrintColorType(spreadsheetDocument, pf.BackgroundColor);
}
}
}
}
}
static void Main(string[] args)
{
ReadAllBackgroundColors();
}
好吧,我有一个类似的用例,在该用例中,我需要测试将哪种 RGB 颜色用作单元格的背景颜色。 只是附加到你的函数中的代码,
backGroundColor = fill.PatternFill.BackgroundColor.Rgb.Value;
return backgroundColor;
这将返回单元格背景中使用的 Rgb 颜色值。
汉斯的回答很棒! 我想添加它,因为我必须为某些列解析渐变填充。 这是我的解决方案:
我只是想获取 rgb 字符串,如果您的要求不同,则必须相应地更改返回类型。
public static IEnumerable<string> GetCellFillColors(string sheetName,
string addressName, WorkbookPart wbPart)
{
WorkbookStylesPart styles = wbPart.WorkbookStylesPart;
Sheet theSheet = wbPart.Workbook.Descendants<Sheet>().
Where(s => s.Name == sheetName).FirstOrDefault();
// Throw an exception if there is no sheet.
if (theSheet == null)
{
throw new ArgumentException("sheetName");
}
// Retrieve a reference to the worksheet part.
WorksheetPart wsPart =
(WorksheetPart)(wbPart.GetPartById(theSheet.Id));
// Use its Worksheet property to get a reference to the cell
// whose address matches the address you supplied.
Cell theCell = wsPart.Worksheet.Descendants<Cell>().
Where(c => c.CellReference == addressName).FirstOrDefault();
int cellStyleIndex;
if (theCell.StyleIndex == null) // I think (from testing) if the StyleIndex is null
{ // then this means use cell style index 0.
cellStyleIndex = 0; // However I did not found it in the open xml
} // specification.
else
{
cellStyleIndex = (int)theCell.StyleIndex.Value;
}
CellFormat cellFormat = (CellFormat)styles.Stylesheet.CellFormats.ChildElements[cellStyleIndex];
DocumentFormat.OpenXml.Spreadsheet.Fill fill = (DocumentFormat.OpenXml.Spreadsheet.Fill)styles.Stylesheet.Fills.ChildElements[(int)cellFormat.FillId.Value];
if (fill.PatternFill != null)
{
return fill.PatternFill?.BackgroundColor?.Rgb?.ToString() != null ?
new List<string>()
{
fill.PatternFill?.BackgroundColor?.Rgb?.ToString()
} : new List<string>();
}
if (fill.GradientFill != null)
{
var colors = fill.GradientFill.ChildElements.Select(e => (DocumentFormat.OpenXml.Spreadsheet.GradientStop)e);
return colors?.Select(c => c?.Color.Rgb?.ToString());
}
return null;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.