Excel 如何使用OpenXmlWriter配置xlsx格式和公式

Excel 如何使用OpenXmlWriter配置xlsx格式和公式,excel,openxml,openxml-sdk,Excel,Openxml,Openxml Sdk,我需要创建大型通用xlsx报告(超过500k行,约50列)。 我编写了生成此报告的方法,但我不知道如何设置单元格格式(数据格式/样式(边框等))以及如何使用OpenXmlWriter将公式放入单元格 private void FillExcelWorksheet<T>(String fileName, IEnumerable<T> source) { var properties = typeof(T).GetPropertie

我需要创建大型通用xlsx报告(超过500k行,约50列)。 我编写了生成此报告的方法,但我不知道如何设置单元格格式(数据格式/样式(边框等))以及如何使用OpenXmlWriter将公式放入单元格

  private void FillExcelWorksheet<T>(String fileName, IEnumerable<T> source)
        {
            var properties = typeof(T).GetProperties();
            using (SpreadsheetDocument document = SpreadsheetDocument.Create(fileName, SpreadsheetDocumentType.Workbook))
            {
                //this list of attributes will be used when writing a start element
                List<OpenXmlAttribute> stringAttributes = new List<OpenXmlAttribute>()
                {
                    new OpenXmlAttribute("t", null, "str")
                };

                OpenXmlWriter writer;

                var workBookPart = document.AddWorkbookPart();
                var workSheetPart = workBookPart.AddNewPart<WorksheetPart>();

                writer = OpenXmlWriter.Create(workSheetPart);
                writer.WriteStartElement(new Worksheet());
                writer.WriteStartElement(new SheetData());

                writer.WriteStartElement(new Row());
                foreach (PropertyInfo property in properties)
                {
                    var pAttributes = property.GetCustomAttributes<ReportColumnAttribute>();

                    if (pAttributes.Any())
                    {
                        var attribute = pAttributes.First();
                        writer.WriteStartElement(new Cell(), stringAttributes);
                        //write the cell value
                        writer.WriteElement(new CellValue(attribute.ColumnName));

                        // write the end cell element
                        writer.WriteEndElement();
                    }
                }

                // write the end row element
                writer.WriteEndElement();

                foreach (var item in source)
                {
                    //write the row start element with the row index attribute
                    writer.WriteStartElement(new Row());

                    foreach (PropertyInfo property in properties)
                    {
                        var pAttributes = property.GetCustomAttributes<ReportColumnAttribute>();

                        if (pAttributes.Any())
                        {
                            //write the cell start element with the type and reference attributes
                            writer.WriteStartElement(new Cell(), stringAttributes);
                            //write the cell value
                            writer.WriteElement(new CellValue(property.GetValue(item) != null ?
                                property.GetValue(item).ToString() : String.Empty));

                            var attribute = pAttributes.First();
                            var format = attribute.Format;
                            //todo apply data format

                            // write the end cell element
                            writer.WriteEndElement();
                        }
                    }

                    // write the end row element
                    writer.WriteEndElement();
                }
                // write the end SheetData element
                writer.WriteEndElement();
                // write the end Worksheet element
                writer.WriteEndElement();
                writer.Close();

                writer = OpenXmlWriter.Create(document.WorkbookPart);
                writer.WriteStartElement(new Workbook());
                writer.WriteStartElement(new Sheets());

                writer.WriteElement(new Sheet()
                {
                    Name = fileName,
                    SheetId = 1,
                    Id = document.WorkbookPart.GetIdOfPart(workSheetPart)
                });

                // End Sheets
                writer.WriteEndElement();
                // End Workbook
                writer.WriteEndElement();

                writer.Close();

                document.Close();
            }
        }
private void fillexcel工作表(字符串文件名,IEnumerable源代码)
{
var properties=typeof(T).GetProperties();
使用(电子表格文档=电子表格文档.Create(文件名,电子表格文档类型.工作簿))
{
//写入开始元素时将使用此属性列表
List stringAttributes=新列表()
{
新的OpenXmlAttribute(“t”,null,“str”)
};
OpenXmlWriter;
var workBookPart=document.AddWorkbookPart();
var workSheetPart=workBookPart.AddNewPart();
writer=OpenXmlWriter.Create(工作表部分);
writer.writeStart元素(新工作表());
writer.writeStarElement(新的SheetData());
writer.writeStarteElement(新行());
foreach(属性中的PropertyInfo属性)
{
var pAttributes=property.GetCustomAttributes();
if(pAttributes.Any())
{
var属性=pAttributes.First();
WriteStarteElement(新单元格(),stringAttributes);
//写入单元格值
WriteElement(新的CellValue(attribute.ColumnName));
//写入结束单元元素
writer.writeedelement();
}
}
//写入结束行元素
writer.writeedelement();
foreach(源中的var项)
{
//使用row index属性写入row start元素
writer.writeStarteElement(新行());
foreach(属性中的PropertyInfo属性)
{
var pAttributes=property.GetCustomAttributes();
if(pAttributes.Any())
{
//使用type和reference属性写入单元格开始元素
WriteStarteElement(新单元格(),stringAttributes);
//写入单元格值
writer.WriteElement(新的CellValue(property.GetValue(item)!=null?
property.GetValue(item.ToString():String.Empty));
var属性=pAttributes.First();
var format=attribute.format;
//todo应用数据格式
//写入结束单元元素
writer.writeedelement();
}
}
//写入结束行元素
writer.writeedelement();
}
//写入结束数据元素
writer.writeedelement();
//编写结束工作表元素
writer.writeedelement();
writer.Close();
writer=OpenXmlWriter.Create(document.WorkbookPart);
writer.writeStart元素(新工作簿());
writer.writeStarElement(新工作表());
WriteElement(新工作表()
{
Name=文件名,
SheetId=1,
Id=document.WorkbookPart.GetIdOfPart(工作表部分)
});
//端板
writer.writeedelement();
//结束工作簿
writer.writeedelement();
writer.Close();
document.Close();
}
}
使用样式生成结果
私有下载结果FillExcelWorksheet(字符串名称,IEnumerable源,Action addNonGenericReportInfo=null)
{
var properties=typeof(T).GetProperties();
var folder=ConfigurationManager.AppSettings[“ReportsPath”];
如果(!Directory.Exists(folder)){
创建目录(文件夹);
}
//删除旧文件
目录.GetFiles(文件夹)
.选择(f=>newfileinfo(f))
.Where(f=>f.CreationTimef.Delete());
var fileName=String.Format(“{0}{1}.xlsx”,name,Guid.NewGuid());
使用(var document=SpreadsheetDocument.Create(文件夹+文件名,SpreadsheetDocumentType.工作簿))
{
//写入开始元素时将使用此属性列表
List stringAttributes=新列表()
{
新的OpenXmlAttribute(“t”,null,“str”)
};
OpenXmlWriter;
var workBookPart=document.AddWorkbookPart();
var workSheetPart=workBookPart.AddNewPart();
var sharedStringPart=workBookPart.AddNewPart();
sharedStringPart.SharedStringTable=新的SharedStringTable();
var stylesPart=document.WorkbookPart.AddNewPart();
stylesPart.Stylesheet=新样式表();
stylesPart.Stylesheet.NumberingFormats=新的NumberingFormats();
//创建填充
stylesPart.Stylesheet.Fills=新填充();
stylesPart.Stylesheet.Fills.AppendChild(新填充{PatternFill=new PatternFill{PatternType=PatternValues.None});//必需,由Excel保留
//示例不删除
//stylesPart.Stylesheet.Fills.AppendChild(新填充{PatternFill=new PatternFill{Patte
result with styles 
private DownloadResult FillExcelWorksheet<T>(String name, IEnumerable<T> source, Action<OpenXmlWriter, WorkbookStylesPart, SharedStringTablePart, Int32> addNonGenericReportInfo = null)
    {
        var properties = typeof(T).GetProperties();
        var folder = ConfigurationManager.AppSettings["ReportsPath"];
        if (!Directory.Exists(folder)) {
            Directory.CreateDirectory(folder);
        }

        //remove old files
        Directory.GetFiles(folder)
             .Select(f => new FileInfo(f))
             .Where(f => f.CreationTime < DateTime.Now.AddDays(-1))
             .ToList()
             .ForEach(f => f.Delete());

        var fileName = String.Format("{0}_{1}.xlsx", name, Guid.NewGuid());

        using (var document = SpreadsheetDocument.Create(folder + fileName, SpreadsheetDocumentType.Workbook))
        {
            //this list of attributes will be used when writing a start element
            List<OpenXmlAttribute> stringAttributes = new List<OpenXmlAttribute>()
            {
                new OpenXmlAttribute("t", null, "str")
            };

            OpenXmlWriter writer;

            var workBookPart = document.AddWorkbookPart();
            var workSheetPart = workBookPart.AddNewPart<WorksheetPart>();
            var sharedStringPart = workBookPart.AddNewPart<SharedStringTablePart>();
            sharedStringPart.SharedStringTable = new SharedStringTable();

            var stylesPart = document.WorkbookPart.AddNewPart<WorkbookStylesPart>();
            stylesPart.Stylesheet = new Stylesheet();
            stylesPart.Stylesheet.NumberingFormats = new NumberingFormats();

            // create fills
            stylesPart.Stylesheet.Fills = new Fills();
            stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill { PatternType = PatternValues.None } }); // required, reserved by Excel
            //EXAMPLE DON'T REMOVE
            //stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill { PatternType = PatternValues.Gray125 } }); // required, reserved by Excel

            //// 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 = solidRed });
            stylesPart.Stylesheet.Fills.Count = 3;

            // blank cell format list
            stylesPart.Stylesheet.CellStyleFormats = new CellStyleFormats();
            stylesPart.Stylesheet.CellStyleFormats.AppendChild(new CellFormat());
            stylesPart.Stylesheet.CellStyleFormats.Count = 1;

            //Borders
            stylesPart.Stylesheet.Borders = new Borders();
            stylesPart.Stylesheet.Borders.AppendChild(new Border());
            var border = new Border();
            border.Append(new BottomBorder() { Style = BorderStyleValues.Thin });
            stylesPart.Stylesheet.Borders.AppendChild(border);
            stylesPart.Stylesheet.Borders.Count = 2;

            //Fonts
            stylesPart.Stylesheet.Fonts = new Fonts();
            stylesPart.Stylesheet.Fonts.AppendChild(new Font());
            var font = new Font();
            font.Bold = new Bold();
            stylesPart.Stylesheet.Fonts.AppendChild(font);
            stylesPart.Stylesheet.Fonts.Count = 2;

            // 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 = 1, BorderId = 1, FillId = 0, ApplyFill = true }).AppendChild(new Alignment { Horizontal = HorizontalAlignmentValues.Center });
            stylesPart.Stylesheet.CellFormats.Count = 2;


            writer = OpenXmlWriter.Create(workSheetPart);
            writer.WriteStartElement(new Worksheet());

            writer.WriteStartElement(new SheetData());

            writer.WriteStartElement(new Row());
            foreach (PropertyInfo property in properties)
            {
                var pAttributes = property.GetCustomAttributes<ReportColumnAttribute>();

                if (pAttributes.Any())
                {
                    var attribute = pAttributes.First();

                    var cell = new Cell();
                    cell.DataType = CellValues.SharedString;
                    cell.StyleIndex = 1;
                    writer.WriteStartElement(cell);
                    //write the cell value
                    var index = InsertSharedStringItem(attribute.ColumnName, sharedStringPart);
                    writer.WriteElement(new CellValue(index.ToString()));

                    // write the end cell element
                    writer.WriteEndElement();
                    if (!String.IsNullOrEmpty(attribute.Format) && !_styleFormats.ContainsKey(attribute.Format))
                    {
                        //164 is first free format id
                        var formatId = 164 + (uint)_styleFormats.Count;
                        var format = new NumberingFormat { NumberFormatId = formatId, FormatCode = attribute.Format };
                        stylesPart.Stylesheet.NumberingFormats.AppendChild(format);
                        stylesPart.Stylesheet.CellFormats.AppendChild(new CellFormat { NumberFormatId = formatId, FontId = 0, BorderId = 0, FillId = 0, ApplyFill = true });
                        //stylesPart.Stylesheet.CellFormats.AppendChild(format);
                        stylesPart.Stylesheet.CellStyleFormats.Count++;

                        _styleFormats.Add(attribute.Format, new StyleIndexes(stylesPart.Stylesheet.CellFormats.Count, formatId));
                        stylesPart.Stylesheet.CellFormats.Count++;
                    }

                }
            }
            // write the end row element
            writer.WriteEndElement();

            foreach (var item in source)
            {
                //write the row start element with the row index attribute
                writer.WriteStartElement(new Row());

                foreach (PropertyInfo property in properties)
                {
                    var pAttributes = property.GetCustomAttributes<ReportColumnAttribute>();

                    if (pAttributes.Any())
                    {
                        var attribute = pAttributes.First();

                        var cell = new Cell();

                        if (!String.IsNullOrEmpty(attribute.Format))
                        {
                            cell.StyleIndex = (uint)_styleFormats[attribute.Format].StyleIndex;
                        }

                        var typeCode = Type.GetTypeCode(property.PropertyType);
                        //write the cell start element with the type and reference attributes
                        if (typeCode == TypeCode.String)
                        {
                            writer.WriteStartElement(cell, stringAttributes);
                        }
                        else
                        {
                            cell.DataType = CellValues.Number;
                            writer.WriteStartElement(cell);
                        }

                        var value = String.Empty;

                        if (typeCode == TypeCode.DateTime)
                        {
                            value = property.GetValue(item) != null ?
                                Convert.ToDateTime(property.GetValue(item)).ToOADate().ToString() : String.Empty;

                        }
                        else { 
                            value = property.GetValue(item) != null ?
                                property.GetValue(item).ToString() : String.Empty;
                        }

                        //write the cell value
                        writer.WriteElement(new CellValue(value));

                        // write the end cell element
                        writer.WriteEndElement();
                    }
                }

                // write the end row element
                writer.WriteEndElement();
            }

            if (addNonGenericReportInfo != null)
            {
                addNonGenericReportInfo(writer, stylesPart, sharedStringPart, source.Count());
            }

            sharedStringPart.SharedStringTable.Save();
            stylesPart.Stylesheet.Save();

            // write the end SheetData element
            writer.WriteEndElement();
            // write the end Worksheet element
            writer.WriteEndElement();
            writer.Close();

            writer = OpenXmlWriter.Create(document.WorkbookPart);
            writer.WriteStartElement(new Workbook());
            writer.WriteStartElement(new Sheets());

            writer.WriteElement(new Sheet()
            {
                Name = name,
                SheetId = 1,
                Id = document.WorkbookPart.GetIdOfPart(workSheetPart)
            });

            // End Sheets
            writer.WriteEndElement();
            // End Workbook
            writer.WriteEndElement();

            writer.Close();

            document.Close();
        }

        return new DownloadResult
        {
            Name = name + ".xlsx",
            PathToDownload = folder + fileName,
        };
    }

    private static int InsertSharedStringItem(string text, SharedStringTablePart shareStringPart)
    {
        // If the part does not contain a SharedStringTable, create one.
        if (shareStringPart.SharedStringTable == null)
        {
            shareStringPart.SharedStringTable = new SharedStringTable();
        }

        int i = 0;

        // Iterate through all the items in the SharedStringTable. If the text already exists, return its index.
        foreach (SharedStringItem item in shareStringPart.SharedStringTable.Elements<SharedStringItem>())
        {
            if (item.InnerText == text)
            {
                return i;
            }

            i++;
        }

        // The text does not exist in the part. Create the SharedStringItem and return its index.
        shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text)));
        shareStringPart.SharedStringTable.Save();

        return i;
    }

    private Dictionary<String, StyleIndexes> _styleFormats;

    private class StyleIndexes
    {
        public StyleIndexes(uint styleIndex, uint numberIndex)
        {
            StyleIndex = styleIndex;
            NumberIndex = numberIndex;
        }

        public uint StyleIndex { get; set; }
        public uint NumberIndex { get; set; }
    }