C#實現(xiàn)快速將數(shù)據(jù)寫入Excel單元格
性能問題
將生成或查詢到的數(shù)據(jù),導(dǎo)出到 Excel 是應(yīng)用中常用的一項功能。其中一些標(biāo)準(zhǔn)的寫入單元格的方法如下:
Worksheet worksheet = (Worksheet) excel.Worksheets[1]; //引用坐標(biāo)對Cells集合進行寫入 worksheet.Cells[1, 1] = "test"; //還可以引用地址進行寫入 worksheet.Cells["A1",Type.Missing]="test";
請注意,office 元素大多的起始序號均從 1 開始,而不是 0,如 worksheet,cells等。
現(xiàn)在我們假設(shè)有二維數(shù)組 object[,] dataobj ,遍歷式的寫法如下:
int arraywidth=dataobj.GetLength(1); int arrayheight=dataobj.GetLength(0); Worksheet worksheet = (Worksheet) excel.Worksheets[1]; for(int j=0;j<arrayheight;j++) { for(int k=0;k<arraywidth;k++) { worksheet.Cells[j+1,k+1]=dataobj[j,k]; }//end columns }// end rows
此種寫法在數(shù)據(jù)較少的時候在寫入速度方面沒有明顯差異,但當(dāng)大數(shù)據(jù)量的情況,多次的讀寫CELL單元格 IO 是一項非常耗時的操作,甚至?xí)o法完成應(yīng)用的預(yù)期目標(biāo)。
Excel元素結(jié)構(gòu)及寫入原理
元素結(jié)構(gòu)如下圖:
其中Range對象,代表了Excel單元格集合的指定區(qū)域。
如圖選中的Range范圍起始的單元格是第5行第3列,結(jié)束于第17行第8列。它相當(dāng)于object[13,6] 的一個二維數(shù)組,Excel的Range提供了get_Resize方法并通過Value2可以一次性的設(shè)置它們。
范例運行環(huán)境
操作系統(tǒng): Windows Server 2019 DataCenter
操作系統(tǒng)上安裝 Office Excel 2016
.net版本: .netFramework4.7.1 或以上
開發(fā)工具:VS2019 C#
配置Office DCOM
配置方法可參照我的文章《C#實現(xiàn)讀取Word表格到DataSet》進行處理和配置。
實現(xiàn)代碼
組件庫引入
核心代碼
WriteArrayToExcel
public void WriteArrayToExcel(object[,] dataobj,ExcelApplication excel,int ActiveSheetId,int StartRowId,int StartColId),該方法參數(shù)說明見下表:
序號 | 參數(shù) | 說明 |
1 | object[,] dataobj | 傳遞要寫入的二維對象數(shù)組 |
2 | ExcelApplication excel | 表示Excel應(yīng)用程序?qū)ο?/td> |
3 | int ActiveSheetId | 指定要寫入哪個工作ID,ID從1開始 |
4 | int StartRowId | 指定要寫入的開始行ID,ID從1開始 |
5 | int StartColId | 指定要寫入的開始列ID,ID從1開始 |
示例代碼如下:
public void WriteArrayToExcel(object[,] dataobj,ExcelApplication excel,int ActiveSheetId,int StartRowId,int StartColId) { Excel.Range _range; int arraywidth=dataobj.GetLength(1); int arrayheight=dataobj.GetLength(0); Worksheet worksheet = (Worksheet) excel.Worksheets[ActiveSheetId]; worksheet.Activate(); _range=excel.Range[excel.Cells[StartRowId,StartColId],excel.Cells[StartRowId+arrayheight-1,StartColId+arraywidth-1]]; _range.get_Resize(arrayheight,arraywidth); _range.Value2=dataobj; } //end writearraytoexcel
神奇的 911 事件
在 Excel 的早期版本(如Excel 2003)寫入的時,我們發(fā)現(xiàn)了一個現(xiàn)象,每寫入第 911個單元格的時候,且第911個單元數(shù)據(jù)為字符串類型的時候,會出現(xiàn)無響應(yīng)的情況。當(dāng)時的解決方案是將原始數(shù)組的每911元素值進行備份,并設(shè)置為空字符串,然后再對Cells單元格進行重寫,修改后的代碼如下:
public void WriteArrayToExcel(object[,] dataobj,ExcelApplication excel,int ActiveSheetId,int StartRowId,int StartColId) { Excel.Range _range; int arraywidth=dataobj.GetLength(1); int arrayheight=dataobj.GetLength(0); Worksheet worksheet = (Worksheet) excel.Worksheets[ActiveSheetId]; worksheet.Activate(); ArrayList ex_x = new ArrayList(); ArrayList ex_y = new ArrayList(); ArrayList ex_value = new ArrayList(); object _fvalue=""; int _maxlen=910; for(int j=0;j<arrayheight;j++) { for(int k=0;k<arraywidth;k++) { _fvalue=dataobj[j,k];// field value //備份每個第911個單元數(shù)據(jù) if(_fvalue.GetType().ToString()=="System.String") { if(((string)_fvalue).Length>_maxlen) { ex_x.Add(j+StartRowId); ex_y.Add(k+StartColId); ex_value.Add(_fvalue); _fvalue=""; }// end maxlen } dataobj[j,k]=_fvalue; }//end columns }// end rows _range=excel.Range[excel.Cells[StartRowId,StartColId],excel.Cells[StartRowId+arrayheight-1,StartColId+arraywidth-1]]; _range.get_Resize(arrayheight,arraywidth); _range.Value2=dataobj; //恢復(fù)重寫對應(yīng)的單元格 for(int j=0;j<ex_value.Count;j++) { excel.Cells[ex_x[j],ex_y[j]]=ex_value[j].ToString(); } } //end writearraytoexcel
小結(jié)
1、911單元格處理的方法是一種兼容性寫法,我們可以根據(jù)安裝的版本來決定是否需要這種寫法。
2、核心方法中輸入的起始行列,可以修改為更加直觀的CELL地址,如“A1”,"B5"等,有助于客戶進行應(yīng)用,提升友好性。
3、我們還可以改造傳遞二維數(shù)組集合,寫入多個worksheet,滿足更多需求,提升應(yīng)用程序的功能。
以上就是C#實現(xiàn)快速將數(shù)據(jù)寫入Excel單元格的詳細內(nèi)容,更多關(guān)于C#數(shù)據(jù)寫入Excel的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#使?XmlReader和XmlWriter操作XML?件
這篇文章介紹了C#使?XmlReader和XmlWriter操作XML?件的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06C++中const的實現(xiàn)細節(jié)介紹(C,C#同理)
本篇文章主要是對C++中const的實現(xiàn)細節(jié)進行了詳細的介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-01-01C#實現(xiàn)一個相當(dāng)全面的數(shù)據(jù)轉(zhuǎn)換工具類
這篇文章主要為大家介紹了如何使用C#編寫一個通用工具類DataConvert來進行數(shù)據(jù)轉(zhuǎn)換,包括30+個數(shù)據(jù)類型轉(zhuǎn)換,需要的可以了解一下2025-03-03C# DataTable與Model互轉(zhuǎn)的示例代碼
這篇文章主要介紹了C#DataTable與Model互轉(zhuǎn)的示例代碼,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-12-12C#中BitConverter.ToUInt16()和BitConverter.ToString()的簡單使用
這篇文章主要介紹了C#中BitConverter.ToUInt16()和BitConverter.ToString()的簡單使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02