VBA 将 DAO 连接字符串和 Recordset 转换为 ODBC
VBA convert DAO connection string and Recordset to ODBC
我有一个用 VBA 在 Word 中编写的加载项,它相当旧。我认为它可以追溯到 1997 年。目前 VBA 代码将连接到 Access 2003 数据库并查询 table 和 return 数据记录集并从中生成供应商列表table查询。
下面是使用DAO方法的代码。现在的问题是我们收到的具有 windows 10 的较新计算机没有 DAO 方法可以使用的旧库。 (加上 DAO 本身又旧又过时)。
Public strData() As String
Sub GetData(strTable As String)
Dim dbf As DAO.Database
Dim rst As DAO.Recordset
Dim Counter As Long
Dim strCriteria As String
If strTable = "VendorQ" Then
strCriteria = "SELECT NameSort FROM Vendor Where Qualified = -1 ORDER BY NameSort"
ElseIf strTable = "VendorU" Then
strCriteria = "SELECT NameSort FROM Vendor Where Qualified = 0 ORDER BY NameSort"
ElseIf strTable = "MainR" Then
strCriteria = "SELECT NameSort FROM Vendor ORDER BY NameSort"
Else
MsgBox "Error"
End If
Set dbf = OpenDatabase("\fileLocation\center.mdb")
Set rst = dbf.OpenRecordset(strCriteria)
frmCenter.MousePointer = fmMousePointerHourGlass
Counter = 0
If rst.RecordCount > 0 Then
rst.MoveLast
ReDim strData(rst.RecordCount - 1) As String
rst.MoveFirst
Do Until rst.EOF
strData(Counter) = rst![NameSort]
Counter = Counter + 1
rst.MoveNext
Loop
Else
ReDim strData(0)
End If
frmCenter.MousePointer = fmMousePointerArrow
rst.Close
End Sub
这将 return 一个列表:
table 已经存在于 MySQL 数据库中,因此我可以使用 ODBC 连接来检索数据,而不是将 Access 作为链接 table 的传递。我尝试转换连接字符串并连接到数据库,但由于某种原因没有显示供应商列表。
转换后的代码如下:
Public strData() As String
Sub GetData(strTable As String)
Dim rst As ADODB.Recordset
Dim Counter As Long
Dim strCriteria As String
Dim conn As ADODB.Connection
Set remoteCon = New ADODB.Connection
conStr = "DRIVER={MySQL ODBC 5.2 ANSI Driver};" & _
"SERVER=server;DATABASE=database;" & _
"UID=uid;PWD=pwd"
remoteCon.ConnectionString = conStr
remoteCon.Open
remoteCon.Execute ("USE database;")
Set rst = New ADODB.Recordset
If strTable = "VendorQ" Then
strCriteria = "SELECT NameSort FROM Vendor Where Qualified = -1 ORDER BY NameSort"
ElseIf strTable = "VendorU" Then
strCriteria = "SELECT NameSort FROM Vendor Where Qualified = 0 ORDER BY NameSort"
ElseIf strTable = "MainR" Then
strCriteria = "SELECT NameSort FROM Main ORDER BY NameSort"
Else
MsgBox "Error"
End If
With rst
.ActiveConnection = remoteCon
.CursorType = adOpenDynamic
.LockType = adLockOptimistic
.Source = strCriteria
.Open
End With
frmCenter.MousePointer = fmMousePointerHourGlass
Counter = 0
If rst.RecordCount > 0 Then
rst.MoveLast
ReDim strData(rst.RecordCount - 1) As String
rst.MoveFirst
Do Until rst.EOF
strData(Counter) = rst![NameSort]
Counter = Counter + 1
rst.MoveNext
Loop
Else
ReDim strData(0)
End If
frmCenter.MousePointer = fmMousePointerArrow
rst.Close
End Sub
是否有不同的方法从 ODBC 源填充记录集?
RecordCount
通常是不可靠的,直到你 运行 记录集结束(例如在 MoveLast 中)所以我会使用 EOF 检查:
If Not rst.EOF Then
rst.MoveLast
ReDim strData(rst.RecordCount - 1) As String
rst.MoveFirst
Do Until rst.EOF
strData(Counter) = rst![NameSort]
Counter = Counter + 1
rst.MoveNext
Loop
Else
ReDim strData(0)
End If
编辑:
仅供参考,在我的测试中,RecordCount 使用 adOpenDynamic
始终为 -1,但我使用 adOpenKeyset
获得了正确的值
如果 RecordCount
不可靠,那么您可以使用 GetRows()
将记录传输到二维数组,然后使用它来调整大小并填充 strData
If Not rs.EOF Then
arrRecs = rs.GetRows 'a 2D array (0 to #cols-1, 0 to #rows-1)
ReDim strData(UBound(arrRecs, 2))
For i = 0 To UBound(arrRecs, 2)
strData(i) = arrRecs(0, i)
Next i
Else
ReDim strData(0)
End If
请参阅 Erik A 的回答
将 .CursorLocation = adUseClient 添加到第一个打开的字符串解决了这个问题。
我有一个用 VBA 在 Word 中编写的加载项,它相当旧。我认为它可以追溯到 1997 年。目前 VBA 代码将连接到 Access 2003 数据库并查询 table 和 return 数据记录集并从中生成供应商列表table查询。
下面是使用DAO方法的代码。现在的问题是我们收到的具有 windows 10 的较新计算机没有 DAO 方法可以使用的旧库。 (加上 DAO 本身又旧又过时)。
Public strData() As String
Sub GetData(strTable As String)
Dim dbf As DAO.Database
Dim rst As DAO.Recordset
Dim Counter As Long
Dim strCriteria As String
If strTable = "VendorQ" Then
strCriteria = "SELECT NameSort FROM Vendor Where Qualified = -1 ORDER BY NameSort"
ElseIf strTable = "VendorU" Then
strCriteria = "SELECT NameSort FROM Vendor Where Qualified = 0 ORDER BY NameSort"
ElseIf strTable = "MainR" Then
strCriteria = "SELECT NameSort FROM Vendor ORDER BY NameSort"
Else
MsgBox "Error"
End If
Set dbf = OpenDatabase("\fileLocation\center.mdb")
Set rst = dbf.OpenRecordset(strCriteria)
frmCenter.MousePointer = fmMousePointerHourGlass
Counter = 0
If rst.RecordCount > 0 Then
rst.MoveLast
ReDim strData(rst.RecordCount - 1) As String
rst.MoveFirst
Do Until rst.EOF
strData(Counter) = rst![NameSort]
Counter = Counter + 1
rst.MoveNext
Loop
Else
ReDim strData(0)
End If
frmCenter.MousePointer = fmMousePointerArrow
rst.Close
End Sub
这将 return 一个列表:
table 已经存在于 MySQL 数据库中,因此我可以使用 ODBC 连接来检索数据,而不是将 Access 作为链接 table 的传递。我尝试转换连接字符串并连接到数据库,但由于某种原因没有显示供应商列表。
转换后的代码如下:
Public strData() As String
Sub GetData(strTable As String)
Dim rst As ADODB.Recordset
Dim Counter As Long
Dim strCriteria As String
Dim conn As ADODB.Connection
Set remoteCon = New ADODB.Connection
conStr = "DRIVER={MySQL ODBC 5.2 ANSI Driver};" & _
"SERVER=server;DATABASE=database;" & _
"UID=uid;PWD=pwd"
remoteCon.ConnectionString = conStr
remoteCon.Open
remoteCon.Execute ("USE database;")
Set rst = New ADODB.Recordset
If strTable = "VendorQ" Then
strCriteria = "SELECT NameSort FROM Vendor Where Qualified = -1 ORDER BY NameSort"
ElseIf strTable = "VendorU" Then
strCriteria = "SELECT NameSort FROM Vendor Where Qualified = 0 ORDER BY NameSort"
ElseIf strTable = "MainR" Then
strCriteria = "SELECT NameSort FROM Main ORDER BY NameSort"
Else
MsgBox "Error"
End If
With rst
.ActiveConnection = remoteCon
.CursorType = adOpenDynamic
.LockType = adLockOptimistic
.Source = strCriteria
.Open
End With
frmCenter.MousePointer = fmMousePointerHourGlass
Counter = 0
If rst.RecordCount > 0 Then
rst.MoveLast
ReDim strData(rst.RecordCount - 1) As String
rst.MoveFirst
Do Until rst.EOF
strData(Counter) = rst![NameSort]
Counter = Counter + 1
rst.MoveNext
Loop
Else
ReDim strData(0)
End If
frmCenter.MousePointer = fmMousePointerArrow
rst.Close
End Sub
是否有不同的方法从 ODBC 源填充记录集?
RecordCount
通常是不可靠的,直到你 运行 记录集结束(例如在 MoveLast 中)所以我会使用 EOF 检查:
If Not rst.EOF Then
rst.MoveLast
ReDim strData(rst.RecordCount - 1) As String
rst.MoveFirst
Do Until rst.EOF
strData(Counter) = rst![NameSort]
Counter = Counter + 1
rst.MoveNext
Loop
Else
ReDim strData(0)
End If
编辑:
仅供参考,在我的测试中,RecordCount 使用 adOpenDynamic
始终为 -1,但我使用 adOpenKeyset
如果 RecordCount
不可靠,那么您可以使用 GetRows()
将记录传输到二维数组,然后使用它来调整大小并填充 strData
If Not rs.EOF Then
arrRecs = rs.GetRows 'a 2D array (0 to #cols-1, 0 to #rows-1)
ReDim strData(UBound(arrRecs, 2))
For i = 0 To UBound(arrRecs, 2)
strData(i) = arrRecs(0, i)
Next i
Else
ReDim strData(0)
End If
请参阅 Erik A 的回答