目录
介绍
在我们开始旅程之前
背景
使用代码
- 下载示例 - 650.6 KB
本文将引导您完成通用导出到Excel功能,该功能经过试用和测试,在WEB API中使用C#并使用NPOI。
本文特定于.NET Framework,而我在.NET Core中尝试过,它运行得非常好。
在我们开始旅程之前本文的主要概念是通过导入npoi开发通用excel来导出功能,并添加下面解释的示例中包含的2个cs文件,然后jet set go。
背景我们正在使用NPOI DLL进行此导出,可以免费使用,有关详细信息,请参阅NPOI NuGet。
更常见的情况是,我们需要在我们的应用程序中开发导出到Excel功能,我们中的许多人通常创建无聊的string构建器,然后将其转换为Excel或使用Interop或ITextSharp或NPOI或其他东西来实现相同的结果。
所有上面列出的方法在它们自己的上下文中都是绝对正确的,但是如果可以有一种方法导出到Excel就像传递一个对象并获得所需的输出一样简单,那么我们的生活会更容易,不是吗?
这就是我将在本文中解释的内容。
使用代码首先,有一个实用程序函数Export(),它只是将您的C#List对象转换为NPOI对象,然后最终提供给HttpResponseMessage类型,可以在您的WEB API Action中使用。
您需要2个文件才能实现它——请参阅本文中附带的解决方案以便更好地理解>>根目录中的ExcelExport文件夹:
- AbstractDataExport.cs——包含公共代码
- AbstractDataExportBridge.cs——转换List为NPOI Excel对象
AbstractDataExport.cs做了什么?
参考Export(List exportData, string fileName, string sheetName = DefaultSheetName)
让我们从我们的第一个文件AbstractDataExport.cs开始
创建一个新的Excel对象——_workbook = new XSSFWorkbook();
- 创建新的Excel工作表对象——_sheet = _workbook.CreateSheet(_sheetName);
- 调用WriteData()——稍后解释
- 最后,创建并返回MemoryStream对象
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
namespace GenericExcelExport.ExcelExport
{
public interface IAbstractDataExport
{
HttpResponseMessage Export(List exportData, string fileName, string sheetName);
}
public abstract class AbstractDataExport : IAbstractDataExport
{
protected string _sheetName;
protected string _fileName;
protected List _headers;
protected List _type;
protected IWorkbook _workbook;
protected ISheet _sheet;
private const string DefaultSheetName = "Sheet1";
public HttpResponseMessage Export
(List exportData, string fileName, string sheetName = DefaultSheetName)
{
_fileName = fileName;
_sheetName = sheetName;
_workbook = new XSSFWorkbook(); //Creating New Excel object
_sheet = _workbook.CreateSheet(_sheetName); //Creating New Excel Sheet object
var headerStyle = _workbook.CreateCellStyle(); //Formatting
var headerFont = _workbook.CreateFont();
headerFont.IsBold = true;
headerStyle.SetFont(headerFont);
WriteData(exportData); //your list object to NPOI excel conversion happens here
//Header
var header = _sheet.CreateRow(0);
for (var i = 0; i < _headers.Count; i++)
{
var cell = header.CreateCell(i);
cell.SetCellValue(_headers[i]);
cell.CellStyle = headerStyle;
// It's heavy, it slows down your Excel if you have large data
//_sheet.AutoSizeColumn(i);
}
using (var memoryStream = new MemoryStream()) //creating memoryStream
{
_workbook.Write(memoryStream);
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(memoryStream.ToArray())
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue
("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = $"{_fileName}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
};
return response;
}
}
//Generic Definition to handle all types of List
public abstract void WriteData(List exportData);
}
}
现在,让我们继续我们的第二个也是最后一个文件,即AbstractDataExportBridge.cs。以下是对WriteData(List exportData)的解释:
- 转换List为DataTable
- Reflection要读取属性名称,您的列标题将来自此处
- 循环DataTable创建excel 行
这里有一些改进的地方,您可以进行必要的更改,例如完全删除DataTable。
using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text.RegularExpressions;
namespace GenericExcelExport.ExcelExport
{
public class AbstractDataExportBridge : AbstractDataExport
{
public AbstractDataExportBridge()
{
_headers = new List();
_type = new List();
}
public override void WriteData(List exportData)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
{
var type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
_type.Add(type.Name);
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ??
prop.PropertyType);
string name = Regex.Replace(prop.Name, "([A-Z])", " $1").Trim();
//name by caps for header
_headers.Add(name);
}
foreach (T item in exportData)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
IRow sheetRow = null;
for (int i = 0; i < table.Rows.Count; i++)
{
sheetRow = _sheet.CreateRow(i + 1);
for (int j = 0; j < table.Columns.Count; j++)
{
ICell Row1 = sheetRow.CreateCell(j);
string cellvalue = Convert.ToString(table.Rows[i][j]);
// TODO: move it to switch case
if (string.IsNullOrWhiteSpace(cellvalue))
{
Row1.SetCellValue(string.Empty);
}
else if (_type[j].ToLower() == "string")
{
Row1.SetCellValue(cellvalue);
}
else if (_type[j].ToLower() == "int32")
{
Row1.SetCellValue(Convert.ToInt32(table.Rows[i][j]));
}
else if (_type[j].ToLower() == "double")
{
Row1.SetCellValue(Convert.ToDouble(table.Rows[i][j]));
}
else if (_type[j].ToLower() == "datetime")
{
Row1.SetCellValue(Convert.ToDateTime
(table.Rows[i][j]).ToString("dd/MM/yyyy hh:mm:ss"));
}
else
{
Row1.SetCellValue(string.Empty);
}
}
}
}
}
}