久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4753|回復: 1
打印 上一主題 下一主題
收起左側

C#導出數據到exceil表格中的方法和源代碼(附超級無敵詳細講解)

[復制鏈接]
跳轉到指定樓層
樓主
如果你耐心仔細看完本文,相信以后再遇到導出EXCLE操作的時候你會很順手覺得SO EASY,主要給新手朋友們看的,老鳥可以直接飄過了,花了一晚上的時間寫的很辛苦,如果覺得對你有幫助煩請留言支持一下,我會寫更多基礎的原創內容來回報大家。

C#導出數據到EXCEL表格是個老生常談的問題了,寫這篇文章主要是給和我一樣的新手朋友提供兩種導出EXCEL的方法并探討一下導出的效率問題,本文中的代碼直接就可用,其中部分代碼參考其他的代碼并做了修改,拋磚引玉,希望大家一起探討,如有不對的地方還請大家多多包涵并指出來,我也是個新手,出錯也是難免的。

首先先總結下自己知道的導出EXCEL表格的方法,大致有以下幾種,有疏漏的請大家補充。
1.數據逐條逐條的寫入EXCEL
2.通過OLEDB把EXCEL做為數據源來寫
3.通過RANGE范圍寫入多行多列內存數據到EXCEL
4.利用系統剪貼板寫入EXCEL

好了,我想這些方法已經足夠完成我們要實現的功能了,方法不在多,在精,不是么?以上4中方法都可以實現導出EXCEL,方法1為最基礎的方法,意思就是效率可能不是太高,當遇到數據量過大時所要付出的時間也是巨大的,后面3種方法都是第一種的衍生,在第一種方法效率低下的基礎上改進的,這里主要就是一個效率問題了,當然如果你數據量都很小,我想4種方法就代碼量和復雜程度來說第1種基本方法就可以了,或當你的硬件非常牛逼了,那再差的方法也可以高效的完成也沒有探討的實際意義了,呵呵說遠了,本文主要是在不考慮硬件或同等硬件條件下單從軟件角度出發探討較好的解決方案。
此項目代碼已打包在附件中,幾乎注釋的無微不至,在配合本文中我唐僧般的娓娓道來(靠,誰丟臭雞蛋砸俺了),相信即使剛入門C#的朋友也能看得懂了吧,大家可以自行下載,代碼中演示了兩種方法,上述的方法1和方法3,我想足夠了,方法3的效率應該是四種中最高的了,其他兩種有興趣的朋友自己實現下哈(方法2在我的程序中也有用到一些,看完你就知道了),程序如下圖所示,先加載一個EXCEL表格進DATAGRIDVIEW作為數據源,然后兩種方法導出EXCEL,配上一個計數功能給大家直觀的看到導出的耗時,大家可以準備個幾萬行和十多行的兩個EXCEL作為數據源來測試,也可以用我打包里的XLS來測試下。


首先使用前都需要加載COM組件Microsoft.Office.Interop.Excel.dll(已打包)

關鍵代碼如下:
方法1,最基本方法,用FOR循環逐條寫入EXCELCELL中,其他的看代碼就行了,關鍵代碼如下
public void ToExcel1(DataGridViewgridView, SaveFileDialog saveFileDialog)
{
...........................
for (int i = 0; i < gridView.RowCount; i++)
{
for (int j = 0; j < gridView.ColumnCount; j++)
{
if (gridView[j,i].Value == typeof(string))
{
excel.Cells[i +2, j + 1] = "" + gridView[i,j].Value.ToString();
}
else
{
excel.Cells[i +2, j + 1] = gridView[j, i].Value.ToString();
}
}
//進度條加1
progressBar1.Value++;
/*
* 注意此Application.DoEvents(),如果無此句,當切換窗口后回到本程序無法重繪窗體會出現假死狀態
* 此處我試過用委托和線程異步調用的方法,但效果沒有這句效果好
*/                            System.Windows.Forms.Application.DoEvents();
...................
}

方法2快速保存內存中大量數據到ExcelWorkSheet。關鍵之處是使用Range一次存儲多行多列數據。
public void ToExcel2(DataGridViewgridView, SaveFileDialog saveFileDialog)
{
....................
System.Reflection.Missing miss = System.Reflection.Missing.Value;
//創建EXCEL對象appExcel,Workbook對象,Worksheet對象,Range對象
Microsoft.Office.Interop.Excel.Application appExcel;
appExcel = new Microsoft.Office.Interop.Excel.Application();                    
Microsoft.Office.Interop.Excel.Workbook workbookData;                    
Microsoft.Office.Interop.Excel.Worksheet worksheetData;                  
Microsoft.Office.Interop.Excel.Range rangedata;
//設置對象不可見
appExcel.Visible= false;
/* 在調用Excel應用程序,或創建Excel工作簿之前,記著加上下面的兩行代碼
* 這是因為Excel有一個Bug,如果你的操作系統的環境不是英文的,而Excel就會在執行下面的代碼時,報異常。
*/
System.Globalization.CultureInfo CurrentCI = System.Threading.Thread.CurrentThread.CurrentCulture;                   System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
workbookData =appExcel.Workbooks.Add(miss);
worksheetData=(Microsoft.Office.Interop.Excel.Worksheet)workbookData.Worksheets.Add(miss,miss, miss, miss);
//給工作表賦名稱
worksheetData.Name= "saved";
//清零計數并開始計數
TimeP = new System.DateTime(0);
timer1.Start();
label1.Text =TimeP.ToString("HH:mm:ss");
// 保存到WorkSheet的表頭,你應該看到,是一個Cell一個Cell的存儲,這樣效率特別低,解決的辦法是,使用Rang,一塊一塊地存儲到Excel
for (int i = 0; i < gridView.ColumnCount; i++)
{
worksheetData.Cells[1,i + 1] = gridView.Columns[ i].HeaderText.ToString();
}
//先給Range對象一個范圍為A2開始,Range對象可以給一個CELL的范圍,也可以給例如A1H10這樣的范圍
//因為第一行已經寫了表頭,所以所有數據都應該從A2開始
rangedata =worksheetData.get_Range("A2",miss);
Microsoft.Office.Interop.Excel.Range xlRang = null;
//iRowCount為實際行數,最大行
int iRowCount =gridView.RowCount;
int iParstedRow =0, iCurrSize = 0;
//iEachSize為每次寫行的數值,可以自己設置,每次寫1000行和每次寫2000行大家可以自己測試下效率
int iEachSize =1000;
//iColumnAccount為實際列數,最大列數
int iColumnAccount= gridView.ColumnCount;
//在內存中聲明一個iEachSize×iColumnAccount的數組,iEachSize是每次最大存儲的行數,iColumnAccount就是存儲的實際列數
object[,] objVal = new object[iEachSize,iColumnAccount];
try
{
//給進度條賦最大值為實際行數最大值
progressBar1.Maximum= gridView.RowCount;
iCurrSize =iEachSize;

while (iParstedRow< iRowCount)
{
if ((iRowCount -iParstedRow) < iEachSize)
iCurrSize =iRowCount - iParstedRow;
//FOR循環給數組賦值
for (int i = 0; i < iCurrSize; i++)
{
for (int j = 0; j < iColumnAccount; j++)
objVal[i, j] =gridView[j, i + iParstedRow].Value.ToString();
progressBar1.Value++;                              System.Windows.Forms.Application.DoEvents();
}
/*
* 建議使用設置斷點研究下哈
* 例如A1H10的意思是從AH,第一行到第十行
* 下句很關鍵,要保證獲取Sheet中對應的Range范圍
* 下句實際上是得到這樣的一個代碼語句xlRang= worksheetData.get_Range("A2","H100");
* 注意看實現的過程
*'A' + iColumnAccount - 1這兒是獲取你的最后列,A的數字碼為65,大家可以仔細看下是不是得到最后列的字母
*iParstedRow + iCurrSize + 1獲取最后行
* WHILE第一次循環的話這應該是A2,最后列字母+最后行數字
*iParstedRow + 2要注意,每次循環這個值不一樣,他取決于你每次循環RANGE取了多大,循環了幾次,也就是iEachSize設置值的大小哦
*/
xlRang =worksheetData.get_Range("A" + ((int)(iParstedRow + 2)).ToString(), ((char)('A' +iColumnAccount - 1)).ToString() + ((int)(iParstedRow+ iCurrSize + 1)).ToString());
// 調用RangeValue2屬性,把內存中的值賦給Excel
xlRang.Value2 =objVal;
iParstedRow =iParstedRow + iCurrSize;
}
//保存工作表
worksheetData.SaveAs(strName,miss, miss, miss, miss, miss, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, miss, miss,miss);                                              System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRang);
xlRang = null;
progressBar1.Value= 0;
//調用方法關閉EXCEL進程,大家可以試下不用的話如果程序不關閉在進程里一直會有EXCEL.EXE這個進程并鎖定你的EXCEL表格
this.KillSpecialExcel(appExcel);
timer1.Stop();
MessageBox.Show("數據已經成功導出到:" +saveFileDialog.FileName.ToString(), "導出完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
timer1.Stop();
return;
}
// 別忘了在結束程序之前恢復你的環境!                   System.Threading.Thread.CurrentThread.CurrentCulture = CurrentCI;

最后再順便說下本程序中的一些部分:
1.做過EXCEL導出的朋友應該遇到過一個情況,當導出完畢后進程中那個討厭的EXCEL.EXE老是無法關閉,造成鎖定導出的XLS文件,要關閉程序后該進程才退出,網上也有一種方法就是我方法ToExcel1()用到的那個方法(詳見下載的代碼),但我寫ToExcel2()方法的時候發現這種關閉的方法突然不好使了,這我用到了另一種方法KillSpecialExcel,調用的時候這樣調用this.KillSpecialExcel(appExcel)大家可以試下把ToExcel2()改為ToExcel1()的關閉EXCEL方法看是否有效,代碼如下

#region 結束EXCEL.EXE進程的方法
/// <summary>
/// 結束EXCEL.EXE進程的方法
/// </summary>
/// <paramname="m_objExcel">EXCEL對象</param>
[DllImport("user32.dll",SetLastError = true)]
static extern intGetWindowThreadProcessId(IntPtr hWnd, out intlpdwProcessId);

public void KillSpecialExcel(Microsoft.Office.Interop.Excel.Application m_objExcel)
{
try
{
if (m_objExcel !=null)
{
int lpdwProcessId;
GetWindowThreadProcessId(new IntPtr(m_objExcel.Hwnd),out lpdwProcessId);                   System.Diagnostics.Process.GetProcessById(lpdwProcessId).Kill();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
2.代碼里寫了個加載EXCELDATAGRIDVIEW的方法,就是想本來就是在寫EXCEL操作相關嘛,干脆數據源也用EXCEL,該方法就是把EXCEL作為OLEDB數據源這樣來操作的,你是不是想到前面我所提到的四種導出EXCEL中的《方法2通過OLEDBEXCEL做為數據源來寫》呢,對了,有興趣你可以嘗試修改下通過OLEDB這樣來導出EXCEL當然,新手朋友可以看下如何加載EXCEL數據,你應該希望去嘗試接著如何把這些數據儲存到數據庫之類的操作
3.System.Windows.Forms.Application.DoEvents()當運行 Windows 窗體時,它將創建新窗體,然后該窗體等待處理事件。該窗體在每次處理事件時,均將處理與該事件關聯的所有代碼。所有其他事件在隊列中等待。在代碼處理事件時,應用程序并不響應。例如,當將另一窗口拖到該窗口前面時,該窗口不重新繪制。如果在代碼中調用 DoEvents,則您的應用程序可以處理其他事件。例如,如果您有向 ListBox 添加數據的窗體,并將 DoEvents 添加到代碼中,那么當將另一窗口拖到您的窗體上時,該窗體將重新繪制。如果從代碼中移除 DoEvents,那么在按鈕的單擊事件處理程序執行結束以前,您的窗體不會重新繪制。
這里說遠一點,關于如何防止UI假死其實還有更科學的方法,就是使用委托加線程異步執行,把耗時的操作另起進程執行,從而減輕UI的壓力,使得前臺UI流暢運行而不假死,多用this.Invoke等,但在我程序用我也測試過反而直接DoEvents效果還好的多,而且線程和委托可能對新手朋友稍微復雜了些,推薦一般應用用DoEvents足夠了哦。

好了,東西不多廢話一大篇,手都寫累了,基本上用到的方法都做了詳細的解釋了,呵呵,希望以后大家多多交流,本人菜鳥一個,寫本文就是因為自己也得到過很多熱心網友的指導和幫助,也希望分享一些自己的東西作為回報,人人為我,我為人人,學會做個懂得感恩的人比什么都重要,歡迎大家和我一起學習套談C#



全部資料下載地址:
C#導出數據到EXCEL方法談(附實例源碼和超級無敵詳細講解).rar (560.85 KB, 下載次數: 74)


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:1 發表于 2017-6-5 17:03 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 好姑娘影视在线观看高清 | 日韩一区在线播放 | 一级高清 | 中文字幕久久精品 | 成人黄色a | 久久久99精品免费观看 | 日韩视频在线免费观看 | 欧美精品一区在线发布 | 中文字幕高清 | 精品欧美乱码久久久久久 | 久久中文字幕电影 | 久久av一区二区三区 | 久久久久久国产免费视网址 | 久久精品久久久 | 美女视频一区二区 | 欧产日产国产精品视频 | 国产91久久久久久 | 午夜小电影 | 欧美性生活一区二区三区 | 中文字幕一区二区三区不卡在线 | 一区在线视频 | 中文字幕在线视频免费视频 | av在线免费观看网站 | 色婷婷久久久久swag精品 | 欧美视频在线看 | 天天夜夜操 | 国产资源在线观看 | 国产sm主人调教女m视频 | 成人精品免费视频 | 人人看人人射 | 最近中文字幕在线视频1 | 久久精品亚洲精品 | 国产一区二区在线播放 | 日日天天 | 欧美日韩一区二区在线 | 久久久免费少妇高潮毛片 | 欧美成人a∨高清免费观看 老司机午夜性大片 | 久久国品片 | 亚洲精品3 | 中文字幕免费在线 | 日韩伦理一区二区三区 |