private Excel.Application m_xlApp = new Excel.Application();
/// <summary>
/// 將DataTable數據導出到Excel表
/// </summary>
/// <param name="dtTmp">要導出的DataTable</param>
/// <param name="filePath">Excel的保存路徑及名稱</param>
public void DataTabletoExcel(System.Data.DataTable dtTmp, string filePath)
{
if (dtTmp == null)
{
return;
}
long rowNum = dtTmp.Rows.Count;//行數
int columnNum = dtTmp.Columns.Count;//列數
m_xlApp = new Excel.Application();
m_xlApp.DisplayAlerts = false;//不顯示更改提示
m_xlApp.Visible = false;
Excel.Workbooks workbooks = m_xlApp.Workbooks;
Excel.Workbook workbook = workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
Excel.Worksheet worksheet = (Excel.Worksheet)workbook.Worksheets[1];//取得Sheet1
try
{
//單張Excel表格最大行數
if (rowNum > 65536)
{
long pageRows = 65535; //定義每頁顯示的行數,行數必須小於65536
int scount = (int)(rowNum / pageRows); //導出數據生成的表單數
if (scount * pageRows < rowNum) //當總行數不被pageRows整除時,經過四舍五入可能頁數不准
{
scount = scount + 1;
}
for (int sc = 1; sc <= scount; sc++)
{
if (sc > 3) //這里由1改為3,20140922
{
object missing = System.Reflection.Missing.Value;
worksheet = (Excel.Worksheet)workbook.Worksheets.Add(
missing, missing, missing, missing); //添加一個sheet
}
else
{
worksheet = (Excel.Worksheet)workbook.Worksheets[sc]; //取得sheet1
}
string[,] datas = new string[pageRows + 1, columnNum];
for (int i = 0; i < columnNum; i++) //寫入字段
{
datas[0, i] = dtTmp.Columns[i].Caption; //表頭信息
}
Excel.Range range = worksheet.get_Range(worksheet.Cells[1, 1], worksheet.Cells[1, columnNum]);
range.Interior.ColorIndex = 15; //15代表灰色
range.Font.Bold = true;
range.Font.Size = 9;
int init = int.Parse(((sc - 1) * pageRows).ToString());
int r = 0;
int index = 0;
int result;
if (pageRows * sc >= rowNum)
{
result = (int)rowNum;
}
else
{
result = int.Parse((pageRows * sc).ToString());
}
for (r = init; r < result; r++)
{
index = index + 1;
for (int i = 0; i < columnNum; i++)
{
object obj = dtTmp.Rows[r][dtTmp.Columns[i].ToString()];
datas[index, i] = obj == null ? "" : obj.ToString().Trim();
}
}
Excel.Range fchR = worksheet.get_Range(worksheet.Cells[1, 1], worksheet.Cells[index + 1, columnNum]);
fchR.Value2 = datas;
worksheet.Columns.EntireColumn.AutoFit(); //列寬自適應。
m_xlApp.WindowState = Excel.XlWindowState.xlMaximized; //Sheet表最大化
range = worksheet.get_Range(worksheet.Cells[1, 1], worksheet.Cells[index + 1, columnNum]);
range.Font.Size = 9;
range.RowHeight = 14.25;
range.Borders.LineStyle = 1;
range.HorizontalAlignment = 1;
}
}
else
{
string[,] datas = new string[rowNum + 1, columnNum];
for (int i = 0; i < columnNum; i++) //寫入字段
{
datas[0, i] = dtTmp.Columns[i].Caption;
}
Excel.Range range = worksheet.get_Range(worksheet.Cells[1, 1], worksheet.Cells[1, columnNum]);
range.Interior.ColorIndex = 15; //15代表灰色
range.Font.Bold = true;
range.Font.Size = 9;
int r = 0;
for (r = 0; r < rowNum; r++)
{
for (int i = 0; i < columnNum; i++)
{
object obj = dtTmp.Rows[r][dtTmp.Columns[i].ToString()];
datas[r + 1, i] = obj == null ? "" : obj.ToString().Trim();
}
}
Excel.Range fchR = worksheet.get_Range(worksheet.Cells[1, 1], worksheet.Cells[rowNum + 1, columnNum]);
fchR.Value2 = datas;
worksheet.Columns.EntireColumn.AutoFit();//列寬自適應。
m_xlApp.WindowState = Excel.XlWindowState.xlMaximized;
range = worksheet.get_Range(worksheet.Cells[1, 1], worksheet.Cells[rowNum + 1, columnNum]);
range.Font.Size = 9;
range.RowHeight = 14.25;
range.Borders.LineStyle = 1;
range.HorizontalAlignment = 1;
}
workbook.Saved = true;
workbook.SaveCopyAs(filePath);
lblMsg.Text = "導出成功!" + DateTime.Now.ToString();
}
catch (Exception ex)
{
string dd = Server.MapPath("~/Tmp/1.txt");
System.IO.File.AppendAllText(dd, "導出異常:" + ex.Message + Environment.NewLine);
}
finally
{
EndReport();
}
}
/// <summary>
/// 退出報表時關閉Excel和清理垃圾Excel進程
/// </summary>
private void EndReport()
{
object missing = System.Reflection.Missing.Value;
try
{
m_xlApp.Workbooks.Close();
m_xlApp.Workbooks.Application.Quit();
m_xlApp.Application.Quit();
m_xlApp.Quit();
}
catch
{
}
finally
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(m_xlApp.Workbooks);
System.Runtime.InteropServices.Marshal.ReleaseComObject(m_xlApp.Application);
System.Runtime.InteropServices.Marshal.ReleaseComObject(m_xlApp);
m_xlApp = null;
}
catch
{
}
try
{
//清理垃圾進程
this.killProcessThread();
}
catch
{
}
GC.Collect();
}
}
/// <summary>
/// 殺掉不死進程
/// </summary>
private void killProcessThread()
{
ArrayList myProcess = new ArrayList();
for (int i = 0; i < myProcess.Count; i++)
{
try
{
System.Diagnostics.Process.GetProcessById(int.Parse((string)myProcess[i])).Kill();
}
catch
{
}
}
}
工作過程中經常會用到將數據導出到Excel中,一般情況下需要導出的數據都是幾百幾千條或者上萬條,這都沒有什么問題,但有時候會遇到特殊的需求,客戶要求把幾十萬條甚至上百萬條的數據導出到Excel中,這就比較麻煩了。當數據量很大導出到Excel表格的時候通常會遇到兩個問題:一個是內存溢出,由於需要處理的數據量比較大,導致Excel占用的內存過多從而導致數據還沒有導出完就因為內存溢出而失敗;另一個是每張Excel表單最多只能有65536行,所以當DataTable或DataSet中數據多於65536行時會報錯,這時候需要考慮Excel分頁功能。
程序由原始的將數據一個表格一個表格地寫入到EXCEL中,改變成程序先將數據存入二維數組中,然后再將數組值賦予EXCEL應用程序對象的VALUE屬性,這樣就使導出的效率提高很多,經測試導出100萬數據沒問題。
