最近,我做的统计功能用到了导出Excel的功能。刚开始我觉着,导出Excel是一个比较简单的功能,分分钟都能解决的,应该和自己当初做机房收费系统的时候一样,引用一下微软的SDK,再做一下相应的适应性处理就差不多了。后来,当我做出来的时候,测试人员说,自己做的功能,有点奇葩,没见过是这样导出Excel 的——打开Excel表格文件,然后将数据存放进去……
之后自己反思一下,发现自己的实现方法确实有点跟平常用的不一样,或许当初自己做的导出Excel也只是仅仅限于没有用户的练习方法吧。
后来一个同事告诉我,用NPOI来实现导出Excel。后来自己在网上查了查相关的资料,发现NPOI确实是一个不错的工具包,相比微软的SDK它的优点大致如下:
1、您可以完全免费使用该框架
2、包含了大部分EXCEL的特性(单元格样式、数据格式、公式等等)
3、支持处理的文件格式包括xls, xlsx, docx.
4、采用面向接口的设计架构( 可以查看 NPOI.SS 的命名空间)
5、同时支持文件的导入和导出
6、基于.net 2.0 也支持xlsx 和 docx格式(当然也支持.net 4.0)
7、来自全世界大量成功且真实的测试Cases
8、大量的实例代码
9、你不需要在服务器上安装微软的Office,可以避免版权问题。
10、使用起来比Office PIA的API更加方便,更人性化。
11、导出速度也是不可同日而语的,之前用微软的SDK时,450条,10列左右的数据用时30多秒,而用NPOI时那速度就是一秒不到,用到项目中了根本不会出现系统卡顿的现象。这个优势也是让我特别惊奇的!
接下来我就把自己写的一个Demo贴出来,供大家参考:
首先是定义个接口类,其中存放了包括打开,保存,修改等功能的接口:
<span style="font-size:24px;"><span style="font-size:24px;"><span style="font-size:24px;">public class ExcelOperateInterface
{
//获取excel操作类对象
public static ExcelOperateInterface CreateInterfaceInstance()
{
ExcelOperateInterface eoi = null;
//switch (EnvirMemory.excelOperateTool)
//{
// case ExcelOperateToolType.Excel_Office:
// {
// eoi = new ExcelOffice();
// } break;
// case ExcelOperateToolType.Excel_NPOI:
// {
eoi = new ExcelNPOI();
// } break;
//case ExcelOperateToolType.Excel_Defalut:
// {
// eoi = new ExcelOffice();
// } break;
//default:
// {
// eoi = new ExcelOffice();
// } break;
//}
return eoi;
}
public virtual void OpenFile(string file,int iSheetIndex) { }
public virtual void CreateFile(string file, int iSheetIndex) { }
public virtual void CloseFile(bool bsave) { }
public virtual string GetCellValue(int iRowIndex, int iColumnIndex) { return ""; }
public virtual void SetCellValue(string sValue, int iRowIndex, int iColumnIndex) { }
public virtual string GetDateCellValue(int iRowIndex, int iColumnIndex) { return ""; }
}
</span></span></span>
接下来是具体的实现类:
<span style="font-size:24px;"><span style="font-size:24px;">public class ExcelNPOI : ExcelOperateInterface
{
private string filename;
private IWorkbook m_iWorkbook;
private ISheet m_iSheet;
private void iInitEnvironment()
{
filename = "";
m_iWorkbook = null;
m_iSheet = null;
}
private void SaveFile()
{
try
{
//NPOI保存文件时,最好是先删除以前的 再新建一个文件
//FilesManager.DeleteFile(filename);
//新建文件流
using (FileStream stream = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write))
{
int i = m_iWorkbook.NumberOfSheets;
for (int ii = 0; ii < i; ++ii)
{
ISheet ish = m_iWorkbook.GetSheetAt(ii);
ish.DisplayGridlines = true;
ish.DisplayRowColHeadings = true;
}
m_iWorkbook.Write(stream);
stream.Flush();
}
}
catch (Exception ex)
{
}
}
public override void CreateFile(string file,int iSheetIndex)
{
try
{
IWorkbook workbook = new XSSFWorkbook();
ISheet sheet = workbook.CreateSheet("sheet0");
for (int i = 0; i < 450; i++)
{
IRow row = sheet.CreateRow(i);
for (int j = 0; j < 50; j++)
{
ICell cell = row.CreateCell(j);
cell.SetCellValue("lcy");
}
}
using (FileStream fs = File.OpenWrite(file))
{
workbook.Write(fs);
}
}
catch (Exception ex)
{
throw;
}
}
public override void OpenFile(string file, int iSheetIndex)
{
try
{
iInitEnvironment();
filename = file;
using (FileStream sfile = new FileStream(file, FileMode.Open, FileAccess.Read))
{
m_iWorkbook = WorkbookFactory.Create(sfile);
if (m_iWorkbook != null)
{
m_iSheet = m_iWorkbook.GetSheetAt(iSheetIndex - 1);
}
}
}
catch (Exception ex)
{
}
}
public override void CloseFile(bool bsave)
{
try
{
if (bsave)
{
SaveFile();
}
iInitEnvironment();
}
catch
{
}
}
public override string GetCellValue(int iRowIndex, int iColumnIndex)
{
string sResult = "";
try
{
IRow irow = m_iSheet.GetRow(iRowIndex - 1);
if (irow != null)
{
ICell icell = irow.GetCell(iColumnIndex - 1);
if (icell != null)
{
sResult = icell.ToString();
}
}
}
catch
{
}
return sResult;
}
public override string GetDateCellValue(int iRowIndex, int iColumnIndex)
{
string sResult = "";
try
{
IRow irow = m_iSheet.GetRow(iRowIndex - 1);
if (irow != null)
{
ICell icell = irow.GetCell(iColumnIndex - 1);
if (icell != null)
{
DateTime dt;
if (DateTime.TryParse(icell.ToString(), out dt))
{
if (icell.CellType == CellType.Numeric)
{
sResult = icell.DateCellValue.ToString();
}
else
{
sResult = icell.ToString();
}
}
}
}
}
catch
{
}
return sResult;
}
public override void SetCellValue(string sValue, int iRowIndex, int iColumnIndex)
{
try
{
//CreateFile("D:\\excel333.xls", 1);
IRow irow = m_iSheet.GetRow(iRowIndex - 1);
if (irow == null)
{
irow = m_iSheet.CreateRow(iRowIndex - 1);
}
ICell icell = irow.GetCell(iColumnIndex - 1);
if (icell == null)
{
icell = irow.CreateCell(iColumnIndex - 1);
}
icell.SetCellType(CellType.String);
if (sValue == "")
{
sValue = "/";
}
icell.SetCellValue(sValue);
CloseFile(true);
}
catch
{
}
}
}</span></span>
最后就是调用了:方法很简单,我现在只用到了导出的功能,所以只用一个Create方法就可以实现了,打开、保存之类的方法是不需要的:
<span style="font-size:24px;"><span style="font-size:24px;"> string file = @"D:\\excel550.xls";
ExcelOperate.ExcelOperateInterface.CreateInterfaceInstance().CreateFile(file, 1);</span></span>