【VBA研究】如何将Excel工作表的内容更新到数据库
iamlaosong文
利用Excel维护数据库,自然就需要完成工作表内容和数据库表内容的互动。将数据库表的内容读到工作表中,这儿就不说了,本文主要是要说一下如何将工作表中修改后的内容更新到数据库表中。
比较快速的方法是采用记录集更新方法,这种方法比较快,也很方便。经测试,对access数据库是没有问题的,微软的SQL Server没测过,不过是一家产品,估计没问题,代码如下:
Sub SaveData_rst()'On Error GoTo ErrMsg:Dim cnn As ADODB.ConnectionDim rst As ADODB.RecordsetDim sqls, mytable As StringDim i, j, n As Integer'建立连接,当前文件的路径可以用ThisWorkbook.PathSet cnn = New ADODB.Connectioncnn.Open 'Provider =Microsoft.ACE.OLEDB.12.0; Data Source = ' & ThisWorkbook.Path & '\支付宝.accdb'mytable = '账号明细'n = Range('a1').End(xlDown).Row '当前工作表有效行数'使用SQL语句操作数据库For i = 2 To nsqls = 'select * from ' & mytable & ' where khzh='' & Cells(i, 1).Value & '''Set rst = New ADODB.Recordset'用记录集对象执行SQL语句rst.Open sqls, cnn, adOpenKeyset, adLockOptimisticIf rst.RecordCount = 0 Then rst.AddNew '找不到,增加一条空记录For j = 1 To rst.Fields.Countrst.Fields(j - 1) = Cells(i, j).ValueNext jrst.UpdateNext irst.Close ' 关闭记录集Set rst = Nothing ' 释放对象cnn.Close ' 关闭连接Set cnn = Nothing ' 释放对象MsgBox '操作成功!'End Sub
现在的问题是我用的不是access而是Oracle,上面的方法不能使用,连接Oracle数据库后,参数adOpenKeyset, adLockOptimistic是空值,用此参数会报错,即使用实值1、3(那两个参数的实际值)替换不报错,可以更新记录集依然不行,提示VBA不支持记录集动态更新。
既然此路不通,只好采取原始的办法,用SQL语句直接完成,实际应用的代码如下:
'将工作表数据保存到数据库Sub SaveData(opName As String)Dim row1, k, KeyNum, FieldNo, MaxRow, UpdateNo, InsertNo As IntegerDim stName, tbName, KeyField, AllFields As StringDim MyRecord(50)On Error GoTo ErrMsg:If opName = 'ZHMX' ThenstName = '账号明细'tbName = 'EMSAPP_ZFB_ZHMX'KeyNum = 1 '关键字列号KeyField = 'khzh'AllFields = '(khzh,dwmc,bmmc,khmc,mark)'FieldNo = 5ElseExit SubEnd IfOraOpen = OracleOpen() '成功执行后,数据库即被打开If OraOpen ThenUpdateNo = 0InsertNo = 0With Sheets(stName)MaxRow = .[A65536].End(xlUp).Row'开始保存For row1 = 2 To MaxRowFor k = 1 To FieldNoMyRecord(k) = .Cells(row1, k)Next ksqls = 'select count(*) from ' & tbName & ' where ' & KeyField & ' = '' & MyRecord(KeyNum) & '''Set rst = cnn.Execute(sqls)Recno = rst(0)If Recno > 0 Thensqls = 'update ' & tbName & ' set ' & AllFields & ' = (select ''For k = 1 To FieldNo - 1sqls = sqls & MyRecord(k) & '',''Next ksqls = sqls & MyRecord(k) & '' from dual) where ' & KeyField & ' = '' & MyRecord(KeyNum) & '''UpdateNo = UpdateNo + 1.Cells(row1, FieldNo + 1) = '更新OK'Else'插入数据sqls = 'insert into ' & tbName & AllFields & ' values (''For k = 1 To FieldNo - 1sqls = sqls & MyRecord(k) & '',''Next ksqls = sqls & MyRecord(k) & '') 'InsertNo = InsertNo + 1.Cells(row1, FieldNo + 1) = '新增OK'End IfSet rst = cnn.Execute(sqls)Next row1End WithEnd If'保存日志msgMsg = '成功保存至数据库,其中更新:' & UpdateNo & ',新增:' & InsertNoProg_Log (opName) '日志OracleClose '关闭连接Msg = MsgBox(Msg, vbOKOnly, 'iamlaosong')Exit SubErrMsg:MsgBox sqls, vbCritical, '操作失败 ,请检查!'End Sub
增加一个参数opName的目的是让这个过程可以保存多个表。生成更新的SQL语句采用的格式是“update set (字段1,字段2...) =(select '值1’,'值2'... from dual) where 条件”这种格式,主要是方便写代码。所有的值都用单引号括起来是没有问题的,即使是数值也不影响,不过日期型是不行的,需要另外处理。
Oracle连接开关函数和过程代码如下:
'连接数据库Function OracleOpen() As BooleanOn Error GoTo ErrMsg:Set cnn = CreateObject('ADODB.Connection')Set rst = CreateObject('ADODB.Recordset')cnnstr = 'Provider=msdaora;Data Source=dl580;User Id=emssxjk;Password=emssxjk;'cnn.Open cnnstrOracleOpen = True '成功执行后,数据库即被打开Exit FunctionErrMsg:OracleOpen = FalseEnd Function'关闭连接Public Sub OracleClose()If rst.State = adStateOpen Then rst.CloseSet rst = NothingIf cnn.State = adStateOpen Then cnn.CloseSet cnn = NothingEnd Sub
最后,把读取数据到工作表中的过程列一下:
Public Sub GetData(opName As String)'根据工作表中的查询语句读取数据On Error GoTo ErrMsg:Dim stName, sqls As StringDim MaxRow As IntegerDim OraOpen As BooleanIf opName = 'ZHMX' ThenstName = '账号明细'sqls = 'select khzh,dwmc,bmmc,khmc,mark from EMSAPP_ZFB_ZHMX'sqls = sqls & ' order by dwmc,bmmc,khzh'ElseIf opName = 'JYMX' ThenstName = '交易明细'sqls = 'select a.jyrq,a.ywlsh,a.khzh,a.srje,a.mark,b.dwmc,b.bmmc,b.khmc from EMSAPP_ZFB_JYMX a, EMSAPP_ZFB_ZHMX b'sqls = sqls & ' where a.jyrq between to_date('' & Sheets(stName).Range('M3') & '','yyyy-mm-dd') and to_date(''sqls = sqls & Sheets(stName).Range('N3') & '','yyyy-mm-dd') and a.khzh=b.khzh(+) order by dwmc,bmmc,khzh'ElseExit SubEnd IfOraOpen = OracleOpen() '成功执行后,数据库即被打开If OraOpen ThenSet rst = cnn.Execute(sqls)sqls = 'CopyFromRecordset'MaxRow = Sheets(stName).UsedRange.Rows.CountIf MaxRow > 1 Then Sheets(stName).Range('A2:L' & MaxRow).ClearContentsSheets(stName).Range('A2').CopyFromRecordset rstOracleCloseExit SubEnd IfErrMsg:MsgBox Err.Description, vbCritical, '操作失败 ,请检查!'MsgBox sqls, vbCritical, '错误语句'End Sub
赞 (0)
