zoukankan      html  css  js  c++  java
  • 数据字典生成工具之旅(4):NPOI操作EXECL

           这篇会介绍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(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("-------------------------------------
    "); //读取行与行之间的提示界限
                                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("-------------------------------------
    "); //读取行与行之间的提示界限
                                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安装程序 最新安装程序
    数据字典生成工具源代码 最新源代码
    http://code.taobao.org/svn/DataDicPub SVN最新源码共享地址

    学习使用

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

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

  • 相关阅读:
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1041:奇偶数判断
    1040:输出绝对值
    1040:输出绝对值
    1040:输出绝对值
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1039:判断数正负
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1039:判断数正负
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1039:判断数正负
    Winform应用程序实现通用遮罩层
    SQL WITH子句、分析函数
    SQL WITH子句、分析函数
  • 原文地址:https://www.cnblogs.com/yanweidie/p/3843517.html
Copyright © 2011-2022 走看看