渝中網(wǎng)站建設(shè)成都網(wǎng)絡(luò)營銷推廣公司
記得有一次處理Excel文件對比,自己前后使用VBA和NPOI對比了下效率。由于涉及到頁面的渲染和刷新,二者的處理速度差了個數(shù)量級(10多秒和幾十分鐘的差別)。當(dāng)然使用NPOI操作時也做了一定優(yōu)化。印象這么深刻這次一有需求就想到了NPOI。
需求:財務(wù)數(shù)據(jù),只挑出最新月份(整數(shù)類型,yyyyMM)的數(shù)據(jù)。然后將數(shù)據(jù)增加一部分固定列內(nèi)容按格式寫入到另外一張表中。
由于宋丹丹老師把一切復(fù)雜的問題都總結(jié)為三步:打開冰箱門,把大象塞進去,關(guān)上冰箱門。那么我也把這個問題拆分出以下幾個三步走
1、打開數(shù)據(jù)源:
使用NPOI可以打開xls和xlsx類型的,這個沒有一點問題
由于使用了wpf,下面也又分為(以下沒有什么好說的都是正常代碼)
????????1.1 設(shè)置一個按鈕
????????1.2 點擊時彈出“打開文件”框
????????1.3如果選擇了文件就獲取文件路徑。
2、讀取數(shù)據(jù):
上面獲取了文件路徑,我們就可以正常打開了。
對于如何讀取到合適的數(shù)據(jù),我在這里有個優(yōu)化
先只讀取日期列,找出最大日期的那些行。這里我用了一個Dictionary<DateTime, List<int>> 來保存行號。同時記錄了一個最大的日期值。通過這點只讀取了日期最大的行,會減少讀取操作。我覺得這一點
ISheet sheet = workbook.GetSheetAt(0);int cellcount = head.LastCellNum;//一行最多有多少個列l(wèi)ong 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++)//第一行是標(biāo)題行,忽略{var row = sheet.GetRow(i);var cell = row.GetCell(0);//日期行,數(shù)據(jù)形式y(tǒng)yyyMMif (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、寫入并保存文件:
由于單元格有一定格式,我想了一個取巧的辦法-使用一個文件模板,保存的時候另存文件。
在數(shù)據(jù)寫入的時候又發(fā)現(xiàn)了一個優(yōu)化點。有20多行他們之前是可以采用循環(huán)來賦值的。
//表1的第10行到34,對應(yīng)表2的第18到42行,數(shù)據(jù)格式也一致,完美。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);}}
自我總結(jié):一個簡單的程序,自頂向下的思路,逐步解決問題。優(yōu)化要多碼,多總結(jié)。