2012-05-25 17 views
6

Próbuję pobrać kolor tła komórki w arkuszu kalkulacyjnym Excel. Używam Open XML 2.0 SDK i jestem w stanie otworzyć plik * .xlsx i na przykład uzyskać wartości komórek. Moje kodu dla uzyskania background-color jest następujący:Uzyskiwanie koloru tła komórki w programie Excel przy użyciu 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; 
    } 

mój problem polega na tym, że PatternFill.BackgroundColor powraca właśnie liczbą naturalną, myślę, że jest to id stylu. Moim problemem jest to, że linia kodu

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

wraca z błędem, ponieważ jest null ... Stylesheet.Colors ... może to dlatego, że stosowany jest „wbudowany” w kolorze Excel - nie jest zdefiniowany własny kolor?!

Jakieś pomysły, w jaki sposób mogę "obliczyć" rzeczywistą liczbę kolorów z "wartości backGroundColor"?

+0

Klasa SpreadsheetReader nie istnieje w OPENXML 2,5 – Elmue

Odpowiedz

10

Wzór wypełnienia komórki w arkuszu kalkulacyjnym programu Excel to złożony z dwóch kolorów: Kolor tła i kolor pierwszego planu. Określenie koloru pierwszego planu jest tu trochę mylące. Nie jest to kolor czcionki, ale kolor pierwszego planu wypełnienia deseniem.

Na przykład, jeśli wypełnienie tła komórki z kolorem własnością releated PatternFill przedmiotu komórce jest ustawiony na wybrane wartości stałych kolorów, gdzie jako BackgroundColor obiekt jest nastawiony na system ForegroundColor kolor pierwszego planu. Właściwość PatternType obiektu PatternFill jest ustawiona na PatternValues.Solid.

Aby uzyskać wartość koloru tła komórki (pełne wypełnienie), należy przeanalizować właściwość dla obiektu zwolnionego obiektu PatternFill. Trzeba określenie „typ koloru” instancja oznacza:

  1. Automatyczny System kolor i kolor zależny
  2. Zindeksowana kolor.
  3. Kolor ARGB (alfa, czerwony, zielony i niebieski)
  4. Kolor oparty na motywach.
  5. Wartość odcienia zastosowana do koloru.

Aby uzyskać więcej informacji na temat różnych „typów kolorystycznych” patrz poniższy link.

Należy pamiętać, że znaczenie własności klasy ForegroundColor i BackgroundColor InnerText zależy od rodzaju koloru. Na przykład w przypadku koloru bazującego na obiekcie, właściwość InnerText jest ustawiona na indeks w kolekcji ColorScheme.

Poniższy przykład wyświetla wszystkie informacje kolor tła dla wszystkich komórek w dokumencie arkusza kalkulacyjnego:

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

Dziękuję za wspaniałą odpowiedź.Tylko jeden punkt do dodania: Jeśli nie zmienię stylu komórki, wiersz 'int cellStyleIndex = (int) theCell.StyleIndex.Value;' powoduje wyjątek null. Skąd mogę wiedzieć na pewno, że jest to styl domyślny i styl "co" (kolor itp.)? Z góry! – basti

+1

@chiffre: Wydaje mi się, że (testowałem), jeśli StyleIndex ma wartość null, musisz użyć indeksu 0 w stylu komórki. Jednak nie znalazłem o tym uwagi w otwartej specyfikacji xml. – Hans

+0

Dzięki za te informacje. Naprawdę istnieje potrzeba dobrego i pełnego opakowania - gdzie można po prostu wywołać "cell.GetColor" itd. (I to faktycznie działa;)) – basti