2012-05-25 12 views
6

Sto cercando di ottenere il backgroundcolor di una cella in un foglio di calcolo Excel. Sto usando Open XML 2.0 SDK e sono in grado di aprire il file * .xlsx e di ottenere valori di cella per esempio. Il mio codice per ottenere il background-color è la seguente:Ottenere cell-backgroundcolor in 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; 
    } 

Il mio problema qui è, che PatternFill.BackgroundColor restituisce solo un numero naturale, penso che sia l'id dello stile. Il mio problema è che la riga di codice

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

ritorna con un errore, perché è Stylesheet.Colorsnull ... ... forse è perché ho usato un "costruito nel" Colore in Excel - non è un auto-definito colore?!

Qualche idea su come "calcolare" il numero di colore reale da "backGroundColor-Value"?

+0

Lo SpreadsheetReader classe non esiste in OpenXML 2.5 – Elmue

risposta

10

Il modello di riempimento di una cella in un foglio di calcolo Excel è composto da due colori: il colore di sfondo e il colore di primo piano. Il termine colore in primo piano è un po 'fuorviante qui. Non è il colore del carattere ma il colore di primo piano del riempimento del motivo.

Per esempio se si riempire lo sfondo di una cella con un colore solido la ForegroundColor proprietà del releated PatternFill oggetto della cella è impostato il valore del colore solido scelto dove, come La BackgroundColor oggetto è impostato sul sistema di colore di primo piano. La proprietà PatternType dell'oggetto PatternFill è impostata su PatternValues.Solid.

Quindi, per ottenere il valore del colore dello sfondo della cella (riempimento solido), è necessario analizzare la proprietà dell'oggetto PatternFill relea. Devi determinare il "tipo di colore" dell'istanza rappresenta:

  1. Un colore automatico e sistema di colorazione diversa a seconda
  2. Una scala di colore.
  3. Un colore ARGB (alfa, rosso, verde e blu)
  4. Un colore basato sul tema.
  5. Un valore di tinta applicata al colore.

Per ulteriori informazioni sui diversi tipi di colore "" vedere il seguente link.

Si prega di notare che il significato della InnerText proprietà della classe ForegroundColor e BackgroundColor dipende dal tipo di colore. Ad esempio, nel caso di un colore basato su un tema, la proprietà InnerText viene impostata sull'indice nella raccolta ColorScheme.

L'esempio seguente stampa tutte le informazioni colore di sfondo per tutte le celle di un foglio elettronico:

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

Grazie per la vostra grande risposta.Un solo punto da aggiungere: se non cambio lo stile di una cella, la riga 'int cellStyleIndex = (int) theCell.StyleIndex.Value;' provoca un'eccezione nulla. Come posso sapere con certezza che in realtà è lo stile predefinito e lo stile "cosa" (colore ecc.)? Grazie in anticipo! – basti

+1

@chiffre: Penso che (ho fatto qualche test) se StyleIndex è nullo devi usare lo stile di cella indice 0. Tuttavia non ho trovato una nota a riguardo nella specifica xml aperta. – Hans

+0

Grazie per questa informazione. C'è davvero bisogno di un wrapper buono e completo - dove puoi semplicemente chiamare "cell.GetColor" ecc. (E che funziona davvero;)) – basti