數據字典生成工具之旅(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("-------------------------------------\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安裝程序 最新安裝程序
數據字典生成工具源代碼 最新源代碼
http://code.taobao.org/svn/DataDicPub SVN最新源碼共享地址

學習使用

      如果你使用了該工具,或者想學習該工具,歡迎加入這個小組,一起討論數據字典生成工具、把該工具做的更強,更方便使用,一起加入147425783 QQ群

      更多數據字典生成工具資料請點擊數據字典生成工具專題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM