这篇会介绍NPOI读写EXECL,读写EXECL的组件很多,可以使用微软自己的COM组件EXECL.exe读写,不过这种方式限制很大。

1:客户环境必须装Office(虽然现在机子上不装Office的几乎没有吧)

2:EXECL读写完毕后EXECL还有进程还留在后台  ,内存回收不了

基于以上的原因,就采用了开源组件NPOI进行操作了。

NPOI简介

1.Excel表格叫做工作表:WorkBook(工作薄),包含的叫页(工作表):Sheet;行:Row;单元格Cell。

2.Npoi 下载地址:http://npoi.codeplex.com

3.Npoi 学习系列教程推荐:http://tonyqus.sinaapp.com

4.npoi 能够读写几乎所有的Office 97-2010文件格式(特别提示读取EXECL2007版本及以上的需要使用NPOI2.0版本才行,也就是.xlsx。之前EXECL老版本是.xls),至少能够支持Word, PowerPoint, Excel, Visio的格式。

简单示例

        1.创建一个简单的xls文件

//创建xls文件
private void button1_Click(object sender, EventArgs e)
{
//创建工作薄
HSSFWorkbook wk = new HSSFWorkbook();
//创建一个名称为mySheet的表
ISheet tb = wk.CreateSheet("mySheet");
//创建一行,此行为第二行
IRow row = tb.CreateRow();
for (int i = ; i < ; i++)
{
ICell cell = row.CreateCell(i); //在第二行中创建单元格
cell.SetCellValue(i);//循环往第二行的单元格中添加数据
}
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
{
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
MessageBox.Show("提示:创建成功!");
}
}

2.读取简单的xls文件

/// <summary>
/// 读取一个简单xls文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
StringBuilder sbr = new StringBuilder();
string path = GetDeskTopPath() + @"\myxls.xls";
using (FileStream fs = File.OpenRead(path)) //打开myxls.xls文件
{
HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中
for (int i = ; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
{
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
for (int j = ; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
{
IRow row = sheet.GetRow(j); //读取当前行数据
if (row != null)
{
sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
for (int k = ; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
{
ICell cell = row.GetCell(k); //当前表格
if (cell != null)
{
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
}
}
}
}
}
}
sbr.ToString();
path = GetDeskTopPath() + @"\myText.txt";
using (StreamWriter wr = new StreamWriter(new FileStream(path, FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
{
wr.Write(sbr.ToString());
wr.Flush();
MessageBox.Show("提示:写入成功!");
}
}

3.读取EXECL文件,兼容xls和xlsx文件,NPOI2.0特意为这种情况提供接口读取,免去用户需要判断文件格式写不同代码的烦恼,看下面的实例

 StringBuilder sbr = new StringBuilder();
string path = GetDeskTopPath() + @"\myxls.xls";
using (FileStream fs = File.OpenRead(path)) //打开myxls.xls文件
{
IWorkbook wk = WorkbookFactory.Create(fs); //使用接口,自动识别excel2003/2007格式
for (int i = ; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
{
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
for (int j = ; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
{
IRow row = sheet.GetRow(j); //读取当前行数据
if (row != null)
{
sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
for (int k = ; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
{
ICell cell = row.GetCell(k); //当前表格
if (cell != null)
{
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
}
}
}
}
}
}
sbr.ToString();
path = GetDeskTopPath() + @"\myText.txt";
using (StreamWriter wr = new StreamWriter(new FileStream(path, FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
{
wr.Write(sbr.ToString());
wr.Flush();
MessageBox.Show("提示:写入成功!");
}

上面表红部分是读取文件的接口,需要着重注意。NPOI提供WorkbookFactroy工厂类。另外创建xlxs文件方法类似,唯一区别使用XSSFWorkbook创建WorkBook对象。

XSSFWorkbook wk = new XSSFWorkbook();

NPOI在本工具的使用及总结

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel; namespace MyTools.DataDic.Utils
{
/// <summary>
/// 解析Execl文件,读取信息
/// </summary>
public class ExeclReader : IReader
{
/// <summary>
/// Execl文件路径
/// </summary>
private string _pdmPath; private List<TableInfo> mTables = null; private IWorkbook hssfworkbook = null; /// <summary>
/// 校验文件路径是否存在
/// </summary>
/// <param name="pdmPath">EXECL文件路径</param>
private void CheckPath(string pdmPath)
{
if (string.IsNullOrEmpty(pdmPath))
{
throw new Exception("文件路径不能为空!");
}
if (!pdmPath.EndsWith(".xls", true, null) && !pdmPath.EndsWith(".xlsx", true, null))
{
throw new Exception("文件格式不正确,请选择EXECL文件!");
}
if (!File.Exists(pdmPath))
{
throw new Exception("指定文件不存在!");
}
} /// <summary>
/// 构造函数 根据路径生成所有表的SQL
/// </summary>
/// <param name="pdmPath">EXECL文件路径</param>
public ExeclReader(string pdmPath)
{
try
{
CheckPath(pdmPath);
_pdmPath = pdmPath;
}
catch (Exception ex)
{
throw ex;
}
} /// <summary>
/// 初始化EXECL
/// </summary>
/// <returns>HSSFWorkbook</returns>
private IWorkbook InitHSSFWorkbook()
{
if (hssfworkbook == null)
{
try
{
using (FileStream fs = new FileStream(_pdmPath, FileMode.Open, FileAccess.Read))
{
hssfworkbook = WorkbookFactory.Create(fs);
}
}
catch (Exception e)
{
throw e;
}
}
return hssfworkbook;
} /// <summary>
/// 从EXECL读取表信息
/// </summary>
/// <returns> List</returns>
public List<TableInfo> GetTableInfo()
{
try
{
IWorkbook hssfworkbook = InitHSSFWorkbook();
List<TableInfo> Tables = new List<TableInfo>();
//杜冬军2014-05-03修改 循环读取EXECL所有的非隐藏Sheet
//sheet总数
int iSheetNum=hssfworkbook.NumberOfSheets;
ISheet sheet = null;
for (int m = ; m < iSheetNum; m++)
{
if (hssfworkbook.IsSheetHidden(m))
{
continue;
}
sheet = hssfworkbook.GetSheetAt(m);
IRow row = null;
ICell cell = null;
int iLastRowNum = sheet.LastRowNum;
for (int i = ; i < iLastRowNum; i++)
{
row = sheet.GetRow(i);
if (row == null)
{
continue;
}
for (int j = ; j < row.LastCellNum; j++)
{
//列索引异常BUG修复 2014-06-07杜冬军修改 row.Cells不适合
cell = row.GetCell(j);
if (cell != null && cell.ToString().Trim() == "数据表中文名称")
{
i = GetTable(sheet, i, cell.ColumnIndex, Tables, sheet.SheetName.Trim());
break;
}
}
}
}
mTables = Tables;
return Tables;
}
catch (Exception ex)
{
throw ex;
}
} /// <summary>
/// 从中读取物理图信息
/// </summary>
/// <returns> List</returns>
public List<PhysicalDiagramInfo> GetPDInfo()
{
try
{
List<PhysicalDiagramInfo> PDList = new List<PhysicalDiagramInfo>();
IWorkbook hssfworkbook = InitHSSFWorkbook();
if (mTables == null)
{
mTables = GetTableInfo();
}
PhysicalDiagramInfo pdInfo = new PhysicalDiagramInfo();
string pid = System.Guid.NewGuid().ToString();
pdInfo.Id = pid;
pdInfo.Name = "所有数据";
PDList.Add(pdInfo); int iSheetNum=hssfworkbook.NumberOfSheets;
for (int m = ; m < iSheetNum; m++)
{
if (hssfworkbook.IsSheetHidden(m))
{
continue;
}
PhysicalDiagramInfo pd = new PhysicalDiagramInfo();
string pid1 = System.Guid.NewGuid().ToString();
pd.Id = pid1;
pd.Name = hssfworkbook.GetSheetAt(m).SheetName.Trim();
pd.PhyParentId = pid;
PDList.Add(pd);
List<TableInfo> query = (from a in mTables
where a.PDName == pd.Name
select a).ToList<TableInfo>(); foreach (TableInfo t in query)
{
pd = new PhysicalDiagramInfo();
pd.Id = System.Guid.NewGuid().ToString();
pd.Name = t.Code;
pd.IfEnd = true;
pd.PhyParentId = pid1;
PDList.Add(pd); }
}
return PDList;
}
catch (Exception ex)
{
throw ex;
}
} /// <summary>
/// 获取表信息
/// </summary>
/// <param name="tableName">表名</param>
/// <returns>表信息</returns>
public List<TableInfo> GetTableColumnName(string tableName)
{
if (string.IsNullOrEmpty(tableName))
{
throw new Exception("参数空异常!");
}
List<TableInfo> list = GetTableInfo();
if (list != null && list.Count > )
{
IEnumerable<TableInfo> query =
from c in list
where c.Code == tableName
select c;
return query.ToList<TableInfo>();
}
return null;
} /// <summary>
/// 获取节点中表的信息
/// </summary>
/// <param name="sheet">sheet</param>
/// <param name="iRow">iRow</param>
/// <param name="iCell">iCell</param>
/// <param name="sheetName">sheetName</param>
/// <returns>表信息</returns>
private int GetTable(ISheet sheet, int iRow, int iCell, List<TableInfo> Tables,string sheetName)
{
try
{
TableInfo mTable = new TableInfo();
List<ColumnInfo> list = new List<ColumnInfo>();
List<PkKeyInfo> listPkKeyInfo = new List<PkKeyInfo>();
mTable.ListColumnInfo = list;
mTable.ListPkKeyInfo = listPkKeyInfo;
mTable.PDName = sheetName;
//表的ID
mTable.TableObjectID = Guid.NewGuid().ToString();
//表的中文名称
mTable.Name = sheet.GetRow(iRow).GetCell(iCell + ).ToString().Trim();
//表的英文名称
mTable.Code = sheet.GetRow(iRow + ).GetCell(iCell + ).ToString().Trim();
//表的描述
mTable.Comment = mTable.Name; //标题列 2014-05-03杜冬军修改,动态读取列,确保列顺序
var row = sheet.GetRow(iRow+);
//缓存列索引和名称
Dictionary<int, string> dic = new Dictionary<int, string>();
for (int i = iCell; i < row.LastCellNum; i++)
{
dic.Add(i, row.GetCell(i).ToString().Trim());
} iRow = iRow + ;
row = sheet.GetRow(iRow);
while (row != null)
{
if (row.GetCell(iCell) != null && !String.IsNullOrEmpty(row.GetCell(iCell).ToString()))
{
InitColumns(row, iCell, mTable,dic);
iRow = iRow + ;
row = sheet.GetRow(iRow);
}
else
{
break;
} } if (string.IsNullOrEmpty(mTable.Comment))
{
mTable.Comment = mTable.Name;
}
if (mTable.ListPkKeyInfo != null && mTable.ListPkKeyInfo.Count > )
{
foreach (PkKeyInfo pkInfo in mTable.ListPkKeyInfo)
{
mTable.PkKeyNameList = mTable.PkKeyNameList + pkInfo.Name + ",";
}
}
if (!string.IsNullOrEmpty(mTable.PkKeyNameList))
{
mTable.PkKeyNameList = mTable.PkKeyNameList.Substring(, mTable.PkKeyNameList.Length - );
}
Tables.Add(mTable);
return iRow;
}
catch (Exception ex)
{
throw ex;
}
} /// <summary>
/// 获取表中的列信息
/// </summary>
/// <param name="row">列节点</param>
/// <param name="iCell">列起始索引</param>
/// <param name="pTable">表信息</param>
/// <param name="dic">列名字典集合</param>
private void InitColumns(IRow row, int iCell, TableInfo pTable, Dictionary<int, string> dic)
{
ColumnInfo mColumn = new ColumnInfo();
//列ID
mColumn.ColumnObjectId = Guid.NewGuid().ToString();
string sTemp = "";
int LastCellIndex = dic.Keys.Last<int>();
for (int i = dic.Keys.First<int>(); i <= LastCellIndex; i++)
{
//2014-07-01杜冬军修改,row.LastCellNum取出来有误,确保不出现空异常
sTemp = row.GetCell(i) == null ? "" : row.GetCell(i).ToString().Trim();
Common.GetColumnInfo(dic, sTemp, mColumn, i, pTable);
}
mColumn.DataTypeStr = Common.GetDataTypeStr(mColumn.DataTypeStr, mColumn.Width);
mColumn.Width = Common.GetColumnWidth(mColumn.DataTypeStr); if (string.IsNullOrEmpty(mColumn.Comment))
{
mColumn.Comment = mColumn.Name;
}
if (string.IsNullOrEmpty(mColumn.DefaultValue))
{
mColumn.DefaultValue = "";
}
mColumn.Sequence = pTable.ListColumnInfo.Count + ;
pTable.ListColumnInfo.Add(mColumn);
}
}
}

上述代码的实现逻辑

  使用NPOI操作EXECL还是很方便的,2.0发布以后支持xlxs文件了,功能更加强大,其实EXECL和WORD的文件结构都是xml文件,只不过是相当复杂的。

NPOI帮我们封装好了这些差异方便使用。工具读取WORD文件之前也是采用NPOI组件,但是性能上存在问题,并且WORD单元格的合并很不好操作,最终采用了

DocX组件来替换它,性能真的提升很多,希望NPOI后面的版本能更好的支持WORD吧。这篇到这里就结束了,敬请期待下一篇DocX操作WORD。

  文中的实例提供下载:NPOIDemo

工具源代码下载

目前总共有经过了七个版本的升级,现在提供最新版本的下载地址

数据字典生成工具V2.0安装程序 最新安装程序
数据字典生成工具源代码 最新源代码
http://code.taobao.org/svn/DataDicPub SVN最新源码共享地址

学习使用

如果你使用了该工具,或者想学习该工具,欢迎加入这个小组,一起讨论数据字典生成工具、把该工具做的更强,更方便使用,一起加入147425783 QQ群

      更多数据字典生成工具资料请点击数据字典生成工具专题

如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的推荐按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我

如果,想给予我更多的鼓励,求打

因为,我的写作热情也离不开您的肯定支持。

感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是焰尾迭 。

数据字典生成工具之旅(4):NPOI操作EXECL的更多相关文章

  1. 数据字典生成工具之旅(3):PowerDesign文件组成结构介绍及操作

    从这篇开始将正式讲解整个重要部分的实现细节,本篇讲解Pdm文件的解析.其实PDM文件就是XML文件,可以用Editplus或者VS打开查看.了解到这一点之后大家就能猜到,可以用解析XML的方式读取PD ...

  2. 数据字典生成工具之旅(5):DocX组件读取与写入Word

    由于上周工作比较繁忙,所以这篇文章等了这么久才写(预告一下,下一个章节正式进入NVelocity篇,到时会讲解怎么使用NVelocity做一款简易的代码生成器,敬请期待!),好了正式进入本篇内容. 这 ...

  3. 数据字典生成工具之旅(6):NVelocity语法介绍及实例

    本章开始将会为大家讲解NVelocity的用法,并带领大家实现一个简单的代码生成器. NVelocity是一个基于.NET的模板引擎(template engine).它允许任何人仅仅简单的使用模板语 ...

  4. 数据字典生成工具之旅(7):NVelocity实现代码生成器

    这个系统好久没有更新了,人也慢慢变懒了,从现在开始每个月至少写三篇文章,欢迎大家监督.对了预告一下,该系列完成以后将为大家带来WebApp开发系列篇,敬请期待.先上几张图,放在文章最后面欢迎预览! 本 ...

  5. 数据字典生成工具之旅(8):SQL查询表的约束默认值等信息

    上一篇代码生成工具里面已经用到了读取表结构的SQL,这篇将更加详细的介绍SQL SERVER常用的几张系统表和视图! 阅读目录 系统表视图介绍 实际应用 本章总结 工具源代码下载 学习使用 回到顶部 ...

  6. 数据字典生成工具(生成Excel, Word,PDF,html)

    转自:http://www.cnblogs.com/yanweidie/p/3838765.html 数据字典生成工具之旅系列文章导航 数据字典生成工具之旅系列文章导航 宣传语 数据字典生成工具.数据 ...

  7. 【C#附源码】数据库文档生成工具支持(Excel+Html)

    [2015] 很多时候,我们在生成数据库文档时,使用某些工具,可效果总不理想,不是内容不详细,就是表现效果一般般.很多还是word.html的.看着真是别扭.本人习惯用Excel,所以闲暇时,就简单的 ...

  8. NPOI操作EXCEL(四)——反射机制批量导出excel文件

    前面我们已经实现了反射机制进行excel表格数据的解析,既然有上传就得有下载,我们再来写一个通用的导出方法,利用反射机制实现对系统所有数据列表的筛选结果导出excel功能. 我们来构想一下这样一个画面 ...

  9. css sprite,css雪碧图生成工具V3.0更新

    V3.0主要改进 1.增加了单独添加单张图片以及删除单张图片的功能 2.增加了生成.sprite文件用以保存雪碧图信息 3.增加了打开.sprite文件功能 什么是css sprite CSS spr ...

随机推荐

  1. 每日Scrum(4)

    今天是冲刺第4天,小组也没有做什么,大家都忙着找大二的学弟学妹来点评来支持我们的软件. 遇到的问题主要是如何劝说学弟学妹选择我们的软件然后继续往下做.

  2. ORACLE 查看有多个执行计划的SQL语句

    在SQL优化过程,有时候需要查看哪些SQL具有多个执行计划(Multiple Executions Plans for the same SQL statement),因为同一个SQL有多个执行计划一 ...

  3. oracle存储过程--导出数据库表的说明文档

    Oracle查询表的名字和comments select a.table_name,b.comments from user_tables a,ALL_TAB_COMMENTS b where a.t ...

  4. [Java入门笔记] Java语言简介

    前言 学习Java有一段时间了,但是一直缺少一个系统的思想,现在重新通过书籍中.网上的文章,视频等资料,整理与回顾Java的知识点. 言归正传,让我们先从了解Java语言开始. Java语言的由来 J ...

  5. App_Data 目录中的数据库位置指定了一个本地 SQL Server

    <configuration> <system.web> <compilation debug="true" targetFramework=&quo ...

  6. android WebView网页浏览器

    组件位置:composite>WebView .xml <WebView android:id="@+id/webview_pipeweb" android:layou ...

  7. 关于TreeView的选中事件

    在使用TreeView的选中事件时,发现,SelectAfter在第一次选中时触发,你再次点击时这个事件并不能引发它.所以找了找,发现有另两种解决办法. 最好的就是使用:NodeMouseClick, ...

  8. Windows Azure Redis 缓存服务

    8月20日,Windows Azure (中国版)开始提供Redis缓存服务,比较国际版的Microsoft Azure晚了差不多一年的时间.说实话,微软真不应该将这个重要的功能delay这么长时间, ...

  9. 查看centos系统版本

    1.查看系统版本 [root@yl-web yl]# cat /etc/redhat-release CentOS Linux release 7.1.1503 (Core) 2.查看内核版本 [ro ...

  10. [转]How do I use variables in Oracle SQL Developer?

    本文转自:http://stackoverflow.com/questions/5653423/how-do-i-use-variables-in-oracle-sql-developer Below ...