記得有一次處理Excel文件對比,自己前后使用VBA和NPOI對比了下效率。由于涉及到頁面的渲染和刷新,二者的處理速度差了個數量級(10多秒和幾十分鐘的差別)。當然使用NPOI操作時也做了一定優化。印象這么深刻這次一有需求就想到了NPOI。
需求:財務數據,只挑出最新月份(整數類型,yyyyMM)的數據。然后將數據增加一部分固定列內容按格式寫入到另外一張表中。
由于宋丹丹老師把一切復雜的問題都總結為三步:打開冰箱門,把大象塞進去,關上冰箱門。那么我也把這個問題拆分出以下幾個三步走
1、打開數據源:
使用NPOI可以打開xls和xlsx類型的,這個沒有一點問題
由于使用了wpf,下面也又分為(以下沒有什么好說的都是正常代碼)
????????1.1 設置一個按鈕
????????1.2 點擊時彈出“打開文件”框
????????1.3如果選擇了文件就獲取文件路徑。
2、讀取數據:
上面獲取了文件路徑,我們就可以正常打開了。
對于如何讀取到合適的數據,我在這里有個優化
先只讀取日期列,找出最大日期的那些行。這里我用了一個Dictionary<DateTime, List<int>> 來保存行號。同時記錄了一個最大的日期值。通過這點只讀取了日期最大的行,會減少讀取操作。我覺得這一點
ISheet sheet = workbook.GetSheetAt(0);int cellcount = head.LastCellNum;//一行最多有多少個列long maxRow = sheet.LastRowNum;//頁面有多少行Dictionary<DateTime, List<int>> dateRows = new Dictionary<DateTime, List<int>>();var rows = new List<IRow>();for (int i = 1; i < maxRow; i++)//第一行是標題行,忽略{var row = sheet.GetRow(i);var cell = row.GetCell(0);//日期行,數據形式yyyyMMif (cell != null){var num=(int) cell.NumericCellValue;var year = num / 100;var mon = num% 100;var day = 1;var date = new DateTime(year, mon, day);if (dateRows.Keys.Contains(date)){dateRows[date].Add(i);}else{dateRows.Add(date, new List<int> { i });}}}
3、寫入并保存文件:
由于單元格有一定格式,我想了一個取巧的辦法-使用一個文件模板,保存的時候另存文件。
在數據寫入的時候又發現了一個優化點。有20多行他們之前是可以采用循環來賦值的。
//表1的第10行到34,對應表2的第18到42行,數據格式也一致,完美。for (int j = 9, k = 17; j < 34; j++, k++){if (srcRow.Cells[j].CellType == CellType.Numeric){row.CreateCell(k).SetCellValue(srcRow.Cells[j].NumericCellValue);}}
自我總結:一個簡單的程序,自頂向下的思路,逐步解決問題。優化要多碼,多總結。