Excel VBA - 存储过程(SQL 服务器)
Excel VBA - Stored Procedure (SQL Server)
我在检索多个记录集(带有列名)并将数据粘贴到 Excel sheet 中时遇到一个小问题,如下图
我的 VBA 代码只检索了第一个记录集而不是其余的
非常感谢任何帮助,谢谢
Sub CProcedure()
Dim Conn As ADODB.Connection, RecordSet As ADODB.RecordSet
Dim Command As ADODB.Command
Dim ConnectionString As String, StoredProcName As String
Dim range1 As ADODB.Parameter, range2 As ADODB.Parameter
Dim SP_Param1 As String
Dim SP_Param2 As String
Application.ScreenUpdating = False
Set Conn = New ADODB.Connection
Set RecordSet = New ADODB.RecordSet
Set Command = New ADODB.Command
ServerName = "1111"
DatabaseName = "dataReporting"
UserId = "88888"
Password = "88888"
SP_Param1 = "StartDate"
SP_Param2 = "EndDate"
StoredProcName = "KPI_Report"
ConnectionString = "PROVIDER=SQLOLEDB;DATA SOURCE=" & ServerName & _
";INITIAL CATALOG=" & DatabaseName & "; User Id=" & _
UserId & "; Password=" & Password & ";"
Conn.Open ConnectionString
With Command
.ActiveConnection = Conn
.CommandType = adCmdStoredProc
.CommandText = StoredProcName
.CommandTimeout = 0
End With
Set range1 = Command.CreateParameter(SP_Param1, adDBDate, adParamInput, , DateSerial(2018, 1, 1))
Command.Parameters.Append range1
Set range2 = Command.CreateParameter(SP_Param2, adDBDate, adParamInput, , DateSerial(2018, 4, 1))
Command.Parameters.Append range2
Set RecordSet = Command.Execute
Sheets("Sheet1").Range("A2").CopyFromRecordset RecordSet
RecordSet.Close
Conn.Close
On Error GoTo 0
Application.ScreenUpdating = True
Exit Sub
End Sub
更新
我添加了下面的循环但还是不行
'Loop through recordset and place values
RecordSet.MoveFirst
Do While RecordSet.EOF = False
For i = 0 To RecordSet.Fields.Count - 1
ActiveCell.Value = RecordSet.Fields(i).Value
ActiveCell.Offset(0, 1).Activate
Next i
ActiveCell.Offset(1, -i).Activate
RecordSet.MoveNext
Loop
这是存储过程代码:
Sub storedproc()
Dim Conn As ADODB.Connection
Dim ADODBCmd As ADODB.Command
Dim rs As ADODB.RecordSet
Dim i As Integer
Dim sConnect As String
ServerName = "1111"
DatabaseName = "dataReporting"
UserId = "88888"
Password = "88888"
SP_Param1 = "StartDate"
SP_Param2 = "EndDate"
StoredProcName = "KPI_Report"
sConnect = "PROVIDER=SQLOLEDB;DATA SOURCE=" & ServerName &
";INITIAL CATALOG=" & DatabaseName & "; User Id=" & UserId &
"; Password=" & Password & ";"
'Establish connection
Set Conn = New ADODB.Connection
Conn.ConnectionString = sConnect
Conn.Open
'Open recordset
Set ADODBCmd = New ADODB.Command
ADODBCmd.ActiveConnection = Conn
ADODBCmd.CommandText = StoredProcName
ADODBCmd.CommandType = adCmdStoredProc
ADODBCmd.CommandTimeout = 0
Set range1 = ADODBCmd.CreateParameter(SP_Param1, adDBDate, adParamInput, , DateSerial(2018, 1, 1))
ADODBCmd.Parameters.Append range1
Set range2 = ADODBCmd.CreateParameter(SP_Param2, adDBDate, adParamInput, , DateSerial(2018, 4, 1))
ADODBCmd.Parameters.Append range2
Set rs = ADODBCmd.Execute()
'Loop through recordset and place values
rs.MoveFirst
Do While rs.EOF = False
For i = 0 To rs.Fields.Count - 1
ActiveCell.Value = rs.Fields(i).Value
ActiveCell.Offset(0, 1).Activate
Next i
ActiveCell.Offset(1, -i).Activate
rs.MoveNext
Loop
'Clean up
rs.Close
Set rs = Nothing
End Sub
所以存储过程需要return多个记录集例如
CREATE PROCEDURE GetCarsAndCategories
AS
BEGIN
SELECT * FROM Cars
SELECT * FROM Categories
END
然后 VBA 代码最初可以访问 Cars 记录集并访问 Categories 记录集调用 GetNextRecordSet
S Meaden 的回答提到 GetNextRecordSet
解决了存储过程导致多个记录集的问题。
以下代码将所有记录集(包括字段名称)转储到 sheet(如果您重复 运行,请不要忘记先清理 sheet)。
...
Set rs = Command.Execute
Dim startcol As Long
startcol = 1
With ThisWorkbook.Sheets(1)
Do While Not rs Is Nothing
Dim col As Long
For col = 0 To rs.Fields.Count - 1
.Cells(1, startcol + col) = rs.Fields(col).Name
Next col
.Cells(2, startcol).CopyFromRecordset rs
startcol = startcol + rs.Fields.Count + 1
Set rs = rs.NextRecordset
Loop
End With
我在检索多个记录集(带有列名)并将数据粘贴到 Excel sheet 中时遇到一个小问题,如下图
我的 VBA 代码只检索了第一个记录集而不是其余的
非常感谢任何帮助,谢谢
Sub CProcedure()
Dim Conn As ADODB.Connection, RecordSet As ADODB.RecordSet
Dim Command As ADODB.Command
Dim ConnectionString As String, StoredProcName As String
Dim range1 As ADODB.Parameter, range2 As ADODB.Parameter
Dim SP_Param1 As String
Dim SP_Param2 As String
Application.ScreenUpdating = False
Set Conn = New ADODB.Connection
Set RecordSet = New ADODB.RecordSet
Set Command = New ADODB.Command
ServerName = "1111"
DatabaseName = "dataReporting"
UserId = "88888"
Password = "88888"
SP_Param1 = "StartDate"
SP_Param2 = "EndDate"
StoredProcName = "KPI_Report"
ConnectionString = "PROVIDER=SQLOLEDB;DATA SOURCE=" & ServerName & _
";INITIAL CATALOG=" & DatabaseName & "; User Id=" & _
UserId & "; Password=" & Password & ";"
Conn.Open ConnectionString
With Command
.ActiveConnection = Conn
.CommandType = adCmdStoredProc
.CommandText = StoredProcName
.CommandTimeout = 0
End With
Set range1 = Command.CreateParameter(SP_Param1, adDBDate, adParamInput, , DateSerial(2018, 1, 1))
Command.Parameters.Append range1
Set range2 = Command.CreateParameter(SP_Param2, adDBDate, adParamInput, , DateSerial(2018, 4, 1))
Command.Parameters.Append range2
Set RecordSet = Command.Execute
Sheets("Sheet1").Range("A2").CopyFromRecordset RecordSet
RecordSet.Close
Conn.Close
On Error GoTo 0
Application.ScreenUpdating = True
Exit Sub
End Sub
更新
我添加了下面的循环但还是不行
'Loop through recordset and place values
RecordSet.MoveFirst
Do While RecordSet.EOF = False
For i = 0 To RecordSet.Fields.Count - 1
ActiveCell.Value = RecordSet.Fields(i).Value
ActiveCell.Offset(0, 1).Activate
Next i
ActiveCell.Offset(1, -i).Activate
RecordSet.MoveNext
Loop
这是存储过程代码:
Sub storedproc()
Dim Conn As ADODB.Connection
Dim ADODBCmd As ADODB.Command
Dim rs As ADODB.RecordSet
Dim i As Integer
Dim sConnect As String
ServerName = "1111"
DatabaseName = "dataReporting"
UserId = "88888"
Password = "88888"
SP_Param1 = "StartDate"
SP_Param2 = "EndDate"
StoredProcName = "KPI_Report"
sConnect = "PROVIDER=SQLOLEDB;DATA SOURCE=" & ServerName &
";INITIAL CATALOG=" & DatabaseName & "; User Id=" & UserId &
"; Password=" & Password & ";"
'Establish connection
Set Conn = New ADODB.Connection
Conn.ConnectionString = sConnect
Conn.Open
'Open recordset
Set ADODBCmd = New ADODB.Command
ADODBCmd.ActiveConnection = Conn
ADODBCmd.CommandText = StoredProcName
ADODBCmd.CommandType = adCmdStoredProc
ADODBCmd.CommandTimeout = 0
Set range1 = ADODBCmd.CreateParameter(SP_Param1, adDBDate, adParamInput, , DateSerial(2018, 1, 1))
ADODBCmd.Parameters.Append range1
Set range2 = ADODBCmd.CreateParameter(SP_Param2, adDBDate, adParamInput, , DateSerial(2018, 4, 1))
ADODBCmd.Parameters.Append range2
Set rs = ADODBCmd.Execute()
'Loop through recordset and place values
rs.MoveFirst
Do While rs.EOF = False
For i = 0 To rs.Fields.Count - 1
ActiveCell.Value = rs.Fields(i).Value
ActiveCell.Offset(0, 1).Activate
Next i
ActiveCell.Offset(1, -i).Activate
rs.MoveNext
Loop
'Clean up
rs.Close
Set rs = Nothing
End Sub
所以存储过程需要return多个记录集例如
CREATE PROCEDURE GetCarsAndCategories
AS
BEGIN
SELECT * FROM Cars
SELECT * FROM Categories
END
然后 VBA 代码最初可以访问 Cars 记录集并访问 Categories 记录集调用 GetNextRecordSet
S Meaden 的回答提到 GetNextRecordSet
解决了存储过程导致多个记录集的问题。
以下代码将所有记录集(包括字段名称)转储到 sheet(如果您重复 运行,请不要忘记先清理 sheet)。
...
Set rs = Command.Execute
Dim startcol As Long
startcol = 1
With ThisWorkbook.Sheets(1)
Do While Not rs Is Nothing
Dim col As Long
For col = 0 To rs.Fields.Count - 1
.Cells(1, startcol + col) = rs.Fields(col).Name
Next col
.Cells(2, startcol).CopyFromRecordset rs
startcol = startcol + rs.Fields.Count + 1
Set rs = rs.NextRecordset
Loop
End With