C#--NPOI操作Excel總結


詳細教程:

NPOI使用手冊——c# - vv彭 - 博客園 (cnblogs.com)

1,NPOI讀取Excel高低版本兼容性問題

報錯1:NPOI.POIFS.FileSystem.OfficeXmlFileException   HResult=0x80070057   Message=The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process

報錯2:NPOI.POIFS.FileSystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)

原因:這是因為NPOI讀取2003時使用的是HSSFWorkbook,更高版本讀取需要使用XSSFWorkbook

解決方式:

將代碼中HSSFWorkbook修改為XSSFWorkbook,最好是導入文件時選擇版本,這樣處理更好

IWorkbook workbook = new XSSFWorkbook(file);

2,NPOI讀取Excel帶計算公式的值

        /// <summary>
        /// 根據填充后的綜合判定表來綜合判定是否OK(獲取帶公式列的值)
        /// </summary>
        /// <param name="filePath">填充后的綜合判定表打印版的文件路徑</param>
        public static void Step4(FilePath filePath)
        {
            XSSFWorkbook workbook;
            XSSFFormulaEvaluator evalor = null;
            using (FileStream fs = File.Open(filePath.PrintMatchFilePath, FileMode.Open,
                FileAccess.Read, FileShare.ReadWrite))
            {
                //把xls文件讀入workbook變量里,之后就可以關閉了  
                workbook = new XSSFWorkbook(fs);

                //【帶公式取值步驟1】創建當前sheet 的動態公式計算器
                evalor = new XSSFFormulaEvaluator(workbook);
                fs.Close();
            }

            ISheet sheet = workbook.GetSheetAt(0);
            int rowCount = sheet.LastRowNum;

            int StandardTotalCount = 0;
            int OKTotalCount = 0;

            ICell cellObj = sheet.GetRow(21).GetCell(3);
            var cellType = cellObj.CellType;
            switch (cellType)
            {
                case CellType.Formula:
                    //【帶公式取值步驟2】針對公式列 進行動態計算;注意:公式暫時只支持 數值 字符串類型
                    var formulaValue = evalor.Evaluate(cellObj);
                    if (formulaValue.CellType == CellType.Numeric)
                    {
                        double b = formulaValue.NumberValue;
                        StandardTotalCount = Convert.ToInt32(b);
                    }
                    else if (formulaValue.CellType == CellType.String)
                    {
                        string s = formulaValue.StringValue;
                    }

                    break;
                default:
                    break;
            }

            ICell cellObj2 = sheet.GetRow(21).GetCell(4);
            var cellType2 = cellObj2.CellType;
            switch (cellType2)
            {
                case CellType.Formula:
                    //針對公式列 進行動態計算;注意:公式暫時只支持 數值 字符串類型
                    var formulaValue = evalor.Evaluate(cellObj2);
                    if (formulaValue.CellType == CellType.Numeric)
                    {
                        double b = formulaValue.NumberValue;
                        OKTotalCount = Convert.ToInt32(b);
                    }
                    else if (formulaValue.CellType == CellType.String)
                    {
                        string s = formulaValue.StringValue;
                    }

                    break;
                default:
                    break;
            }


            if (StandardTotalCount == OKTotalCount)
            {
                sheet.GetRow(21).GetCell(6).SetCellValue("OK");
            }
            else
            {
                sheet.GetRow(21).GetCell(6).SetCellValue("NG");
            }

            //轉為字節數組  
            MemoryStream stream = new MemoryStream();
            workbook.Write(stream);
            var buf = stream.ToArray();
            //保存為Excel文件  這種方式能保存.xls和.xlsx文件
            using (FileStream fs = new FileStream(filePath.PrintMatchFilePath, FileMode.Create, FileAccess.Write))
            {
                fs.Write(buf, 0, buf.Length);
                fs.Flush();
            }
        }

  

3,元格帶有公式的值不能自動更新

            ISheet sheet = workbook.GetSheetAt(0);

            //解決單元格帶有公式的值不能自動更新
            //解決辦法:在程序最后添加一句(關閉文件前),使得sheetdata自動重算【我測試過不用放在關閉文件前也可以的】
            sheet.ForceFormulaRecalculation = true;

  

4,設置打印頁面縮放和自適應列寬

        /// <summary>
        /// 自適應列寬和打印頁縮放
        /// </summary>
        /// <param name="filePath">excel文件路徑</param>
        /// <param name="scale">縮放比例(77,80,100等)</param>
        public static void AutoColumnWidth(string filePath,short scale=80)
        {
            //【1】打開excel文件的第幾張表,第幾行的數據,返回一個字典{列名:列的索引}
            //字典的作用:可以根據列名快速找到對應的列索引
            Dictionary<string, int> dicData = ExcelHelper.GetDataDictionary(filePath, 1, 1);

            bool isCompatible = ExcelHelper.GetIsCompatible(filePath);
            IWorkbook workbook = null;

            using (FileStream fs = File.Open(filePath, FileMode.Open,
                FileAccess.Read, FileShare.ReadWrite))
            {
                //把xls文件讀入workbook變量里,之后就可以關閉了  
                workbook = ExcelHelper.CreateWorkbook(isCompatible, fs);
                fs.Close();
            }

            ISheet sheet = workbook.GetSheetAt(0);

            int rowCount = sheet.LastRowNum;


            for (int col = 0; col < sheet.GetRow(0).LastCellNum; col++)
            {
                //自適應列寬
                sheet.AutoSizeColumn(col);
            }

            //sheet.PrintSetup.FitWidth = 1;
            //sheet.PrintSetup.FitHeight = 0;

            //設置打印頁面縮放比例
            sheet.PrintSetup.Scale = scale;

            #region 非常的耗時,不推薦使用

            ////開始遍歷【遍歷行操作】
            //for (int r = 1; r <= rowCount; r++) //從第二行開始遍歷
            //{
            //    IRow currentRow = sheet.GetRow(r); //讀取當前行數據
            //    if (currentRow == null) //如果為空,重新創建一行,防止null報錯
            //    {
            //        sheet.CreateRow(r);
            //        currentRow = sheet.GetRow(r);
            //    }

            //    for (int i = 0; i < currentRow.LastCellNum; i++)
            //    {
            //        //sheet.AutoSizeColumn(i);//非常的耗時,不推薦用
            //    }               
            //}

            #endregion

            //轉為字節數組  
            MemoryStream stream = new MemoryStream();
            workbook.Write(stream);
            var buf = stream.ToArray();
            //保存為Excel文件  這種方式能保存.xls和.xlsx文件
            using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
            {
                fs.Write(buf, 0, buf.Length);
                fs.Flush();
            }
        }

  

行或單元格為null報錯問題:

        private void Step6()
        {

            //【1】打開excel文件的第幾張表,第幾行的數據,返回一個字典{列名:列的索引}
            //字典的作用:可以根據列名快速找到對應的列索引
            Dictionary<string, int> dicData = ExcelHelper.GetDataDictionary(filePath.CheckFilePath, 1, 2);

            bool isCompatible = ExcelHelper.GetIsCompatible(filePath.CheckFilePath);

            IWorkbook workbook = null;

            using (FileStream fs = File.Open(filePath.CheckFilePath, FileMode.Open,
            FileAccess.Read, FileShare.ReadWrite))
            {
                //把xls文件讀入workbook變量里,之后就可以關閉了  
                workbook = ExcelHelper.CreateWorkbook(isCompatible, fs);
                fs.Close();
            }

            ICellStyle sOK = workbook.CreateCellStyle(); //設置單元格的背景顏色需要用到的代碼
            sOK.FillForegroundColor = HSSFColor.SeaGreen.Index; //設置單元格的背景顏色需要用到的代碼
            sOK.FillPattern = FillPattern.SolidForeground; //設置單元格的背景顏色需要用到的代碼

            ICellStyle sNOK = workbook.CreateCellStyle(); //設置單元格的背景顏色需要用到的代碼
            sNOK.FillForegroundColor = HSSFColor.Red.Index; //設置單元格的背景顏色需要用到的代碼
            sNOK.FillPattern = FillPattern.SolidForeground; //設置單元格的背景顏色需要用到的代碼

            ICellStyle sCheck = workbook.CreateCellStyle(); //設置單元格的背景顏色需要用到的代碼
            sCheck.FillForegroundColor = HSSFColor.Yellow.Index; //設置單元格的背景顏色需要用到的代碼
            sCheck.FillPattern = FillPattern.SolidForeground; //設置單元格的背景顏色需要用到的代碼

            ISheet sheet = workbook.GetSheetAt(0);

            int rowCount = sheet.LastRowNum;
            //開始遍歷【遍歷行操作】
            for (int r = 1; r <= rowCount; r++) //從第二行開始遍歷
            {
                IRow currentRow = sheet.GetRow(r); //讀取當前行數據
                if (currentRow == null) //如果為空,重新創建一行,防止null報錯
                {
                    sheet.CreateRow(r);
                    currentRow = sheet.GetRow(r);
                }

                //物料編碼
                if (currentRow.GetCell(dicData["物料編碼"]) == null)
                {
                    currentRow.CreateCell(dicData["物料編碼"]);
                };
                string materialNumber = currentRow.GetCell(dicData["物料編碼"]).ToString();
                //訂單編號
                string orderNumber = currentRow.GetCell(dicData["訂單編號"]).ToString();
                //行號
                string lineNumber = currentRow.GetCell(dicData["行號"]).ToString();

                //未到貨數量
                string orderQuantity = currentRow.GetCell(dicData["未到貨數量"]).ToString();
                int iOrderQuantity;
                iOrderQuantity=int.TryParse(orderQuantity, out iOrderQuantity)? iOrderQuantity : -1;

                #region 避開第二步的標識

                if (currentRow.GetCell(dicData["供應商是否更改供應商承諾交期(Y/N)"]) == null)
                {
                    currentRow.CreateCell(dicData["供應商是否更改供應商承諾交期(Y/N)"]);
                };
                if (currentRow.GetCell(dicData["供應商是否更改供應商承諾交期(Y/N)"]).ToString() == "N") continue;
                #endregion

                //如果 現存量 中有 這個型號   .
                if (dicLatestPrice.ContainsKey(materialNumber))
                {
                    //獲取客戶的采購數量
                    string purchaseQuantity = currentRow.GetCell(dicData["采購訂單總數量"]).ToString(); ;
                    int iPurchaseQuantity;
                    int.TryParse(purchaseQuantity, out iPurchaseQuantity);

                    //獲取 可用量
                    int iAvailableQuantity = dicLatestPrice[materialNumber].AvailableQuantity;

                    // 獲取 現存量
                    int iOnHandQuantity = dicLatestPrice[materialNumber].OnHandQuantity;

                    //如果品牌是歐姆龍的
                    if (dicLatestPrice[materialNumber].Brand == "歐姆龍")
                    {
                        //且該物料編碼的 采購入庫待入量 大於等於 未到貨數量
                        if (dicLatestPrice[materialNumber].PurchaseQuantity > iOrderQuantity)
                        {
                            currentRow.GetCell(dicData["供應商是否更改供應商承諾交期(Y/N)"]).SetCellValue("N");
                            currentRow.GetCell(dicData["供應商是否更改供應商承諾交期(Y/N)"]).CellStyle = sOK;
                            if (currentRow.GetCell(dicData["目前物料的狀態"]) == null)
                                currentRow.CreateCell(dicData["目前物料的狀態"]);
                            currentRow.GetCell(dicData["目前物料的狀態"]).SetCellValue(dicLatestPrice[materialNumber].Brand + "已提貨");
                            currentRow.GetCell(dicData["目前物料的狀態"]).CellStyle = sOK;
                        }
                    }

                }
            }

            //轉為字節數組  
            MemoryStream stream = new MemoryStream();
            workbook.Write(stream);
            workbook.Close();//關閉工作薄

            var buf = stream.ToArray();
            //保存為Excel文件  這種方式能保存.xls和.xlsx文件
            using (FileStream fs = new FileStream(filePath.CheckFilePath, FileMode.Create, FileAccess.Write))
            {
                fs.Write(buf, 0, buf.Length);
                fs.Flush();
                fs.Dispose();//釋放文件流
            }

        }

  

 


免責聲明!

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



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