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