欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
C#導出數據到exceil表格中的方法和源代碼(附超級無敵詳細講解)
[打印本頁]
作者:
神龍無敵16
時間:
2017-6-5 16:25
標題:
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來測試下。
0.png
(54.77 KB, 下載次數: 77)
下載附件
2017-6-5 17:00 上傳
首先使用前都需要加載
COM
組件
Microsoft.Office.Interop.Excel.dll
(已打包)
關鍵代碼如下:
方法
1
,最基本方法,用
FOR
循環逐條寫入
EXCEL
的
CELL
中,其他的看代碼就行了,關鍵代碼如下
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
,
快速保存內存中大量數據到
Excel
的
WorkSheet
。關鍵之處是使用
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
的范圍,也可以給例如
A1
到
H10
這樣的范圍
//
因為第一行已經寫了表頭,所以所有數據都應該從
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();
}
/*
*
建議使用設置斷點研究下哈
*
例如
A1
到
H10
的意思是從
A
到
H
,第一行到第十行
*
下句很關鍵,要保證獲取
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());
//
調用
Range
的
Value2
屬性,把內存中的值賦給
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.
代碼里寫了個加載
EXCEL
到
DATAGRIDVIEW
的方法,就是想本來就是在寫
EXCEL
操作相關嘛,干脆數據源也用
EXCEL
,該方法就是把
EXCEL
作為
OLEDB
數據源這樣來操作的,你是不是想到前面我所提到的四種導出
EXCEL
中的《方法
2
通過
OLEDB
把
EXCEL
做為數據源來寫》呢,對了,有興趣你可以嘗試修改下通過
OLEDB
這樣來導出
EXCEL
,
當然,新手朋友可以看下如何加載
EXCEL
數據,你應該希望去嘗試接著如何把這些數據儲存到數據庫之類的操作
3.
System.Windows.Forms.Application.DoEvents()
,
當運行
Windows
窗體時,它將創建新窗體,然后該窗體等待處理事件。該窗體在每次處理事件時,均將處理與該事件關聯的所有代碼。所有其他事件在隊列中等待。在代碼處理事件時,應用程序并不響應。例如,當將另一窗口拖到該窗口前面時,該窗口不重新繪制。如果在代碼中調用
DoEvents
,則您的應用程序可以處理其他事件。例如,如果您有向
ListBox
添加數據的窗體,并將
DoEvents
添加到代碼中,那么當將另一窗口拖到您的窗體上時,該窗體將重新繪制。如果從代碼中移除
DoEvents
,那么在按鈕的單擊事件處理程序執行結束以前,您的窗體不會重新繪制。
這里說遠一點,關于如何防止
UI
假死其實還有更科學的方法,就是使用委托加線程異步執行,把耗時的操作另起進程執行,從而減輕
UI
的壓力,使得前臺
UI
流暢運行而不假死,多用
this.Invoke
等,但在我程序用我也測試過反而直接
DoEvents
效果還好的多,而且線程和委托可能對新手朋友稍微復雜了些,推薦一般應用用
DoEvents
足夠了哦。
好了,東西不多廢話一大篇,手都寫累了,基本上用到的方法都做了詳細的解釋了,呵呵,希望以后大家多多交流,本人菜鳥一個,寫本文就是因為自己也得到過很多熱心網友的指導和幫助,也希望分享一些自己的東西作為回報,人人為我,我為人人,學會做個懂得感恩的人比什么都重要,歡迎大家和我一起學習套談
C#
0.png
(40.63 KB, 下載次數: 96)
下載附件
2017-6-5 16:51 上傳
全部資料下載地址:
C#導出數據到EXCEL方法談(附實例源碼和超級無敵詳細講解).rar
(560.85 KB, 下載次數: 74)
2017-6-5 16:22 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
admin
時間:
2017-6-5 17:03
好資料,51黑有你更精彩!!!
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1