C#導出Excel方法有多種﹐常用的按照Microsoft 的方法如下:
1﹑"Use Automation to Transfer Data Cell by Cell "
2﹑"Use Automation to Transfer an Array of Data to a Range on a Worksheet "
3﹑"Use Automation to Transfer an ADO Recordset to a Worksheet Range "
4﹑"Use Automation to Create a QueryTable on a Worksheet"
5﹑"Use the Clipboard"
6﹑"Create a Delimited Text File that Excel Can Parse into Rows and Columns"
7﹑"Transfer Data to a Worksheet Using ADO.NET "
在此本人主要使用第4種方法:即利用Excel的QueryTable導出海量數據。
要利用Excel的QueryTable的方法﹐首先需要引用Excel類庫。這個我就不多說了。
第二步就是新增一個窗體文件﹐為簡單起見﹐只在窗體上加一個button按鈕。在Button Click事件中加入操作的代碼。整個操作﹐我只在一個類中實現﹐源碼附貼如下(office2003)﹕
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication3
{
public partial class Form1 : Form
{
private Microsoft.Office.Interop.Excel.Application m_objExcel = null ;
private Microsoft.Office.Interop.Excel.Workbooks m_objBooks = null ;
private Microsoft.Office.Interop.Excel._Workbook m_objBook = null ;
private Microsoft.Office.Interop.Excel.Sheets m_objSheets = null ;
private Microsoft.Office.Interop.Excel._Worksheet m_objSheet = null ;
private Microsoft.Office.Interop.Excel.Range m_objRange = null ;
// private Microsoft.Office.Interop.Excel.Font m_objFont = null;
// private Microsoft.Office.Interop.Excel.QueryTables m_objQryTables = null;
private Microsoft.Office.Interop.Excel._QueryTable m_objQryTable = null ;
// Frequenty-used variable for optional arguments.
private object m_objOpt = System.Reflection.Missing.Value;
// DataBase-used variable
private System.Data.SqlClient.SqlConnection sqlConn = null ;
private string strConnect = " Data Source='localhost';Password = ;User ID=sa;Initial Catalog=TEST " ;
private System.Data.SqlClient.SqlCommand sqlCmd = null ;
// Sheets variable
private double dbSheetSize = 65535 ; // the hight limit number in one sheet
private int intSheetTotalSize = 0 ; // total record can divied sheet number
private double dbTotalSize = 0 ; // record total number
public Form1()
{
InitializeComponent();
}
private int GetTotalSize()
{
sqlConn = new System.Data.SqlClient.SqlConnection(strConnect);
sqlCmd = new System.Data.SqlClient.SqlCommand( " Select Count(*) From PD_WORKBIL_MST " , sqlConn);
sqlConn.Open();
dbTotalSize = ( int )sqlCmd.ExecuteScalar();
sqlConn.Close();
return ( int )Math.Ceiling(dbTotalSize / this .dbSheetSize);
}
private void DeclareExcelApp()
{
m_objExcel = new Microsoft.Office.Interop.Excel.Application();
m_objBooks = (Microsoft.Office.Interop.Excel.Workbooks)m_objExcel.Workbooks;
m_objBook = (Microsoft.Office.Interop.Excel._Workbook)(m_objBooks.Add(m_objOpt));
m_objSheets = (Microsoft.Office.Interop.Excel.Sheets)m_objBook.Worksheets;
intSheetTotalSize = GetTotalSize();
if (intSheetTotalSize <= 3 )
{
if ( this .dbTotalSize <= this .dbSheetSize)
{
this .ExportDataByQueryTable( 1 , false );
return ;
}
else if ( this .dbTotalSize <= this .dbSheetSize * 2 )
{
this .ExportDataByQueryTable( 1 , false );
this .ExportDataByQueryTable( 2 , true );
return ;
}
else
{
this .ExportDataByQueryTable( 1 , false );
this .ExportDataByQueryTable( 2 , true );
this .ExportDataByQueryTable( 3 , true );
return ;
}
}
for ( int i = 3 ; i < intSheetTotalSize; i ++ )
{
m_objSheets.Add(m_objOpt, m_objSheets.get_Item(i), m_objOpt, m_objOpt);
}
ExportDataByQueryTable( 1 , false );
for ( int i = 2 ; i <= m_objSheets.Count; i ++ )
{
ExportDataByQueryTable(i, true );
}
}
private void SaveExcelApp()
{
string excelFileName = string .Empty;
SaveFileDialog sf = new SaveFileDialog();
sf.Filter = " *.xls|*.* " ;
if (sf.ShowDialog() == DialogResult.OK)
{
excelFileName = sf.FileName;
}
else
{
return ;
}
m_objBook.SaveAs(excelFileName, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt,
Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt);
}
private void ExportDataByQueryTable( int intSheetNumber, bool blIsMoreThan)
{
string strQuery = string .Empty;
if (blIsMoreThan)
{
strQuery = " Select Top " +
this .dbSheetSize + " * From PD_WORKBIL_MST Where Not CMPID In (Select Top " +
dbSheetSize * (intSheetNumber - 1 ) + " CMPID From PD_WORKBIL_MST) " ;
}
else
{
strQuery = " Select Top " + this .dbSheetSize + " * From PD_WORKBIL_MST " ;
}
m_objSheet = (Microsoft.Office.Interop.Excel._Worksheet)(m_objSheets.get_Item(intSheetNumber));
m_objSheet.get_Range( " A1 " , m_objOpt).set_Value(m_objOpt, " 中文測試一 " );
m_objSheet.get_Range( " B1 " , m_objOpt).set_Value(m_objOpt, " 中文測試二 " );
m_objSheet.get_Range( " C1 " , m_objOpt).set_Value(m_objOpt, " 中文測試三 " );
m_objSheet.get_Range( " D1 " , m_objOpt).set_Value(m_objOpt, " 中文測試四 " );
m_objSheet.get_Range( " E1 " , m_objOpt).set_Value(m_objOpt, " 中文測試五 " );
m_objRange = m_objSheet.get_Range( " A2 " , m_objOpt);
m_objQryTable = m_objSheet.QueryTables.Add( " OLEDB;Provider=SQLOLEDB.1; " + strConnect, m_objRange, strQuery);
m_objQryTable.RefreshStyle = Microsoft.Office.Interop.Excel.XlCellInsertionMode.xlInsertEntireRows;
m_objQryTable.FieldNames = false ;
m_objQryTable.Refresh( false );
}
private void button1_Click( object sender, EventArgs e)
{
DeclareExcelApp();
SaveExcelApp();
}
}
}
使用office2000的話﹐好像類庫有些不同﹐為給大家一個比較﹐也將源碼附貼如下﹕
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication2
{
public partial class Form1 : Form
{
Excel.Range m_objRange = null ;
Excel.Application m_objExcel = null ;
Excel.Workbooks m_objBooks = null ;
Excel._Workbook m_objBook = null ;
Excel.Sheets m_objSheets = null ;
Excel._Worksheet m_objSheet = null ;
Excel.QueryTable m_objQryTable = null ;
object m_objOpt = System.Reflection.Missing.Value;
// DataBase-used variable
private System.Data.SqlClient.SqlConnection sqlConn = null ;
private string strConnect = " Data Source='localhost';Password = ;User ID=sa;Initial Catalog=TEST " ;
private System.Data.SqlClient.SqlCommand sqlCmd = null ;
// Sheets variable
private double dbSheetSize = 65535 ; // the hight limit number in one sheet
private int intSheetTotalSize = 0 ; // total record can divied sheet number
private double dbTotalSize = 0 ; // record total number
public Form1()
{
InitializeComponent();
}
private int GetTotalSize()
{
sqlConn = new System.Data.SqlClient.SqlConnection(strConnect);
sqlCmd = new System.Data.SqlClient.SqlCommand( " Select Count(*) From PD_WORKBIL_MST " , sqlConn);
sqlConn.Open();
dbTotalSize = ( int )sqlCmd.ExecuteScalar();
sqlConn.Close();
return ( int )Math.Ceiling(dbTotalSize / this .dbSheetSize);
}
private void DeclareExcelApp()
{
m_objExcel = new Excel.ApplicationClass();
m_objBooks = (Excel.Workbooks)m_objExcel.Workbooks;
m_objBook = (Excel._Workbook)(m_objBooks.Add(m_objOpt));
m_objSheets = (Excel.Sheets)m_objBook.Worksheets;
intSheetTotalSize = GetTotalSize();
if (intSheetTotalSize <= 3 )
{
if ( this .dbTotalSize <= this .dbSheetSize)
{
this .ExportDataByQueryTable( 1 , false );
return ;
}
else if ( this .dbTotalSize <= this .dbSheetSize * 2 )
{
this .ExportDataByQueryTable( 1 , false );
this .ExportDataByQueryTable( 2 , true );
return ;
}
else
{
this .ExportDataByQueryTable( 1 , false );
this .ExportDataByQueryTable( 2 , true );
this .ExportDataByQueryTable( 3 , true );
return ;
}
}
for ( int i = 3 ; i < intSheetTotalSize; i ++ )
{
m_objSheets.Add(m_objOpt, m_objSheets.get_Item(i), m_objOpt, m_objOpt);
}
ExportDataByQueryTable( 1 , false );
for ( int i = 2 ; i <= m_objSheets.Count; i ++ )
{
ExportDataByQueryTable(i, true );
}
}
private void SaveExcelApp()
{
string excelFileName = string .Empty;
SaveFileDialog sf = new SaveFileDialog();
sf.Filter = " *.xls|*.* " ;
if (sf.ShowDialog() == DialogResult.OK)
{
excelFileName = sf.FileName;
}
else
{
return ;
}
m_objBook.SaveAs(excelFileName, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt,
Excel.XlSaveAsAccessMode.xlNoChange, m_objOpt, m_objOpt, m_objOpt, m_objOpt);
}
private void ExportDataByQueryTable( int intSheetNumber, bool blIsMoreThan)
{
string strQuery = string .Empty;
if (blIsMoreThan)
{
strQuery = " Select Top " +
this .dbSheetSize + " * From PD_WORKBIL_MST Where Not CMPID In (Select Top " +
dbSheetSize * (intSheetNumber - 1 ) + " CMPID From PD_WORKBIL_MST) " ;
}
else
{
strQuery = " Select Top " + this .dbSheetSize + " * From PD_WORKBIL_MST " ;
}
m_objSheet = (Excel._Worksheet)(m_objSheets.get_Item(intSheetNumber));
m_objSheet.Cells[ 1 , 1 ] = " 中文測試一 " ;
m_objSheet.Cells[ 1 , 2 ] = " 中文測試二 " ;
m_objSheet.Cells[ 1 , 3 ] = " 中文測試三 " ;
m_objSheet.Cells[ 1 , 4 ] = " 中文測試四 " ;
m_objSheet.Cells[ 1 , 5 ] = " 中文測試五 " ;
m_objRange = m_objSheet.get_Range( " A2 " , m_objOpt);
m_objQryTable = m_objSheet.QueryTables.Add( " OLEDB;Provider=SQLOLEDB.1; " + strConnect, m_objRange, strQuery);
m_objQryTable.RefreshStyle = Excel.XlCellInsertionMode.xlInsertEntireRows;
m_objQryTable.FieldNames = false ;
m_objQryTable.Refresh( false );
}
private void button1_Click( object sender, EventArgs e)
{
DeclareExcelApp();
SaveExcelApp();
}
}
}
在本篇中﹐是將13萬多條記錄分多個Sheet導出。如果你的機器大概像我這樣:P4CPU,1G內存的話。全部導出包括保存也就是20秒左右就可以全部搞定。
也許大家會有更好的方法來實現﹐歡迎各位交流﹗
其實﹐我這篇文章是在Windows程序中實現的。你說無法關掉Excel進程﹐這個我承認﹐我在代碼中沒有體現﹐在button1_Click方法的最后﹐應加入如下几句﹕
//Clean-up
m_objRange = null;
m_objSheet = null;
m_objSheets = null;
m_objBooks = null;
m_objBook = null;
m_objExcel = null;
GC.Collect();
原文出处:
http://www.cnblogs.com/jinliangliu/archive/2006/08/18/480391.html
相关链接:Excel扩展.NET应用
====================================================================

若要开发使用 Microsoft Office Excel 2003 的解决方案,您可以与 Excel 对象模型提供的对象进行交互。本主题介绍最重要的类:Microsoft.Office.Interop.Excel.Application、Microsoft.Office.Interop.Excel.Workbook、Microsoft.Office.Interop.Excel.Worksheet 和 Microsoft.Office.Interop.Excel.Range。很多时候,该对象模型都直接模拟用户界面。例如,Application 对象表示整个应用程序,每个 Workbook 对象都包含 Worksheet 对象的一个集合。由此看出,Range 是主要的用于单元格抽象表示的对象,该对象供您用来处理单个单元格或成组的单元格。
Microsoft Visual Studio 2005 Tools for the Microsoft Office System 扩展了其中的许多本机对象,以使它们具有包括数据绑定功能和事件在内的附加功能。这些扩展的对象称为宿主控件。例如,本机 Excel Microsoft.Office.Interop.Excel.Range 对象被扩展为 Microsoft.Office.Tools.Excel.NamedRange 控件,该控件可与数据绑定并公开事件。有关宿主控件的更多信息,请参见宿主项和宿主控件概述。
访问 Excel 项目中的对象
当您使用 Visual Studio Tools for Office 创建新的 Excel 项目时,可以选择创建新的 Excel 应用程序项目或 Excel 模板项目。无论是文档项目还是模板项目,Visual Studio Tools for Office 都在您的新 Excel 项目中自动创建下面的代码文件。
Visual Basic | C# |
---|---|
ThisWorkbook.vb | ThisWorkbook.cs |
Sheet1.vb | Sheet1.cs |
Sheet2.vb | Sheet2.cs |
Sheet3.vb | Sheet3.cs |
您可以使用全局类 Globals 从 ThisWorkbook、Sheet1、Sheet2 或 Sheet3 类的外部分别访问各个类。有关更多信息,请参见全局访问文档的对象。下面的示例调用 Sheet1 的 PrintPreview 方法,而不管代码是放在 Sheet 类中还是放在 Workbook 类中:
Globals.Sheet1.PrintPreview()
Globals.Sheet1.PrintPreview(missing);
由于 Excel 文档中的数据是高度结构化的,因此该对象模型也具有层次结构并且简单明了。Excel 提供了数百个您可能需要与之交互的对象,不过您可以从这些对象中的少数几个开始来掌握对象模型。这些对象包括:
-
Application 对象
-
Workbook 对象
-
Worksheet 对象
-
Range 对象
使用 Excel 完成的很多工作都是围绕这四个类和它们的成员进行的。
Application 对象
Excel Application 对象表示 Excel 应用程序本身。Application 对象公开了大量有关正在运行的应用程序、应用于该实例的选项以及在该实例中打开的当前用户的对象的信息。
![]() |
---|
您不应该将 Excel 中的 Application 对象的 EnableEvents 属性设置为 false。将此属性设置为 false 将阻止 Excel 引发任何事件,包括宿主控件的事件。 |
Workbook 对象
Microsoft.Office.Interop.Excel.Workbook 类表示 Excel 应用程序中的单个工作簿。Visual Studio Tools for Office 通过提供 Microsoft.Office.Tools.Excel.Workbook 类(使用该类可以访问 Workbooks 集合的所有成员)以及数据绑定功能和附加事件来扩展 Microsoft.Office.Interop.Excel.Workbook 类。
Worksheet 对象
Microsoft.Office.Interop.Excel.Worksheet 对象是 Worksheets 集合的成员。Microsoft.Office.Interop.Excel.Worksheet 的许多属性、方法和事件都与 Application 和/或 Microsoft.Office.Interop.Excel.Workbook 类提供的成员完全相同或相似。
Excel 提供 Sheets 集合作为 Microsoft.Office.Interop.Excel.Workbook 对象的属性,但是 Excel 中没有 Sheet 类。相反,Sheets 集合的每个成员都是一个 Microsoft.Office.Interop.Excel.Worksheet 对象,或者是一个 Microsoft.Office.Interop.Excel.Chart 对象。Visual Studio Tools for Office 提供 Microsoft.Office.Tools.Excel.Worksheet 宿主项,并在创建项目时创建三个实例:Sheet1、Sheet2 和 Sheet3。对其中任何工作表的访问都可以通过 Globals 引用进行。Visual Studio Tools for Office 通过提供 Microsoft.Office.Tools.Excel.Worksheet 宿主项来扩展 Microsoft.Office.Interop.Excel.Worksheet 对象。
Range 对象
Microsoft.Office.Interop.Excel.Range 对象是 Excel 应用程序中最常用的对象。在能够处理 Excel 内的任何范围之前,必须将它表示为 Range 对象,并处理该对象的方法和属性。Range 对象表示一个单元格、一行、一列、包含一个或多个单元格块(可以连续,也可以不连续)的单元格选定范围,甚至多个工作表中的一组单元格。
Visual Studio Tools for Office 引入了两个范围宿主控件:Microsoft.Office.Tools.Excel.NamedRange 控件和 Microsoft.Office.Tools.Excel.XMLMappedRange 控件。有关宿主控件的更多信息,请参见宿主项和宿主控件概述。
扩展的对象
了解 Excel 对象模型提供的本机对象和 Visual Studio Tools for Office 提供的扩展对象(宿主项和宿主控件)之间的区别是很重要的,原因是这两类对象对您的项目都是可用的。务必记住下面的几点:
-
设计时。当您在设计时添加任何扩展的 Excel 对象时,它们将自动创建为宿主项和宿主控件。例如,如果在设计器中向工作表添加一个列表,则会自动生成将该列表扩展为一个 Microsoft.Office.Tools.Excel.ListObject 控件的代码。
-
运行时。不会在运行时自动创建宿主项。如果在运行时添加工作簿、工作表或图表工作表,它们将是本机 Excel 对象,不具备宿主项所提供的附加功能。您能够以编程方式添加许多宿主控件。有关更多信息,请参见宿主项和宿主控件概述。
-
数据绑定和事件。宿主项和宿主控件具有数据绑定功能和事件,这两点是本机对象所不具备的。
-
类型。本机 Excel 对象使用 Microsoft.Office.Interop.Excel 中定义的类型,而宿主项和宿主控件使用 Microsoft.Office.Tools.Excel 中定义的聚合类型。
本主题已介绍了最重要的类:Application、Workbook、Worksheet 和 Range。还有许多其他类可能对您有用,例如 PivotTable 和 Chart。Visual Studio Tools for Office 通过将功能扩展到包括数据绑定和事件来扩展这其中的许多类。对象模型使您能够完成您需要的几乎任何自动化任务。