从Excel转Access的一个方法说开去(DataRow的state状态)
因为客户对access不太熟悉,更喜欢玩EXCEL。但是系统要求导入ACCESS。所以我们得做个把EXCEL转换成Access的小工具。(别问我为啥不让系统直接导入excel....我不知道!),然后耗费了点时间写了个公用的方法,如下:
/// <summary> /// /// </summary> /// <param name="excelpath">excel路径</param> /// <param name="exceltablename">Excel表名</param> /// <param name="accessmodelpath">access模版路径</param> /// <param name="accesspath">access输出路径</param> /// <param name="accesstablename">access表名</param> /// <param name="msg">错误信息</param> /// <returns></returns> public static bool ExcelToAccess(string excelpath, string exceltablename, string accessmodelpath, string accesspath, string accesstablename, ref string msg) { try { DataTable dt = ExcelToDataTable(excelpath, exceltablename); if (dt == null) { msg = "Excel没有任何内容"; return false; } accesspath = accesspath + "\\生成的access.mdb"; System.IO.File.Copy(accessmodelpath, accesspath, true); string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + accesspath + ";User Id=admin;Password=;"; string sql = "Select * from " + accesstablename + ""; System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection(connStr); System.Data.OleDb.OleDbDataAdapter da = new System.Data.OleDb.OleDbDataAdapter(sql, conn); System.Data.DataTable acedt = new DataTable(); da.Fill(acedt); System.Data.OleDb.OleDbCommandBuilder ocb = new System.Data.OleDb.OleDbCommandBuilder(da); da.InsertCommand = ocb.GetInsertCommand(); DataRow[] drs = dt.Select(); foreach (DataRow r in drs) { acedt.ImportRow(r); } // acedt.AcceptChanges();//此处不能有 da.Update(acedt); da.Dispose(); conn.Close(); conn.Dispose(); return true; } catch (Exception ex) { msg = ex.Message; return false; } }
这里用了模版,用IO的创建代替用sql创建access,应该是个比较好点的办法,当然,前提是你得实现有个模版。
然后是 ExcelToDataTable方法的代码:
/// <summary> /// Excel转换成datatable /// </summary> /// <param name="excelpath"></param> /// <param name="exceltablename"></param> /// <returns></returns> public static DataTable ExcelToDataTable(string excelpath, string exceltablename) { try { // string strCon =string.Format( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=‘Excel 8.0;IMEX=1‘",excelpath); OleDbConnection Conn = new OleDbConnection(strCon); string strCom = "SELECT distinct * FROM [" + exceltablename + "$] where 1=1 "; OleDbDataAdapter da = new OleDbDataAdapter(strCom, Conn); DataTable dt = new DataTable(); da.AcceptChangesDuringFill = false; da.Fill(dt); return dt; } catch(Exception ex) { return null; } }
关键点是 da.AcceptChangesDuringFill = false;这句。最初的时候,我并没有写这一局。
一开始我没主意到这个,跑这个方法的时候,运行起来没有任何问题,但是,打开生成的access,是空数据!
查阅资料外加问人,发现了此时dt的datarow的rowstate为unchanged;
知道问题所在了,就去百度,添加该句后状态改变为added;
然后终于可以添加到access了。
现在看起来不是很难,但是,为了找到这个原因,耗费了一天的时间。
下面是我查找参考资料的时候从MSDN看到的关于DataRow.RowState的一些代码:
static void Main(string[] args) { // Run a function to create a DataTable with one column. DataTable table = MakeTable(); DataRow row; // Create a new DataRow. row = table.NewRow(); // Detached row. Console.WriteLine("New Row " + row.RowState); table.Rows.Add(row); // New row. Console.WriteLine("AddRow " + row.RowState); table.AcceptChanges(); // Unchanged row. Console.WriteLine("AcceptChanges " + row.RowState); row["FirstName"] = "Scott"; // Modified row. Console.WriteLine("Modified " + row.RowState); row.Delete(); // Deleted row. Console.WriteLine("Deleted " + row.RowState); Console.ReadKey(); } private static DataTable MakeTable() { // Make a simple table with one column. DataTable table = new DataTable("table"); DataColumn dcFirstName = new DataColumn( "FirstName", Type.GetType("System.String")); table.Columns.Add(dcFirstName); return table; }
才知道原来不同的操作,datarow的状态是不同的。
下面来说说他的状态:
DataRowState枚舉有如下几种状态:
add 该行已添加到 DataRowCollection 中,AcceptChanges 尚未调用
Deleted 该行已通过 DataRow 的 Delete 方法被删除。
Detached 该行已被创建,但不属于任何 DataRowCollection。DataRow 在以下情况下立即处于此状态:创建之后添加到集合中之前;或从集合中移除之后。
Modified 该行已被修改,AcceptChanges 尚未调用。
Unchanged 该行自上次调用 AcceptChanges 以来尚未更改。
要正確理解上面這集中狀態應該對AcceptChanges有很好的理解:
提交自上次调用 AcceptChanges 以来对该行进行的所有更改。(意思就是对以上做的更改的确认)
在调用 AcceptChanges 时,EndEdit 方法被隐式调用,以便终止任何编辑。如果行的 RowState 是“Added”或“Modified”,则 RowState 变成“Unchanged”。如果 RowState 是“Deleted”,则该行将被移除。
如何获取已删除行的信息:获取行的DataRowVersion.Original版本就可以了.
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。