2012-05-25 22 views
6

Estoy tratando de obtener el color de fondo de una celda en una hoja de cálculo de Excel. Estoy usando Open XML 2.0 SDK y puedo abrir el archivo * .xlsx y obtener valores de celda, por ejemplo. Mi código para conseguir el color de fondo es la siguiente:Obtener cell-backgroundcolor en Excel con Open XML 2.0

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; 
    } 

Mi problema aquí es que PatternFill.BackgroundColor vuelve simplemente un número natural, creo que es el id del estilo. Mi problema es que la línea de código

DocumentFormat.OpenXml.Spreadsheet.Color c = (DocumentFormat.OpenXml.Spreadsheet.Color)styles.Stylesheet.Colors.ChildElements[Int32.Parse(backGroundColor.InnerText)]; 

devuelve un error, porque es Stylesheet.Colorsnull ... ... tal vez es porque he usado un "construido en" color en Excel - no es un auto-definido ¡¿color?!

Alguna idea de cómo podría "calcular" el número de color real de "backGroundColor-Value"?

+0

El SpreadsheetReader clase no existe en OpenXML 2,5 – Elmue

Respuesta

10

El patrón de relleno de una celda en una hoja de cálculo de Excel es compuesto por dos colores: el color de fondo y el color de primer plano. El término color de primer plano es un poco engañoso aquí. No es el color de la fuente, sino el color de primer plano del relleno de patrón.

Por ejemplo, si se llena el fondo de una celda con un color sólido la propiedad ForegroundColor del releated PatternFill objeto de la célula se establece en el valor del color sólido elegido en el que el objeto BackgroundColor se establece en el sistema color de primer plano. La propiedad PatternType del objeto PatternFill se establece en PatternValues.Solid.

Por lo tanto, para obtener el valor del color del fondo de su celda (relleno sólido), debe analizar la propiedad ForegroundColor del objeto PatternFill reticulado. Tienes que determinar el "tipo de color de" la instancia representa: color dependiente del

  1. Un color y sistema automático
  2. Un color indexado.
  3. Un color ARGB (alfa, rojo, verde y azul)
  4. Un color basado en el tema.
  5. Un valor de tinte aplicado al color.

Para obtener más información acerca de los diferentes tipos de color "" En la siguiente link.

Tenga en cuenta que el sentido de la propiedad de la clase InnerTextForegroundColor y BackgroundColor depende del tipo de color. Por ejemplo, en el caso de un color basado en tema, la propiedad InnerText se establece en el índice en la colección ColorScheme.

el siguiente ejemplo se imprime toda la información de color de fondo para todas las celdas de una hoja de cálculo:

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(); 
} 
+0

Gracias por su gran respuesta.Solo un punto para agregar: si no cambio el estilo de una celda, la línea 'int cellStyleIndex = (int) theCell.StyleIndex.Value;' causa una excepción nula. ¿Cómo puedo estar seguro de que en realidad es el estilo predeterminado y el estilo "qué" (color, etc.)? Thx por adelantado! – basti

+1

@chiffre: Creo (hice algunas pruebas) si StyleIndex es nulo, debe usar el índice de estilo de celda 0. Sin embargo, no encontré una nota al respecto en la especificación xml abierta. – Hans

+0

Gracias por esa información. Realmente existe la necesidad de un envoltorio bueno y completo, donde simplemente se puede llamar a "cell.GetColor", etc. (y eso realmente funciona;)) – basti

Cuestiones relacionadas