首页 > 代码库 > 数据字典生成工具之旅(4):NPOI操作EXECL

数据字典生成工具之旅(4):NPOI操作EXECL

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

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

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

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

阅读目录

  • NPOI简介
  • 简单示例
  • 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(1);            for (int i = 0; i < 20; 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 = 0; i < wk.NumberOfSheets; i++)  //NumberOfSheets是myxls.xls中总共的表数                {                    ISheet sheet = wk.GetSheetAt(i);   //读取当前表数据                    for (int j = 0; j <= sheet.LastRowNum; j++)  //LastRowNum 是当前表的总行数                    {                        IRow row = sheet.GetRow(j);  //读取当前行数据                        if (row != null)                        {                            sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限                            for (int k = 0; 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 = 0; i < wk.NumberOfSheets; i++)  //NumberOfSheets是myxls.xls中总共的表数                {                    ISheet sheet = wk.GetSheetAt(i);   //读取当前表数据                    for (int j = 0; j <= sheet.LastRowNum; j++)  //LastRowNum 是当前表的总行数                    {                        IRow row = sheet.GetRow(j);  //读取当前行数据                        if (row != null)                        {                            sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限                            for (int k = 0; 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 = 0; 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 = 0; i < iLastRowNum; i++)                    {                        row = sheet.GetRow(i);                        if (row == null)                        {                            continue;                        }                        for (int j = 0; 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 = 0; 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 > 0)            {                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 + 2).ToString().Trim();                //表的英文名称                mTable.Code = sheet.GetRow(iRow + 1).GetCell(iCell + 2).ToString().Trim();                //表的描述                mTable.Comment = mTable.Name;                //标题列 2014-05-03杜冬军修改,动态读取列,确保列顺序                var row = sheet.GetRow(iRow+3);                //缓存列索引和名称                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 + 4;                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 + 1;                        row = sheet.GetRow(iRow);                    }                    else                    {                        break;                    }                }                if (string.IsNullOrEmpty(mTable.Comment))                {                    mTable.Comment = mTable.Name;                }                if (mTable.ListPkKeyInfo != null && mTable.ListPkKeyInfo.Count > 0)                {                    foreach (PkKeyInfo pkInfo in mTable.ListPkKeyInfo)                    {                        mTable.PkKeyNameList = mTable.PkKeyNameList + pkInfo.Name + ",";                    }                }                if (!string.IsNullOrEmpty(mTable.PkKeyNameList))                {                    mTable.PkKeyNameList = mTable.PkKeyNameList.Substring(0, mTable.PkKeyNameList.Length - 1);                }                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 + 1;            pTable.ListColumnInfo.Add(mColumn);        }    }}
View Code

      上述代码的实现逻辑

       

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

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

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

  文中的实例提供下载:NPOIDemo

回到顶部

工具源代码下载

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

数据字典生成工具V2.0安装程序最新安装程序
数据字典生成工具源代码最新源代码
回到顶部

学习使用

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

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