2013年5月14日 星期二

{C#} NPOI 進階-讀Excel 儲存格公式 取其結果方法

Excel的公式有很多種,有
1.日期型的公式
2.字串組合變化公式
3.純數值(儲存格數值)加總等公式
4.其他(還沒想到)

ps.NPOI版本為2.0
NPOI讀取公式類型的儲存格,其依以上不同而有不同的寫法

//每一格儲存格的資料類型為公式
//EX:Date('2010','4','1')、Sum($A1,$A2)、$A1 & $A2
if(hssfRow.GetCell(k).CellType==CellType.FORMULA)
{
     //由NPOI內提供的類別庫判斷公式結果類型

     IFormulaEvaluator iFormula = WorkbookFactory.CreateFormulaEvaluator(workbook);
     var formulaType = iFormula.Evaluate(hssfRow.GetCell(k)).CellType;
    //結果類型為數值(日期結果會被轉為數值)
     if (formulaType == CellType.NUMERIC)
    {
        ICell cell = iFormula.EvaluateInCell((hssfRow.GetCell(k)));
        // 判斷是否日期
         if (DateUtil.IsCellDateFormatted(cell))
           dr[k] = hssfRow.GetCell(k).DateCellValue;
         else
           dr[k] = hssfRow.GetCell(k).NumericCellValue;
    }
    //字串公式
    else if (formulaType == CellType.STRING)
       dr[k] = hssfRow.GetCell(k).StringCellValue;
    else
       dr[k] = hssfRow.GetCell(k).ToString();

}


參考資訊:
http://www.dotblogs.com.tw/smartleos/archive/2010/10/11/18284.aspx
http://tonyqus.sinaapp.com/archives/tag/excel-2007

2013年5月13日 星期一

{JavaScript} JS中資料轉Json格式中文成Unicode(\u...)問題

以下情況僅IE 8會發生..........以下解法經用IE 8測試OK

當在JS中將資料利用JSON.stringify()方式
轉為Json遇到中文時,會被成Unicode編碼

紅框為中文字

傳到後端會自動將Unicode解碼
但也可以手動在解碼一次

string factoryName = Regex.Unescape(jsonResult.FactoryName);
string lineName = Regex.Unescape(jsonResult.LineName);


前端的部分,JSON.parse會自動轉中文字
var data = JSON.parse(jsonResult);

參考資訊:

2013年5月9日 星期四

{C#} Excel.dll & NPOI 分析

Microsoft.Office.Interop.Excel;
 原理:開啟Server端Excel Application 讀取內容後關閉
 需求:Server端機器需加裝office Excel
 Code:
           Excel.Application xExcel = new Excel.Application();
            Excel.Workbook xbook = null;
            Excel.Worksheet xsheet = null;
            Excel.Range xRange = null;
            try
            {
               .......
            }
            finally
            {
                xbook.Close();
                xExcel.Quit();
                xbook = null;
                xsheet = null;
                xRange = null;
                xExcel = null;
                //確認已經沒有excel工作再回收
                GC.Collect();
            }

圖一、每New一次Excel.Application 使office Automation 啟動 即產生一個Process


嘗試以回收源方式關閉Process 無效;直接手動寫Code Kill Process 有一定的風險

                xbook.Close();
                xExcel.Quit();
                xbook = null;
                xsheet = null;
                xRange = null;
                xExcel = null;
                //確認已經沒有excel工作再回收
                GC.Collect();


嘗試引用已啟動的Excel.Application,在WinServer2008 R2 x64 OS下,出現Error Message
「HRESULT: 0x800401E3」
原因為Excel.Application被認定Running 無法被調用

 //檢查PC有無Excel在執行
            bool flag = false;
            foreach (var item in Process.GetProcesses())
            {
                if (item.ProcessName == "EXCEL")
                {
                    flag = true;
                    break;
                }
            }

            if (!flag)
            {
                xExcel = new Excel.Application();
            }
            else
            {
                ////延遲5秒載入
                //Thread.Sleep(5000);
                try
                {
                    //發生錯誤的地方
                    xExcel = (Excel.Application)Marshal.GetActiveObject("Excel.Application");//引用已在執行的Excel
                }
                catch (Exception)
                {
                }
             
            }

            if (xExcel != null) xExcel.Visible = true;//設false效能會比較好


NPOI
 原理:利用Java 函式庫POI轉包成.NET版本。POI直接深入到 OLE Compound Document 複合式  文件格式內存取資料,並物件導向化,外部開發人員利用POI 屬性去控制Office 檔案
 需求:NPOI 2.0 版本需引出多個Dll
 Code:
            Stream fileConent = File.Open(xlsPath, FileMode.Open);

////辯別是2007還是2003
            IWorkbook workbook = WorkbookFactory.Create(fileConent);

.....

//讀完一個Sheet關閉一個Sheet
                hs = null;

圖二、Excel物件的組成


NPOI目前每匯一張Excel僅透過Stream方式讀出資料,但讀取xlsx時,速度會因為xlsx架構是XmlSerializer  ,檔案越大,讀的速度越慢
http://npoi.codeplex.com/discussions/439282




OLE Compound Document 複合式文件:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms693383(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/dd942415.aspx

office運作與POI:
POI本身就是處理Office檔案的函式庫,Office都是微軟發展的OLE Compound Document 複合式文件,以結構化格式儲存在檔案中,由Excel物件模型去解析

參考來源:
http://www.dotblogs.com.tw/yc421206/archive/2012/03/09/70624.aspx

2013年5月6日 星期一

{C#} Microsoft.Office.Interop.Excel 引用 匯入Excel


Excel.Application:Excel應用程式
Excel.Workbook:應用程式裡的活頁簿,預設情況下,不管你開幾個Excel檔案,在工作管理員裡只會出現一個Excel.exe
Excel.Worksheet:活頁簿裡的工作表
Excel.Range:工作表裡的儲存格,一格也是Range,多格也是Range,用法Excel.Range[“A1”];
Excel.Range.Cells:這是儲存格的最小單位,代表一格的Range,用法Excel.Range.Cells[1,1];

//是否有Excel.exe 正在執行

void initailExcel()
        {
            //檢查PC有無Excel在執行
            bool flag = false;
            foreach (var item in Process.GetProcesses())
            {
                if (item.ProcessName == "EXCEL")
                {
                    flag = true;
                    break;
                }
            }
            if (!flag)
            {
                this._Excel = new Excel.Application();
            }
            else
            {
               //引用已在執行的Excel
                object obj = Marshal.GetActiveObject("Excel.Application");
                _Excel = obj as Excel.Application;
            }
            //設false效能會比較好
            this._Excel.Visible = true;
        }



開始讀Excel
  void openExcel(string filepath)
        {
            Excel.Workbook book = null;
            Excel.Worksheet sheet = null;
            Excel.Range range = null;
            DataTable arrdt = null;
            DataSet ds = new DataSet();
            string path = filepath;
            bool flag = false;
            try
            {
                book = _Excel.Workbooks.Open(path);//開啟舊檔案

                var sheetCount =book.Sheets.Count;
                //讀所有Sheet
                for(int i=1;i<=sheetCount;i++)
                {
                    arrdt = new DataTable();
                    sheet = (Excel.Worksheet)book.Sheets[i];
                    //sheet = (Excel.Worksheet)book.Sheets[1];//指定活頁簿,代表Sheet1
                    //sheet = (Excel.Worksheet)book.Sheets["Sheet1"];//也可以直接指定工作表名稱
                    Excel.Range xRange = sheet.UsedRange;
                   
                    //利用obj物件儲存值
                    object[,] valueArray = (object[,])xRange.get_Value(
                      Excel.XlRangeValueDataType.xlRangeValueDefault);

                    if (valueArray.Length > 0)  //陣列資料總個數大於零
                    {
                        int y = valueArray.GetLength(0);  //取得維度1的長度,即列數
                        int x = valueArray.GetLength(1);  //取得維度2的長度,即欄數
                        //建立欄名
                        for (int arri = 1; arri <= x; arri++)
                        {
                            if (valueArray.GetValue(1, arri) != null)
                                arrdt.Columns.Add(valueArray.GetValue(1, arri).ToString());
                            else
                                arrdt.Columns.Add("");

                        }

                        DataRow arrdr;
                        //建立資料
                        for (int arrj = 2; arrj <= y; arrj++)
                        {
                            flag = false;
                            arrdr = arrdt.NewRow();
                            for (int arrk = 1; arrk <= x; arrk++)
                            {
                                arrdr[arrk - 1] = (valueArray.GetValue(arrj, arrk) == null) ? "" : valueArray.GetValue(arrj, arrk).ToString();
                                if (arrdr[arrk - 1].ToString() != "")
                                    flag = true;
                            }
                            if(flag)
                                arrdt.Rows.Add(arrdr);
                        }
                    }
                    ds.Tables.Add(arrdt);
                }

                GridView1.DataSource = ds.Tables[0];
                GridView1.DataBind();
                GridView2.DataSource = ds.Tables[1];
                GridView2.DataBind();
            }
            finally
            {
                book.Close();
                book = null;
            }
        }


來源:
http://www.dotblogs.com.tw/yc421206/archive/2012/03/09/70624.aspx