我們經常需要將數據導出爲excel文件。最常用的是導出datatable。另外就是導出list。目前一般excel操作常用NPOI開源組件,因爲大家用過office com調用的都知道,其調用以及後期軟件部署都要處理很多問題,相對比較麻煩。所以用NPOI來導出。
我自己在日常也用到導出,所以寫了一個導出的類。exportListToExcel 是將list泛型對象導出爲excel文件,但是返回的是byte[]。主要是爲了方便asp.net輸出。SetCellStyle函數是設置單元格樣式。
另外既然是泛型,導出時需要動態獲取值,經過網友比較動態DynamicMethod方法調用比直接反射取屬性效率高,所以使用DynamicMethod這個類來取對象屬性。後面又增加了datatable導出方法,附在後面,大同小異,datatable導出更簡單。
public class ExportObjectsToExcel<T> where T : class
{
/// <summary>
/// 導出列表對象到excel
/// </summary>
/// <param name="title">excel sheet title</param>
/// <param name="columns">first row names to export</param>
/// <param name="fields">property on object to export</param>
/// <param name="list">object list to export</param>
/// <returns>bytes content of excel file,can write out to xlsx excel file</returns>
public byte[] exportListToExcel(string title, string[] columns, string[] fields, IList<T> list )
{
XSSFWorkbook workbookX = new XSSFWorkbook();
ISheet sheet = workbookX.CreateSheet(title);
ICellStyle cellStyle_14_Left = SetCellStyle(
workbookX, 12,
BorderStyle.Thin,
HorizontalAlignment.Left,
VerticalAlignment.Center
); //設計單元格格式
int startRow = 0, startCol = 0;
int fieldIndex = startCol + 0;
IRow fieldRow = sheet.CreateRow(startRow++);
fieldRow.Height = 400;
for (int i = 0; i < columns.Length; i++)
{
string sColumnName = columns[i];
ICell fieldCell = fieldRow.CreateCell(fieldIndex++);
//列寬度
sheet.SetColumnWidth(i, 13 * 256);
if (i == columns.Length - 1)
{
sheet.SetColumnWidth(i, 30 * 256);
}
//fieldCell.SetCellValue(sColumnName);
//fieldCell.CellStyle = cellStyle_14_Left;
}
fieldRow = sheet.CreateRow(startRow++);
fieldRow.Height = 400;
fieldIndex = 0;
for (int i = 0; i < columns.Length; i++)
{
string sColumnName = columns[i];
ICell fieldCell = fieldRow.CreateCell(fieldIndex++);
//列寬度
sheet.SetColumnWidth(i, 40 * 256);
if (i == columns.Length - 1)
{
sheet.SetColumnWidth(i, 90 * 256);
}
fieldCell.SetCellValue(sColumnName);
fieldCell.CellStyle = cellStyle_14_Left;
}
sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, columns.Length - 1));
sheet.GetRow(0).GetCell(0).SetCellValue(title);
sheet.GetRow(0).GetCell(0).CellStyle = cellStyle_14_Left;
DynamicMethod<T> dynamicMethod = new DynamicMethod<T>();
for (int i = 0; i < list.Count; i++)
{
IRow dataRow = sheet.CreateRow(startRow++);
dataRow.Height = 400;
for (int j = 0; j < fields.Length; j++)
{
string fieldName = fields[j];
ICell newCell = dataRow.CreateCell(j);
object data1 = list[i];
object drValue = dynamicMethod.GetValue(data1, fieldName);
string DataType = "";
if (drValue!=null )
{
DataType = drValue.GetType().ToString();
}
switch (DataType)
{
case "System.String": //字符串類型
newCell.SetCellValue(TypeConvert.ToString(drValue));
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.DateTime": //日期類型
DateTime dateV = TypeConvert.ToDateTime(drValue);
newCell.SetCellValue(dateV.ToString("yyyy-MM-dd"));
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.Boolean": //布爾型
bool boolV = false;
bool.TryParse(TypeConvert.ToString(drValue), out boolV);
newCell.SetCellValue(boolV);
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.Int16": //整型
case "System.Int32":
case "System.Int64":
case "System.Byte":
int intV = 0;
int.TryParse(TypeConvert.ToString(drValue), out intV);
TypeConvert.ToInt32(drValue);
newCell.SetCellValue(intV);
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.Decimal": //浮點型
case "System.Double":
double doubV = 0;
double.TryParse(TypeConvert.ToString(drValue), out doubV);
newCell.SetCellValue(doubV.ToString("f6"));
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.DBNull": //空值處理
newCell.SetCellValue("");
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
default:
newCell.SetCellValue("");
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
}
}
}
MemoryStream stream = new System.IO.MemoryStream();
workbookX.Write(stream);
stream.Close();
byte[] bytes=stream.ToArray();
workbookX.Close();
return bytes;
}
private ICellStyle SetCellStyle(IWorkbook wk, int fontSize, BorderStyle borderStyle, HorizontalAlignment horAli, VerticalAlignment verAli)
{
ICellStyle cellStyle = wk.CreateCellStyle();
//設置單元格上下左右邊框線
cellStyle.BorderTop = borderStyle;
cellStyle.BorderBottom = borderStyle;
cellStyle.BorderLeft = borderStyle;
cellStyle.BorderRight = borderStyle;
//文字水平和垂直對齊方式
cellStyle.Alignment = horAli;
cellStyle.VerticalAlignment = verAli;
IFont font = wk.CreateFont();
font.FontHeight = fontSize;
cellStyle.SetFont(font);
//是否換行
cellStyle.WrapText = true; //自動換行
//縮小字體填充
//cellStyle.ShrinkToFit = true;
return cellStyle;
}
}
public class DynamicMethod<T>
{
internal static Func<object, string, object> GetValueDelegate;
public object GetValue(object instance, string memberName)
{
return GetValueDelegate(instance, memberName);
}
static DynamicMethod()
{
GetValueDelegate = GenerateGetValue();
}
private static Func<object, string, object> GenerateGetValue()
{
var type = typeof(T);
var instance = Expression.Parameter(typeof(object), "instance");
var memberName = Expression.Parameter(typeof(string), "memberName");
var nameHash = Expression.Variable(typeof(int), "nameHash");
var calHash = Expression.Assign(nameHash, Expression.Call(memberName, typeof(object).GetMethod("GetHashCode")));
var cases = new List<SwitchCase>();
foreach (var propertyInfo in type.GetProperties())
{
var property = Expression.Property(Expression.Convert(instance, typeof(T)), propertyInfo.Name);
var propertyHash = Expression.Constant(propertyInfo.Name.GetHashCode(), typeof(int));
cases.Add(Expression.SwitchCase(Expression.Convert(property, typeof(object)), propertyHash));
}
var switchEx = Expression.Switch(nameHash, Expression.Constant(null), cases.ToArray());
var methodBody = Expression.Block(typeof(object), new[] { nameHash }, calHash, switchEx);
return Expression.Lambda<Func<object, string, object>>(methodBody, instance, memberName).Compile();
}
}
datatable的導出方法。
/// <summary>
/// export datatable to excel file
/// </summary>
/// <param name="title">table title</param>
/// <param name="dt">table</param>
/// <param name="xlsFileName">export file name xlsx</param>
public void exportDataTable(string title, DataTable dt, string xlsFileName)
{
string fileName = xlsFileName;
if (fileName.ToLower().EndsWith(".xls"))
{
fileName = fileName + "x";
}
XSSFWorkbook workbookX = new XSSFWorkbook();
FileStream stream = File.Create(fileName);
{
ISheet sheet = workbookX.CreateSheet(title);
ICellStyle cellStyle_14_Left = SetCellStyle(
workbookX, 12,
BorderStyle.Thin,
HorizontalAlignment.Left,
VerticalAlignment.Center
); //設計單元格格式
int startRow = 0, startCol = 0;
int fieldIndex = startCol + 0;
IRow fieldRow = sheet.CreateRow(startRow++);
fieldRow.Height = 400;
for (int i = 0; i < dt.Columns.Count; i++)
{
string sColumnName = dt.Columns[i].ColumnName;
ICell fieldCell = fieldRow.CreateCell(fieldIndex++);
//列寬度
sheet.SetColumnWidth(i, 13 * 256);
if (i == dt.Columns.Count - 1)
{
sheet.SetColumnWidth(i, 30 * 256);
}
//fieldCell.SetCellValue(sColumnName);
//fieldCell.CellStyle = cellStyle_14_Left;
}
fieldRow = sheet.CreateRow(startRow++);
fieldRow.Height = 400;
fieldIndex = 0;
for (int i = 0; i < dt.Columns.Count; i++)
{
string sColumnName = dt.Columns[i].ColumnName;
ICell fieldCell = fieldRow.CreateCell(fieldIndex++);
//列寬度
sheet.SetColumnWidth(i, 13 * 256);
if (i == dt.Columns.Count - 1)
{
sheet.SetColumnWidth(i, 30 * 256);
}
fieldCell.SetCellValue(sColumnName);
fieldCell.CellStyle = cellStyle_14_Left;
}
sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, dt.Columns.Count - 1));
sheet.GetRow(0).GetCell(0).SetCellValue(title);
sheet.GetRow(0).GetCell(0).CellStyle = cellStyle_14_Left;
for (int i = 0; i < dt.Rows.Count; i++)
{
IRow dataRow = sheet.CreateRow(startRow++);
dataRow.Height = 400;
foreach (DataColumn column in dt.Columns)
{
ICell newCell = dataRow.CreateCell(column.Ordinal);
DataRow row = dt.Rows[i];
string drValue = TypeConvert.ToString(row[column]);
switch (column.DataType.ToString())
{
case "System.String": //字符串類型
newCell.SetCellValue(drValue);
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.DateTime": //日期類型
DateTime dateV = TypeConvert.ToDateTime(row[column]);
newCell.SetCellValue(dateV.ToString("yyyy-MM-dd"));
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.Boolean": //布爾型
bool boolV = false;
bool.TryParse(drValue, out boolV);
newCell.SetCellValue(boolV);
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.Int16": //整型
case "System.Int32":
case "System.Int64":
case "System.Byte":
int intV = 0;
int.TryParse(drValue, out intV);
TypeConvert.ToInt32(drValue);
newCell.SetCellValue(intV);
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.Decimal": //浮點型
case "System.Double":
double doubV = 0;
double.TryParse(drValue, out doubV);
newCell.SetCellValue(doubV.ToString("f6"));
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
case "System.DBNull": //空值處理
newCell.SetCellValue("");
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
default:
newCell.SetCellValue("");
newCell.CellStyle = cellStyle_14_Left; //格式化顯示
break;
}
}
}
}
workbookX.Write(stream);
stream.Close();
workbookX.Close();
}