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