Filling a cell with a solid color, using OpenXML that preserves otherwise existing sheet format

*爱你&永不变心* 提交于 2021-01-29 11:00:00

问题


The following takes the format of existing sheet sSheet and creates a red font (along with some timestamp content) at A19:

using (SpreadsheetDocument document = SpreadsheetDocument.Open(sPath, true)) {
 IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sSheet);
 WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheets.FirstOrDefault().Id);


 Worksheet worksheet = worksheetPart.Worksheet;
 WorkbookStylesPart styles = document.WorkbookPart.WorkbookStylesPart;
 Stylesheet stylesheet = styles.Stylesheet;
 CellFormats cellformats = stylesheet.CellFormats;
 Fonts fonts = stylesheet.Fonts;

 UInt32 fontIndex = fonts.Count;
 UInt32 formatIndex = cellformats.Count;

 Cell cell = GetCell(worksheet, "A", 19);
 cell.CellValue = new CellValue(DateTime.Now.ToLongTimeString());
 cell.DataType = new EnumValue<CellValues>(CellValues.String);

 CellFormat f = (CellFormat)cellformats.ElementAt((int)cell.StyleIndex.Value);

 var font = (Font)fonts.ElementAt((int)f.FontId.Value);
 var newfont = (Font)font.Clone();
 newfont.Color = new Color() { Rgb = new HexBinaryValue("ff0000") };
 fonts.Append(newfont);

 CellFormat newformat = (CellFormat)f.Clone();
 newformat.FontId = fontIndex;
 cellformats.Append(newformat);
 stylesheet.Save();
 cell.StyleIndex = formatIndex;



 worksheetPart.Worksheet.Save();
 document.WorkbookPart.Workbook.Save();
 document.Close();
}

But I can't make it create a solid fill. I tried adding Fills fills = stylesheet.Fills; underneath Fonts fonts = stylesheet.Fonts;, as well as adding some wording that uses similar Fill language underneath the

var font = (Font)fonts.ElementAt((int)f.FontId.Value);
var newfont = (Font)font.Clone();
newfont.Color = new Color() { Rgb = new HexBinaryValue("ff0000") };
fonts.Append(newfont);

...as well as a lot of variations to it, but nothing compiled. I cannot figure out how to add a solid color fill. Any help is much appreciated. Thank you.


回答1:


I obtained the code that follows by creating two basically "empty" workbooks, one with a cell having the background color, the other with no background color. I then opened the latter using the Open XML SDK Productivity Tool and used it to compare with the workbook having a background fill. This yields the code to turn the one into the other.

As you can see, it's necessary to create a new Fill with PatternFill, BackgroundColor and ForegroundColorelements. This is added to the list ofCellFormats` so that it can be referenced by the cell on the worksheet.

    private void btnAddFillColor_Click(object sender, EventArgs e)
    {
        string filePath = "C:\\Test\\OpenXMLTest_NoFillColor.xlsx";

        using (SpreadsheetDocument document = SpreadsheetDocument.Open(filePath, true))
        {
            WorkbookPart wbPart = document.WorkbookPart;
            WorksheetPart wsPart = wbPart.WorksheetParts.FirstOrDefault();
            WorkbookStylesPart stylesPart = document.WorkbookPart.WorkbookStylesPart;
            ChangeWorkbookStylesPart(stylesPart);
            ChangeWorksheetPart(wsPart);
        }
    }

    private void ChangeWorkbookStylesPart(WorkbookStylesPart workbookStylesPart1)
    {
        xl.Stylesheet stylesheet1 = workbookStylesPart1.Stylesheet;

        xl.Fills fills1 = stylesheet1.GetFirstChild<xl.Fills>();
        xl.CellFormats cellFormats1 = stylesheet1.GetFirstChild<xl.CellFormats>();
        fills1.Count = (UInt32Value)3U;

        xl.Fill fill1 = new xl.Fill();

        xl.PatternFill patternFill1 = new xl.PatternFill() { PatternType = xl.PatternValues.Solid };
        xl.ForegroundColor foregroundColor1 = new xl.ForegroundColor() { Rgb = "FFC00000" };
        xl.BackgroundColor backgroundColor1 = new xl.BackgroundColor() { Indexed = (UInt32Value)64U };

        patternFill1.Append(foregroundColor1);
        patternFill1.Append(backgroundColor1);

        fill1.Append(patternFill1);
        fills1.Append(fill1);
        cellFormats1.Count = (UInt32Value)2U;

        xl.CellFormat cellFormat1 = new xl.CellFormat() { NumberFormatId = (UInt32Value)0U, FontId = (UInt32Value)0U, FillId = (UInt32Value)2U, BorderId = (UInt32Value)0U, FormatId = (UInt32Value)0U, ApplyFill = true };
        cellFormats1.Append(cellFormat1);
    }

    private void ChangeWorksheetPart(WorksheetPart worksheetPart1)
    {
        xl.Worksheet worksheet1 = worksheetPart1.Worksheet;

        xl.SheetData sheetData1 = worksheet1.GetFirstChild<xl.SheetData>();

        xl.Row row1 = sheetData1.GetFirstChild<xl.Row>();

        xl.Cell cell1 = row1.GetFirstChild<xl.Cell>();
        cell1.StyleIndex = (UInt32Value)1U;
    }



回答2:


Generate a xlsx file by calling ExportDataSetToExcellWithColour_openXML(your_dataset, your_destination_file_full_path.xlsx). If the file exists, it will be deleted first.

No other third-party lib is used except OpenXML.

Your DataTable should be like:

column a, column b, column c, color

abc, def, ghi, #FF0000

aa1, bb2, ccc, #FFFF00

Data of the column 'color' should be a hex color code. The column 'color' will be removed in the destination xlsx file, and each line will be painted with the specified color.

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;

......

public static void ExportDataSetToExcellWithColour_openXML(DataSet ds, string destination)
    {
        if (File.Exists(destination))
        {
            try
            {
                File.SetAttributes(destination, FileAttributes.Normal);
                File.Delete(destination);
            }
            catch { }
        }

        using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
        {
            var workbookPart = workbook.AddWorkbookPart();

            workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
            workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();

            #region deal with color
            List<string> colorCode = new List<string>();
            foreach (global::System.Data.DataTable table in ds.Tables)
            {
                if (table.Columns.Contains("color"))
                {
                    foreach (DataRow dr in table.Rows)
                    {
                        if (!colorCode.Contains(dr["color"].ToString()))
                        {
                            colorCode.Add(dr["color"].ToString());
                        }
                    }
                }
            }
            WorkbookStylesPart stylePart = workbook.WorkbookPart.AddNewPart<WorkbookStylesPart>();
            stylePart.Stylesheet = CreateStylesheet(colorCode);
            //stylePart.Stylesheet = CreateStylesheet_ori();

            stylePart.Stylesheet.Save();
            #endregion

            foreach (global::System.Data.DataTable table in ds.Tables)
            {
                DataTable ori_dt = null;
                if (table.Columns.Contains("color"))
                {
                    ori_dt = table.Clone();
                    foreach (DataRow dr in table.Rows)
                    {
                        ori_dt.Rows.Add(dr.ItemArray);
                    }
                    table.Columns.Remove("color");
                }

                var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
                var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
                sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);

                DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
                string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);

                uint sheetId = 1;
                if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
                {
                    sheetId =
                        sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
                }

                DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName };
                sheets.Append(sheet);

                DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();

                List<String> columns = new List<string>();
                foreach (global::System.Data.DataColumn column in table.Columns)
                {
                    columns.Add(column.ColumnName);

                    DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
                    cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
                    cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
                    headerRow.AppendChild(cell);
                }


                sheetData.AppendChild(headerRow);
                int rowindex = 0;
                foreach (global::System.Data.DataRow dsrow in table.Rows)
                {
                    DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
                    foreach (String col in columns)
                    {
                        DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
                        cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
                        cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
                        if (ori_dt.Columns.Contains("color"))
                        {
                            try
                            {
                                cell.StyleIndex =
                                    (
                                        (UInt32)colorCode.FindIndex(
                                            a => a == ori_dt.Rows[rowindex]["color"].ToString()
                                        )
                                    ) + 1;

                                //cell.StyleIndex = (UInt32)2;
                            }
                            catch (Exception ex)
                            {
                            }
                        }
                        newRow.AppendChild(cell);
                    }

                    sheetData.AppendChild(newRow);
                    rowindex++;
                }



            }
        }
    }

    public static Stylesheet CreateStylesheet(List<string> colorCode)
    {
        Stylesheet stylesheet1 = new Stylesheet() { MCAttributes = new MarkupCompatibilityAttributes() { Ignorable = "x14ac" } };
        stylesheet1.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
        stylesheet1.AddNamespaceDeclaration("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");

        DocumentFormat.OpenXml.Spreadsheet.Fonts fonts1 = new DocumentFormat.OpenXml.Spreadsheet.Fonts() { Count = (UInt32Value)1U, KnownFonts = true };

        DocumentFormat.OpenXml.Spreadsheet.Font font1 = new DocumentFormat.OpenXml.Spreadsheet.Font();
        DocumentFormat.OpenXml.Spreadsheet.FontSize fontSize1 = new DocumentFormat.OpenXml.Spreadsheet.FontSize() { Val = 11D };
        DocumentFormat.OpenXml.Spreadsheet.Color color1 = new DocumentFormat.OpenXml.Spreadsheet.Color() { Theme = (UInt32Value)1U };
        DocumentFormat.OpenXml.Spreadsheet.FontName fontName1 = new DocumentFormat.OpenXml.Spreadsheet.FontName() { Val = "Calibri" };
        FontFamilyNumbering fontFamilyNumbering1 = new FontFamilyNumbering() { Val = 2 };
        FontScheme fontScheme1 = new FontScheme() { Val = FontSchemeValues.Minor };

        font1.Append(fontSize1);
        font1.Append(color1);
        font1.Append(fontName1);
        font1.Append(fontFamilyNumbering1);
        font1.Append(fontScheme1);

        fonts1.Append(font1);

        Fills fills1 = new Fills() { Count = (UInt32)(colorCode.Count + 2) };

        // FillId = 0
        Fill fill1 = new Fill();
        PatternFill patternFill1 = new PatternFill() { PatternType = PatternValues.None };
        fill1.Append(patternFill1);
        fills1.Append(fill1);

        // FillId = 1
        Fill fill2 = new Fill();
        PatternFill patternFill2 = new PatternFill() { PatternType = PatternValues.Gray125 };
        fill2.Append(patternFill2);
        fills1.Append(fill2);

        foreach (string color in colorCode)
        {
            Fill fill5 = new Fill();
            PatternFill patternFill5 = new PatternFill() { PatternType = PatternValues.Solid };
            ForegroundColor foregroundColor3 = new ForegroundColor() { Rgb = color.Replace("#", "") };
            BackgroundColor backgroundColor3 = new BackgroundColor() { Indexed = (UInt32Value)64U };
            patternFill5.Append(foregroundColor3);
            patternFill5.Append(backgroundColor3);
            fill5.Append(patternFill5);
            fills1.Append(fill5);
        }


        Borders borders1 = new Borders() { Count = (UInt32Value)1U };

        DocumentFormat.OpenXml.Spreadsheet.Border border1 = new DocumentFormat.OpenXml.Spreadsheet.Border();
        DocumentFormat.OpenXml.Spreadsheet.LeftBorder leftBorder1 = new DocumentFormat.OpenXml.Spreadsheet.LeftBorder();
        DocumentFormat.OpenXml.Spreadsheet.RightBorder rightBorder1 = new DocumentFormat.OpenXml.Spreadsheet.RightBorder();
        DocumentFormat.OpenXml.Spreadsheet.TopBorder topBorder1 = new DocumentFormat.OpenXml.Spreadsheet.TopBorder();
        DocumentFormat.OpenXml.Spreadsheet.BottomBorder bottomBorder1 = new DocumentFormat.OpenXml.Spreadsheet.BottomBorder();
        DocumentFormat.OpenXml.Spreadsheet.DiagonalBorder diagonalBorder1 = new DocumentFormat.OpenXml.Spreadsheet.DiagonalBorder();

        border1.Append(leftBorder1);
        border1.Append(rightBorder1);
        border1.Append(topBorder1);
        border1.Append(bottomBorder1);
        border1.Append(diagonalBorder1);

        borders1.Append(border1);

        CellStyleFormats cellStyleFormats1 = new CellStyleFormats() { Count = (UInt32Value)1U };
        CellFormat cellFormat1 = new CellFormat() { NumberFormatId = (UInt32Value)0U, FontId = (UInt32Value)0U, FillId = (UInt32Value)0U, BorderId = (UInt32Value)0U };

        cellStyleFormats1.Append(cellFormat1);

        CellFormats cellFormats1 = new CellFormats() { Count = (UInt32)(colorCode.Count + 1) };
        CellFormat cellFormat0 = new CellFormat()
        {
            NumberFormatId = (UInt32Value)0U,
            FontId = (UInt32Value)0U,
            FillId = (UInt32)0,
            BorderId = (UInt32Value)0U,
            FormatId = (UInt32Value)0U,
            ApplyFill = true
        };
        cellFormats1.Append(cellFormat0);

        int colorCodeIndex = 0;
        foreach (string color in colorCode)
        {
            CellFormat cellFormat5 = new CellFormat()
            {
                NumberFormatId = (UInt32Value)0U,
                FontId = (UInt32Value)0U,
                FillId = (UInt32)(colorCodeIndex + 2),
                BorderId = (UInt32Value)0U,
                FormatId = (UInt32Value)0U,
                ApplyFill = true
            };
            cellFormats1.Append(cellFormat5);
            colorCodeIndex++;
        }

        CellStyles cellStyles1 = new CellStyles() { Count = (UInt32Value)1U };
        CellStyle cellStyle1 = new CellStyle() { Name = "Normal", FormatId = (UInt32Value)0U, BuiltinId = (UInt32Value)0U };

        cellStyles1.Append(cellStyle1);
        DifferentialFormats differentialFormats1 = new DifferentialFormats() { Count = (UInt32Value)0U };
        TableStyles tableStyles1 = new TableStyles() { Count = (UInt32Value)0U, DefaultTableStyle = "TableStyleMedium2", DefaultPivotStyle = "PivotStyleMedium9" };

        StylesheetExtensionList stylesheetExtensionList1 = new StylesheetExtensionList();

        StylesheetExtension stylesheetExtension1 = new StylesheetExtension() { Uri = "{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}" };
        stylesheetExtension1.AddNamespaceDeclaration("x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main");
        DocumentFormat.OpenXml.Office2010.Excel.SlicerStyles slicerStyles1 = new DocumentFormat.OpenXml.Office2010.Excel.SlicerStyles() { DefaultSlicerStyle = "SlicerStyleLight1" };

        stylesheetExtension1.Append(slicerStyles1);

        stylesheetExtensionList1.Append(stylesheetExtension1);

        stylesheet1.Append(fonts1);
        stylesheet1.Append(fills1);
        stylesheet1.Append(borders1);
        stylesheet1.Append(cellStyleFormats1);
        stylesheet1.Append(cellFormats1);
        stylesheet1.Append(cellStyles1);
        stylesheet1.Append(differentialFormats1);
        stylesheet1.Append(tableStyles1);
        stylesheet1.Append(stylesheetExtensionList1);
        return stylesheet1;
    }


来源:https://stackoverflow.com/questions/51621206/filling-a-cell-with-a-solid-color-using-openxml-that-preserves-otherwise-existi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!