使用OFFICE COM对象操作EXCEL需要运行环境拥有OFFICE的COM组件安装,本组件不需EXCEL安装,完成EXCEL文件转换为DataSet 的操作。
其中要点技术细节为使用JET引擎,并添加额外属性“EXCEL 8.0”
连接字符串样例:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=数据.xls;Extended Properties=excel 8.0;Persist Security Info=False
部分代码摘要自CODE PROJECT。
-----------控件代码--------------------------
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
using System.Data;
using System.Data.OleDb;
//using System.Drawing;
namespace excellib
{
public delegate void 导出SheetHandler(string SheetName);
public interface IExcelR
{
System.Data.DataSet ExportDataSet();
int SheetCount
{
get;
}
event 导出SheetHandler on导出Sheet;
string ExcelPath
{
get;
set;
}
bool Headers
{
get;
set;
}
bool MixedData
{
get;
set;
}
string SheetName
{
get;
set;
}
string SheetRange
{
get;
set;
}
}
//[ToolboxBitmap(@"指定工具箱图标")]
public class ExcelR: System.ComponentModel.Component,IExcelR
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
///
private System.ComponentModel.Container components = null;
public ExcelR(System.ComponentModel.IContainer container)
{
/// <summary>
/// Windows.Forms 类撰写设计器支持所必需的
/// </summary>
container.Add(this);
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
public ExcelR()
{
/// <summary>
/// Windows.Forms 类撰写设计器支持所必需的
/// </summary>
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
#region Component Designer generated code
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
#region "excel"
private class ExcelReader : IDisposable
{
#region Variables
private int[] _PKCol;
private string _strExcelFilename;
private bool _blnMixedData=true;
private bool _blnHeaders=false;
private string _strSheetName;
private string _strSheetRange;
private bool _blnKeepConnectionOpen=false;
private OleDbConnection _oleConn;
private OleDbCommand _oleCmdSelect;
private OleDbCommand _oleCmdUpdate;
#endregion
#region properties
public int[] PKCols
{
get {return _PKCol;}
set {_PKCol=value;}
}
public string ColName(int intCol)
{
string sColName="";
if (intCol<26)
sColName= Convert.ToString(Convert.ToChar((Convert.ToByte((char) 'A')+intCol)) );
else
{
int intFirst = ((int) intCol / 26);
int intSecond = ((int) intCol % 26);
sColName= Convert.ToString(Convert.ToByte((char) 'A')+intFirst);
sColName += Convert.ToString(Convert.ToByte((char) 'A')+intSecond);
}
return sColName;
}
public int ColNumber(string strCol)
{
strCol = strCol.ToUpper();
int intColNumber=0;
if (strCol.Length>1)
{
intColNumber = Convert.ToInt16(Convert.ToByte(strCol[1])-65);
intColNumber += Convert.ToInt16(Convert.ToByte(strCol[1])-64)*26;
}
else
intColNumber = Convert.ToInt16(Convert.ToByte(strCol[0])-65);
return intColNumber;
}
public String[] GetExcelSheetNames()
{
System.Data.DataTable dt = null;
try
{
if (_oleConn ==null) Open();
// Get the data table containing the schema
dt = _oleConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if(dt == null)
{
return null;
}
String[] excelSheets = new String[dt.Rows.Count];
int i = 0;
// Add the sheet name to the string array.
foreach(DataRow row in dt.Rows)
{
string strSheetTableName = row["TABLE_NAME"].ToString();
excelSheets[i] = strSheetTableName.Substring(0,strSheetTableName.Length-1);
i++;
}
return excelSheets;
}
catch(Exception)
{
return null;
}
finally
{
// Clean up.
if(this.KeepConnectionOpen==false)
{
this.Close();
}
if(dt != null)
{
dt.Dispose();
dt=null;
}
}
}
public string ExcelFilename
{
get { return _strExcelFilename;}
set { _strExcelFilename=value;}
}
public string SheetName
{
get { return _strSheetName;}
set { _strSheetName=value;}
}
public string SheetRange
{
get {return _strSheetRange;}
set
{
if(value==""){
}
else
{
if (value.IndexOf(":")==-1) throw new Exception("Invalid range length");
}
_strSheetRange=value;
}
}
public bool KeepConnectionOpen
{
get { return _blnKeepConnectionOpen;}
set {_blnKeepConnectionOpen=value;}
}
public bool Headers
{
get { return _blnHeaders;}
set { _blnHeaders=value;}
}
public bool MixedData
{
get {return _blnMixedData;}
set {_blnMixedData=value;}
}
#endregion
#region Methods
#region Excel Connection
private string ExcelConnectionOptions()
{
string strOpts="";
if (this.MixedData ==true)
strOpts += "Imex=2;";
if (this.Headers==true)
strOpts += "HDR=Yes;";
else
strOpts += "HDR=No;";
return strOpts;
}
private string ExcelConnection()
{
return
@"Provider=Microsoft.Jet.OLEDB.4.0;" +
@"Data Source=" + _strExcelFilename + ";" +
@"Extended Properties=" + Convert.ToChar(34).ToString() +
@"Excel 8.0;"+ ExcelConnectionOptions() + Convert.ToChar(34).ToString();
}
#endregion
#region Open / Close
public void Open()
{
try
{
if (_oleConn !=null)
{
if (_oleConn.State==ConnectionState.Open)
{
_oleConn.Close();
}
_oleConn=null;
}
if (System.IO.File.Exists(_strExcelFilename)==false)
{
throw new Exception("Excel file " + _strExcelFilename + "could not be found.");
}
_oleConn = new OleDbConnection(ExcelConnection());
_oleConn.Open();
}
catch (Exception ex)
{
throw ex;
}
}
public void Close()
{
if (_oleConn !=null)
{
if (_oleConn.State != ConnectionState.Closed)
_oleConn.Close();
_oleConn.Dispose();
_oleConn=null;
}
}
#endregion
#region Command Select
private bool SetSheetQuerySelect()
{
try
{
if (_oleConn == null)
{
throw new Exception("Connection is unassigned or closed.");
}
if (_strSheetName.Length ==0)
throw new Exception("Sheetname was not assigned.");
_oleCmdSelect =new OleDbCommand(
@"SELECT * FROM ["
+ _strSheetName
+ "$" + _strSheetRange
+ "]", _oleConn);
return true;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region simple utilities
private string AddWithComma(string strSource,string strAdd)
{
if (strSource !="") strSource = strSource += ", ";
return strSource + strAdd;
}
private string AddWithAnd(string strSource,string strAdd)
{
if (strSource !="") strSource = strSource += " and ";
return strSource + strAdd;
}
#endregion
private OleDbDataAdapter SetSheetQueryAdapter(DataTable dt)
{
// Deleting in Excel workbook is not possible
//So this command is not defined
try
{
if (_oleConn == null)
{
throw new Exception("Connection is unassigned or closed.");
}
if (_strSheetName.Length ==0)
throw new Exception("Sheetname was not assigned.");
if (PKCols == null)
throw new Exception("Cannot update excel sheet with no primarykey set.");
if (PKCols.Length<1)
throw new Exception("Cannot update excel sheet with no primarykey set.");
OleDbDataAdapter oleda = new OleDbDataAdapter(_oleCmdSelect);
string strUpdate="";
string strInsertPar="";
string strInsert="";
string strWhere="";
for (int iPK=0;iPK<PKCols.Length;iPK++)
{
strWhere = AddWithAnd(strWhere,dt.Columns[iPK].ColumnName + "=?");
}
strWhere =" Where "+strWhere;
for (int iCol=0;iCol<dt.Columns.Count;iCol++)
{
strInsert= AddWithComma(strInsert,dt.Columns[iCol].ColumnName);
strInsertPar= AddWithComma(strInsertPar,"?");
strUpdate= AddWithComma(strUpdate,dt.Columns[iCol].ColumnName)+"=?";
}
string strTable = "["+ this.SheetName + "$" + this.SheetRange + "]";
strInsert = "INSERT INTO "+ strTable + "(" + strInsert +") Values (" + strInsertPar + ")";
strUpdate = "Update " + strTable + " Set " + strUpdate + strWhere;
oleda.InsertCommand = new OleDbCommand(strInsert,_oleConn);
oleda.UpdateCommand = new OleDbCommand(strUpdate,_oleConn);
OleDbParameter oleParIns = null;
OleDbParameter oleParUpd = null;
for (int iCol=0;iCol<dt.Columns.Count;iCol++)
{
oleParIns = new OleDbParameter("?",dt.Columns[iCol].DataType.ToString());
oleParUpd = new OleDbParameter("?",dt.Columns[iCol].DataType.ToString());
oleParIns.SourceColumn =dt.Columns[iCol].ColumnName;
oleParUpd.SourceColumn =dt.Columns[iCol].ColumnName;
oleda.InsertCommand.Parameters.Add(oleParIns);
oleda.UpdateCommand.Parameters.Add(oleParUpd);
oleParIns=null;
oleParUpd=null;
}
for (int iPK=0;iPK<PKCols.Length;iPK++)
{
oleParUpd = new OleDbParameter("?",dt.Columns[iPK].DataType.ToString());
oleParUpd.SourceColumn =dt.Columns[iPK].ColumnName;
oleParUpd.SourceVersion = DataRowVersion.Original;
oleda.UpdateCommand.Parameters.Add(oleParUpd);
}
return oleda;
}
catch (Exception ex)
{
throw ex;
}
}
#region command Singe Value Update
private bool SetSheetQuerySingelValUpdate(string strVal)
{
try
{
if (_oleConn == null)
{
throw new Exception("Connection is unassigned or closed.");
}
if (_strSheetName.Length ==0)
throw new Exception("Sheetname was not assigned.");
_oleCmdUpdate =new OleDbCommand(
@" Update ["
+ _strSheetName
+ "$" + _strSheetRange
+ "] set F1=" + strVal, _oleConn);
return true;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
public void SetPrimaryKey(int intCol)
{
_PKCol = new int[1] { intCol };
}
public DataTable GetTable()
{
return GetTable("ExcelTable");
}
private void SetPrimaryKey(DataTable dt)
{
try
{
if (PKCols!=null)
{
//set the primary key
if (PKCols.Length>0)
{
DataColumn[] dc;
dc = new DataColumn[PKCols.Length];
for (int i=0;i<PKCols.Length;i++)
{
dc[i] =dt.Columns[PKCols[i]];
}
dt.PrimaryKey = dc;
}
}
}
catch (Exception ex)
{
throw ex;
}
}
public DataTable GetTable(string strTableName)
{
try
{
//Open and query
if (_oleConn ==null) Open();
if (_oleConn.State != ConnectionState.Open)
throw new Exception("Connection cannot open error.");
if (SetSheetQuerySelect()==false) return null;
//Fill table
OleDbDataAdapter oleAdapter = new OleDbDataAdapter();
oleAdapter.SelectCommand = _oleCmdSelect;
DataTable dt = new DataTable(strTableName);
oleAdapter.FillSchema(dt,SchemaType.Source);
oleAdapter.Fill(dt);
if (this.Headers ==false)
{
if (_strSheetRange.IndexOf(":")>0)
{
string FirstCol = _strSheetRange.Substring(0,_strSheetRange.IndexOf(":")-1);
int intCol = this.ColNumber(FirstCol);
for (int intI=0;intI<dt.Columns.Count;intI++)
{
dt.Columns[intI].Caption =ColName(intCol+intI);
}
}
}
SetPrimaryKey(dt);
//Cannot delete rows in Excel workbook
dt.DefaultView.AllowDelete =false;
//Clean up
_oleCmdSelect.Dispose();
_oleCmdSelect=null;
oleAdapter.Dispose();
oleAdapter=null;
if (KeepConnectionOpen==false) Close();
return dt;
}
catch (Exception ex)
{
throw ex;
}
}
private void CheckPKExists(DataTable dt)
{
if (dt.PrimaryKey.Length==0)
if (this.PKCols !=null)
{
SetPrimaryKey(dt);
}
else
throw new Exception("Provide an primary key to the datatable");
}
public DataTable SetTable(DataTable dt)
{
try
{
DataTable dtChanges = dt.GetChanges();
if (dtChanges == null) throw new Exception("There are no changes to be saved!");
CheckPKExists(dt);
//Open and query
if (_oleConn ==null) Open();
if (_oleConn.State != ConnectionState.Open)
throw new Exception("Connection cannot open error.");
if (SetSheetQuerySelect()==false) return null;
//Fill table
OleDbDataAdapter oleAdapter = SetSheetQueryAdapter(dtChanges);
oleAdapter.Update(dtChanges);
//Clean up
_oleCmdSelect.Dispose();
_oleCmdSelect=null;
oleAdapter.Dispose();
oleAdapter=null;
if (KeepConnectionOpen==false) Close();
return dt;
}
catch (Exception ex)
{
throw ex;
}
}
#region Get/Set Single Value
public void SetSingleCellRange(string strCell)
{
_strSheetRange = strCell + ":" + strCell;
}
public object GetValue(string strCell)
{
SetSingleCellRange(strCell);
object objValue=null;
//Open and query
if (_oleConn ==null) Open();
if (_oleConn.State != ConnectionState.Open)
throw new Exception("Connection is not open error.");
if (SetSheetQuerySelect()==false) return null;
objValue = _oleCmdSelect.ExecuteScalar();
_oleCmdSelect.Dispose();
_oleCmdSelect=null;
if (KeepConnectionOpen==false) Close();
return objValue;
}
public void SetValue(string strCell,object objValue)
{
try
{
SetSingleCellRange(strCell);
//Open and query
if (_oleConn ==null) Open();
if (_oleConn.State != ConnectionState.Open)
throw new Exception("Connection is not open error.");
if (SetSheetQuerySingelValUpdate(objValue.ToString())==false) return;
objValue = _oleCmdUpdate.ExecuteNonQuery();
_oleCmdUpdate.Dispose();
_oleCmdUpdate=null;
if (KeepConnectionOpen==false) Close();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (_oleCmdUpdate != null)
{
_oleCmdUpdate.Dispose();
_oleCmdUpdate=null;
}
}
}
#endregion
#endregion
public
#region Dispose / Destructor
void Dispose()
{
if (_oleConn !=null)
{
_oleConn.Dispose();
_oleConn=null;
}
if (_oleCmdSelect!=null)
{
_oleCmdSelect.Dispose();
_oleCmdSelect=null;
}
// Dispose of remaining objects.
}
#endregion
#region CTOR
public ExcelReader()
{
//
// TODO: Add constructor logic here
//
}
#endregion
}
#endregion
private ExcelReader _exr=null;
#region 属性
private string _strExcelFilename="";
[
Category("ExcelR"),
Description("Excel文件的路径")
]
public string ExcelPath
{
get
{
return _strExcelFilename;
}
set
{
this._strExcelFilename=value;
}
}
private bool _boolHeaders=true;
[
Category("ExcelR"),
Description("Excel表是否包含表头")
]
public bool Headers
{
get
{
return _boolHeaders;
}
set
{
_boolHeaders=value;
}
}
private bool _boolMixedData=true;
[
Category("ExcelR"),
Description("Excel表是否混合数据")
]
public bool MixedData
{
get
{
return _boolMixedData;
}
set
{
_boolMixedData=value;
}
}
private string _strSheetName="";
[
Category("ExcelR"),
Description("Excel工作表名")
]
public string SheetName
{
get
{
return _strSheetName;
}
set
{
_strSheetName=value;
}
}
private string _strSheetRange="";
[Category("ExcelR"),
Description("Excel工作表区域")
]
public string SheetRange
{
get
{
return _strSheetRange;
}
set
{
_strSheetRange=value;
}
}
[Category("ExcelR"),
Description("Excel工作表总数")
]
public int SheetCount
{
get
{
if (this._exr == null)
{
this._exr = new ExcelReader();
}
this._exr.KeepConnectionOpen=true;
this._exr.ExcelFilename = _strExcelFilename;
this._exr.Headers =this._boolHeaders;
this._exr.MixedData =this._boolMixedData;
_exr.Open();
int i=0;
i=_exr.GetExcelSheetNames().Length;
_exr.Close();
return i;
}
}
#endregion
#region 事件
导出SheetHandler _on导出Sheet;
[Category("ExcelR"),
Description("每导出一张Excel工作表时触发")
]
public event 导出SheetHandler on导出Sheet
{
add
{
_on导出Sheet=value;
}
remove
{
_on导出Sheet=null;
}
}
#endregion
public System.Data.DataSet ExportDataSet()
{
System.Data.DataSet ds=new System.Data.DataSet();
if (!System.IO.File.Exists(_strExcelFilename))
{
throw new System.Exception();
}
else
{
//todo:
if (this._exr == null)
{
this._exr = new ExcelReader();
}
this._exr.KeepConnectionOpen=true;
this._exr.ExcelFilename = _strExcelFilename;
this._exr.Headers =this._boolHeaders;
this._exr.MixedData =this._boolMixedData;
_exr.Open();
if(this._strSheetName.Trim()=="")
{
string[] sheetnames = this._exr.GetExcelSheetNames();
if(sheetnames.Length<1)
{
throw new System.Exception("EXCEL中没有工作表");
}
foreach(string str in sheetnames)
{
_exr.SheetName=str;
ds.Tables.Add(_exr.GetTable(str));
this._on导出Sheet(str);
}
}
else
{
_exr.SheetName=this._strSheetName;
if(_exr.SheetName.Trim()=="")
{
throw new System.Exception("首先需要指定工作表");
}
_exr.SheetRange=this.SheetRange;
ds.Tables.Add(_exr.GetTable(_exr.SheetName));
this._on导出Sheet(_exr.SheetName);
}
_exr.Close();
}
return ds;
}
}
}
----------------使用控件样例(winform)-------------------
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace WindowsApplication3
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.DataGrid dataGrid1;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
private excellib.ExcelR excelR1;
private System.Windows.Forms.ProgressBar progressBar1;
private System.ComponentModel.IContainer components;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.button1 = new System.Windows.Forms.Button();
this.dataGrid1 = new System.Windows.Forms.DataGrid();
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.excelR1 = new excellib.ExcelR(this.components);
this.progressBar1 = new System.Windows.Forms.ProgressBar();
((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).BeginInit();
this.SuspendLayout();
//
// button1
//
this.button1.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left);
this.button1.Location = new System.Drawing.Point(8, 328);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(80, 40);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// dataGrid1
//
this.dataGrid1.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right);
this.dataGrid1.DataMember = "";
this.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText;
this.dataGrid1.Location = new System.Drawing.Point(8, 8);
this.dataGrid1.Name = "dataGrid1";
this.dataGrid1.Size = new System.Drawing.Size(456, 312);
this.dataGrid1.TabIndex = 1;
//
// excelR1
//
this.excelR1.ExcelPath = null;
this.excelR1.Headers = true;
this.excelR1.MixedData = true;
this.excelR1.SheetName = "";
this.excelR1.SheetRange = "";
//
// progressBar1
//
this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right);
this.progressBar1.Location = new System.Drawing.Point(96, 328);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(368, 40);
this.progressBar1.TabIndex = 2;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(472, 381);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.progressBar1,
this.dataGrid1,
this.button1});
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).EndInit();
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
System.Data.DataSet ds=new System.Data.DataSet();
private void button1_Click(object sender, System.EventArgs e)
{
if(this.openFileDialog1.ShowDialog()==System.Windows.Forms.DialogResult.OK)
{
ds.Tables.Clear();
System.Threading.Thread t=new System.Threading.Thread(new System.Threading.ThreadStart(getD));
t.Start();
t.Join();
this.dataGrid1.DataSource=ds.Tables[0];
this.progressBar1.Value=0;
}
}
private void Form1_Load(object sender, System.EventArgs e)
{
this.excelR1.on导出Sheet+=new excellib.导出SheetHandler(on导出Sheet);
}
private void on导出Sheet(string tablename)
{
this.progressBar1.Value+=1;
}
private void getD()
{
this.excelR1.ExcelPath=this.openFileDialog1.FileName;
this.progressBar1.Minimum=0;
this.progressBar1.Maximum=this.excelR1.SheetCount;
this.button1.Enabled=false;
this.ds.Tables.Add(this.excelR1.ExportDataSet().Tables[0].Copy());
this.button1.Enabled=true;
}
}
}