Porównaj ceny domen i usług IT, sprzedawców z całego świata

Style komórek w arkuszu kalkulacyjnym OpenXML (SpreadsheetML)


Utworzyłem arkusz kalkulacyjny .xlsx w C # przy użyciu OpenXML SDK, ale nie mogę dowiedzieć się, jak sprawić, by style komórek działały. Przeglądałem pliki utworzone w programie Excel i nie mogę dowiedzieć się, jak to się robi.
Teraz tworzę wypełnienie, tworzę CellstyleFormat , co wskazuje na wypełnienie, utwórz CellFormat , co wskazuje indeks
CellstyleFormat
, a następnie Utwórz Cellstyle Wskazuje
CellFormat
.
Oto kod, którego używam, aby utworzyć dokument:
Console.WriteLine("Creating document");
using (var spreadsheet = SpreadsheetDocument.Create("output.xlsx", SpreadsheetDocumentType.Workbook))
{
Console.WriteLine("Creating workbook");
spreadsheet.AddWorkbookPart();
spreadsheet.WorkbookPart.Workbook = new Workbook();
Console.WriteLine("Creating worksheet");
var wsPart = spreadsheet.WorkbookPart.AddNewPart<WorksheetPart>();
wsPart.Worksheet = new Worksheet(); var stylesPart = spreadsheet.WorkbookPart.AddNewPart<WorkbookStylesPart>();
stylesPart.Stylesheet = new Stylesheet();
stylesPart.Stylesheet.Fills = new Fills();// create a solid red fill
var solidRed = new PatternFill() { PatternType = PatternValues.Solid };
solidRed.AppendChild(new BackgroundColor { Rgb = HexBinaryValue.FromString("FF00FF00") }); stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill() { PatternType = PatternValues.None } });
stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = solidRed });
stylesPart.Stylesheet.CellStyleFormats = new CellStyleFormats();
stylesPart.Stylesheet.CellStyleFormats.AppendChild(new CellFormat { FillId = 0, ApplyFill = false });
stylesPart.Stylesheet.CellStyleFormats.AppendChild(new CellFormat { FillId = 1, ApplyFill = true });
stylesPart.Stylesheet.CellFormats = new CellFormats();
stylesPart.Stylesheet.CellFormats.AppendChild(new CellFormat { FormatId = 0 });
stylesPart.Stylesheet.CellFormats.AppendChild(new CellFormat { FormatId = 1 });
stylesPart.Stylesheet.CellStyles = new CellStyles();
stylesPart.Stylesheet.CellStyles.AppendChild(new CellStyle { Name = "None", FormatId = 0 });
stylesPart.Stylesheet.CellStyles.AppendChild(new CellStyle { Name = "Solid Red", FormatId = 1 }); stylesPart.Stylesheet.Save(); Console.WriteLine("Creating sheet data");
var sheetData = wsPart.Worksheet.AppendChild(new SheetData()); Console.WriteLine("Adding rows/cells..."); var row = sheetData.AppendChild(new Row());
row.AppendChild(new Cell() { CellValue = new CellValue("This"), DataType = CellValues.String });
row.AppendChild(new Cell() { CellValue = new CellValue("is"), DataType = CellValues.String });
row.AppendChild(new Cell() { CellValue = new CellValue("a"), DataType = CellValues.String });
row.AppendChild(new Cell() { CellValue = new CellValue("test."), DataType = CellValues.String }); sheetData.AppendChild(new Row()); row = sheetData.AppendChild(new Row());
row.AppendChild(new Cell() { CellValue = new CellValue("Value:"), DataType = CellValues.String });
row.AppendChild(new Cell() { CellValue = new CellValue("123"), DataType = CellValues.Number });
row.AppendChild(new Cell() { CellValue = new CellValue("Formula:"), DataType = CellValues.String });
row.AppendChild(new Cell() { CellFormula = new CellFormula("B3"), StyleIndex = 1 });// Console.WriteLine("Saving worksheet");
wsPart.Worksheet.Save(); Console.WriteLine("Creating sheet list");
var sheets = spreadsheet.WorkbookPart.Workbook.AppendChild(new Sheets());
sheets.AppendChild(new Sheet() { Id = spreadsheet.WorkbookPart.GetIdOfPart(wsPart), SheetId = 1, Name = "Test" }); Console.WriteLine("Saving workbook");
spreadsheet.WorkbookPart.Workbook.Save(); Console.WriteLine("Done.");
}

Oto wygenerowany XML:

workbook.xml

<?xml version="1.0" encoding="utf-8"?>
<x:workbook xmlns:x="[url=http://schemas.openxmlformats.org/spreadsheetml/2006/main">]http://schemas.openxmlformats. ... gt%3B[/url]
<x:sheets>
<x:sheet name="Test" sheetId="1" r:id="Rbad86b8c80844a16" xmlns:r="[url=http://schemas.openxmlformats.org/officeDocument/2006/relationships"/>]http://schemas.openxmlformats. ... gt%3B[/url]
</x:sheets>
</x:workbook>


styles.xml

<?xml version="1.0" encoding="utf-8"?>
<x:styleSheet xmlns:x="[url=http://schemas.openxmlformats.org/spreadsheetml/2006/main">]http://schemas.openxmlformats. ... gt%3B[/url]
<x:fills>
<x:fill>
<x:patternFill patternType="none"/>
</x:fill>
<x:fill>
<x:patternFill patternType="solid">
<x:bgColor rgb="FF00FF00"/>
</x:patternFill>
</x:fill>
</x:fills>
<x:cellStyleXfs>
<x:xf fillId="0" applyFill="0"/>
<x:xf fillId="1" applyFill="1"/>
</x:cellStyleXfs>
<x:cellXfs>
<x:xf xfId="0"/>
<x:xf xfId="1"/>
</x:cellXfs>
<x:cellStyles>
<x:cellStyle name="None" xfId="0"/>
<x:cellStyle name="Solid Red" xfId="1"/>
</x:cellStyles>
</x:styleSheet>


worksheets/sheet.xml

<?xml version="1.0" encoding="utf-8"?>
<x:worksheet xmlns:x="[url=http://schemas.openxmlformats.org/spreadsheetml/2006/main">]http://schemas.openxmlformats. ... gt%3B[/url]
<x:sheetData>
<x:row>
<x:c t="str"><x:v>This</x:v></x:c>
<x:c t="str"><x:v>is</x:v></x:c>
<x:c t="str"><x:v>a</x:v></x:c>
<x:c t="str"><x:v>test.</x:v></x:c>
</x:row>
<x:row/>
<x:row>
<x:c t="str"><x:v>Value:</x:v></x:c>
<x:c t="n"><x:v>123</x:v></x:c>
<x:c t="str"><x:v>Formula:</x:v></x:c>
<x:c s="1"><x:f>B3</x:f></x:c>
</x:row>
</x:sheetData>
</x:worksheet>

Ostatnia komórka ostatniego wiersza to miejsce, w którym próbuję dodać styl.
Wszystko to sprawdza się poprawnie, gdy uruchamiam go za pomocą narzędzia wydajności OpenXML SDK, ale kiedy próbuję otworzyć plik w programie Excel, pojawia się następujący błąd:

Odzyskane rekordy: Format z/XL/Styles.xml Część (style)

Następnie wyświetlany jest arkusz kalkulacyjny, ale wypełnienie nie ma zastosowania.
Jakieś pomysły, jak to naprawić?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Tak, udało mi się to rozgryźć po wielu eksperymentach.
Okazuje się, że programy Excel Reserves Style 0 i 1 dla normalnych komórek i wzoru "Gray125" napełniają odpowiednio. Większość powyższego kodu można usunąć, ponieważ w rzeczywistości potrzebujemy tylko
CellFormat
.
Kod pracujący:
Console.WriteLine("Creating document");
using (var spreadsheet = SpreadsheetDocument.Create("output.xlsx", SpreadsheetDocumentType.Workbook))
{
Console.WriteLine("Creating workbook");
spreadsheet.AddWorkbookPart();
spreadsheet.WorkbookPart.Workbook = new Workbook();
Console.WriteLine("Creating worksheet");
var wsPart = spreadsheet.WorkbookPart.AddNewPart<WorksheetPart>();
wsPart.Worksheet = new Worksheet(); var stylesPart = spreadsheet.WorkbookPart.AddNewPart<WorkbookStylesPart>();
stylesPart.Stylesheet = new Stylesheet(); Console.WriteLine("Creating styles");// blank font list
stylesPart.Stylesheet.Fonts = new Fonts();
stylesPart.Stylesheet.Fonts.Count = 1;
stylesPart.Stylesheet.Fonts.AppendChild(new Font());// create fills
stylesPart.Stylesheet.Fills = new Fills();// create a solid red fill
var solidRed = new PatternFill() { PatternType = PatternValues.Solid };
solidRed.ForegroundColor = new ForegroundColor { Rgb = HexBinaryValue.FromString("FFFF0000") };// red fill
solidRed.BackgroundColor = new BackgroundColor { Indexed = 64 }; stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill { PatternType = PatternValues.None } });// required, reserved by Excel
stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill { PatternType = PatternValues.Gray125 } });// required, reserved by Excel
stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = solidRed });
stylesPart.Stylesheet.Fills.Count = 3;// blank border list
stylesPart.Stylesheet.Borders = new Borders();
stylesPart.Stylesheet.Borders.Count = 1;
stylesPart.Stylesheet.Borders.AppendChild(new Border());// blank cell format list
stylesPart.Stylesheet.CellStyleFormats = new CellStyleFormats();
stylesPart.Stylesheet.CellStyleFormats.Count = 1;
stylesPart.Stylesheet.CellStyleFormats.AppendChild(new CellFormat());// cell format list
stylesPart.Stylesheet.CellFormats = new CellFormats();
// empty one for index 0, seems to be required
stylesPart.Stylesheet.CellFormats.AppendChild(new CellFormat());
// cell format references style format 0, font 0, border 0, fill 2 and applies the fill
stylesPart.Stylesheet.CellFormats.AppendChild(new CellFormat { FormatId = 0, FontId = 0, BorderId = 0, FillId = 2, ApplyFill = true }).AppendChild(new Alignment { Horizontal = HorizontalAlignmentValues.Center });
stylesPart.Stylesheet.CellFormats.Count = 2; stylesPart.Stylesheet.Save(); Console.WriteLine("Creating sheet data");
var sheetData = wsPart.Worksheet.AppendChild(new SheetData()); Console.WriteLine("Adding rows/cells..."); var row = sheetData.AppendChild(new Row());
row.AppendChild(new Cell() { CellValue = new CellValue("This"), DataType = CellValues.String });
row.AppendChild(new Cell() { CellValue = new CellValue("is"), DataType = CellValues.String });
row.AppendChild(new Cell() { CellValue = new CellValue("a"), DataType = CellValues.String });
row.AppendChild(new Cell() { CellValue = new CellValue("test."), DataType = CellValues.String }); sheetData.AppendChild(new Row()); row = sheetData.AppendChild(new Row());
row.AppendChild(new Cell() { CellValue = new CellValue("Value:"), DataType = CellValues.String });
row.AppendChild(new Cell() { CellValue = new CellValue("123"), DataType = CellValues.Number });
row.AppendChild(new Cell() { CellValue = new CellValue("Formula:"), DataType = CellValues.String });
// style index = 1, i.e. point at our fill format
row.AppendChild(new Cell() { CellFormula = new CellFormula("B3"), DataType = CellValues.Number, StyleIndex = 1 }); Console.WriteLine("Saving worksheet");
wsPart.Worksheet.Save(); Console.WriteLine("Creating sheet list");
var sheets = spreadsheet.WorkbookPart.Workbook.AppendChild(new Sheets());
sheets.AppendChild(new Sheet() { Id = spreadsheet.WorkbookPart.GetIdOfPart(wsPart), SheetId = 1, Name = "Test" }); Console.WriteLine("Saving workbook");
spreadsheet.WorkbookPart.Workbook.Save(); Console.WriteLine("Done.");
}

Kilka wskazówek:

Użyj ClosedXML, jeśli chcesz uniknąć tego szaleństwa.
>

Nie mogę polecić

ClosedXML
https://github.com/closedxml/closedxml
wystarczająco wysokie, jeśli wykonujesz tego rodzaju pracę.

Format API OpenXML i strasznie żmudny do pracy w sobie, ze wszystkimi typami nieudokumentowanych przypadków. Closedxml robi dla ciebie tyle nóg. Są również bardzo dobrzy w szybkiej korekcji błędów.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Bardziej powszechna odpowiedź, znalazłem to wszystko po testowaniu, więc brak dokumentacji, na której można określić.
Po zainstalowaniu kolekcji
CellFormats
w arkuszu stylów program Excel przeprowadza dokładniejszą weryfikację.
CellFormats Nie można pusty, powinien mieć co najmniej jeden CellFormat .
Gdy tylko dodasz CellFormat , Excel narzeknie, jeśli wypełnia ,
Czcionki
lub
Borders
lub
Granice
są puste.
Najpierw Czcionka jest domyślnie używana dla całej książki, a także nagłówki kolumnowe/strun w programie Excel.
Excel zignoruje pierwszy element
CellFormat
, więc po prostu dodaj puste.
Jeśli potrzebujesz
Granicy
lub
Wypełnij
w formacie, program Excel ignoruje również pierwszy Granicy i
Wypełnij
, więc także dodaj Opróżnij jako pierwszy potomek w
Granice
i
wypełnia
.
Wreszcie, począwszy od drugiego
CellFormat
( S = "1" ), możesz iść.
Testowany w Excel 2010.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się