作为C#处理Excel的强大的开源组件,NPOI具有Office Excel的绝大部分功能,与收费的Spire比虽有不足,但对于一般性的处理来说还是基本够用,这也是NPOI至今仍作为众多C#堆码人员的选择的原因。
收费软件能够提供更多的功能给用户,这也是它的卖点。Spire的DataTable数据导入,就是NPOI所不具备的,而导入DataTable数据,对于C#来说是经常遇到的,所以NPOI用起来虽然也能够想办法处理,却没有那么方便。
下面的代码,仿照Spire的DataTable数据导入,提供大家一个参照。
/// <summary>
/// NPOI把DataTable的数据写入到指定的Sheet中
/// </summary>
/// <param name="sourceData">要写入的数据表</param>
/// <param name="sheet">当前要写入的Sheet</param>
/// <param name="rowStart">当前要写入的Sheet的起始行号(行计数从1起)</param>
/// <param name="colStart">当前要写入的Sheet的起始列号(列计数从1起)</param>
/// <param name="IsWriteColumnName">DataTable的列名称是否写入Sheet</param>
/// <param name="cellStyle">单元格格式</param>
/// <returns>返回标题行数和写入的表行数的合计</returns>
private int DataTableToSheet_NPOI(DataTable sourceData, ISheet sheet, int rowStart, int colStart, bool IsWriteColumnName, ICellStyle cellStyle = null)
{
//Sheet的总行数
int WriteRowCount = rowStart - 1; //已有行数,同时为新行号(NPOI计数从0起)
ICell cell;
//是否写入列名,则写入DataTable的列名,已有行后的下一行写入列名
if (IsWriteColumnName)
{
//sheet表创建新的一行,即已有行后的第一行
IRow ColumnNameRow = sheet.CreateRow(WriteRowCount);
//进行写入DataTable的列名
for (int colunmNameIndex = 0; colunmNameIndex < sourceData.Columns.Count; colunmNameIndex++)
{
cell = ColumnNameRow.CreateCell(colStart - 1 + colunmNameIndex);
cell.SetCellValue(sourceData.Columns[colunmNameIndex].ColumnName.ToString());
SetValue(cell, sourceData.Columns[colunmNameIndex].ColumnName);
if (cellStyle != null)
cell.CellStyle = cellStyle;
}
WriteRowCount++;
}
//写入数据
for (int row = 0; row < sourceData.Rows.Count; row++)
{
//sheet表创建新的一行
IRow newRow = sheet.CreateRow(WriteRowCount);
for (int column = 0; column < sourceData.Columns.Count; column++)
{
cell = newRow.CreateCell(colStart - 1 + column);
SetValue(cell, sourceData.Rows[row][column]);
if (cellStyle != null)
cell.CellStyle = cellStyle;
}
WriteRowCount++; //下一行号
}
return WriteRowCount;
}
private void SetValue(ICell cell,object value)
{
Type type = value.GetType();
switch (type.Name)
{
case "Boolean":
cell.SetCellValue((bool)value);
break;
case "String":
cell.SetCellValue(value.ToString());
break;
case "DateTime":
cell.SetCellValue((DateTime)value);
break;
case "Int32":
cell.SetCellValue((int)value);
break;
case "Single":
cell.SetCellValue((double)value);
break;
case "Double":
cell.SetCellValue((double)value);
break;
default:
cell.SetCellValue(value.ToString());
break;
}
}
以上示例亲测通过。关于单元格格式,还可以增加一个标题格式(列名格式处理),这个处理没有问题吧。