【问题标题】:Getting cell-backgroundcolor in Excel with Open XML 2.0使用 Openxml 2.0 在 Excel 中获取单元格背景颜色
【发布时间】:2012-05-25 14:27:35
【问题描述】:

我正在尝试获取 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.Colorsnull... ...可能是因为我在 excel 中使用了“内置”颜色 - 不是自定义颜色?!

有什么想法可以从“backGroundColor-Value”中“计算”出真实的颜色编号吗?

【问题讨论】:

标签: c# excel .net-4.0 openxml-sdk


【解决方案1】:

Excel 电子表格中单元格的填充模式是 由两种颜色组成:背景色和前景色。 前景色一词在这里有点误导。它不是 字体的颜色,但图案填充的前景色。

例如,如果您用纯色填充单元格的背景 单元格的相关PatternFill 对象的ForegroundColor 属性 设置为选择的纯色值,其中 BackgroundColor 对象 设置为系统前景色。 PatternType 的属性 PatternFill 对象设置为PatternValues.Solid

因此,要获得单元格背景的颜色值(实心填充),您必须分析 相关 PatternFill 对象的 ForegroundColor 属性。你必须 确定实例代表的“颜色类型”:

  1. 一种自动颜色和系统相关颜色
  2. 索引颜色。
  3. 一种 ARGB 颜色(alpha、红色、绿色和蓝色)
  4. 基于主题的颜色。
  5. 应用于颜色的色调值。

有关不同“颜色类型”的更多信息,请参阅以下内容 link.

请注意ForegroundColorBackgroundColorInnerText属性的含义 类取决于颜色类型。例如,在基于主题的颜色的情况下,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();
}

【讨论】:

  • 感谢您的出色回答。只需添加一点:如果我不更改单元格的样式,则行 `int cellStyleIndex = (int)theCell.StyleIndex.Value;` 会导致空异常。我怎么能确定它实际上是默认样式和“什么”样式(颜色等)?提前谢谢!
  • @chiffre:我认为(我做了一些测试)如果 StyleIndex 为空,你必须使用单元格样式索引 0。但是我没有在 open xml 规范中找到关于它的注释。
  • 感谢您提供的信息。确实需要一个好的和完整的包装器——你可以简单地调用“cell.GetColor”等。(这确实有效;))
  • 感谢您的详尽解释,但我发现您无法使用 ColorType.Theme 作为索引可靠地从 ThemeElements.ColorScheme 获取颜色:索引 0 和 1(通常为黑色/白色)已交换位置,以及索引 2 和 3。这些是主题的“Dark1”/“Light1”/“Dark2”/“Light2”颜色。我们可以指望这些索引总是被交换,还是我们需要以其他方式找到主题颜色?
  • 同样的代码也适用于字体属性。感谢您的帮助。备案:提取字体 id 并从 Fonts 属性中获取字体(类型 Font)。
【解决方案2】:

嗯,我有一个类似的用例,我需要测试哪个 RGB 颜色作为背景颜色应用到单元格。只需附加到您的函数中的代码,

backGroundColor = fill.PatternFill.BackgroundColor.Rgb.Value;
return backgroundColor;

这将返回单元格背景中使用的 Rgb 颜色值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 2014-03-03
    • 1970-01-01
    • 2013-11-07
    相关资源
    最近更新 更多