VBA - 如果工作表1已满,则返回工作表2中的结果

时间:2016-12-12 14:59:04

标签: sql vba excel-vba excel

我目前正在从Excel宏运行SQL存储过程。返回记录的计数超过一个工作表的最大行数。如何将溢出结果传输到第二张纸?

Sub Button1_Click()
Dim con As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim par As String
Dim WSP1 As Worksheet
Set con = New ADODB.Connection
Set cmd = New ADODB.Command
Set rs = New ADODB.Recordset

Application.DisplayStatusBar = True
Application.StatusBar = "Contacting SQL Server..."

' Remove any values in the cells where we
' want to put our Stored Procedure's results.
Dim rngRange As Range
Set rngRange = Range(Cells(8, 2), Cells(Rows.Count, 1)).EntireRow
rngRange.ClearContents


' Log into our SQL Server, and run the Stored Procedure
con.Open "Provider=SQLOLEDB;Data Source=67.09;Initial Catalog=TEST..."
 cmd.ActiveConnection = con

 Application.StatusBar = "Running stored procedure..."
cmd.CommandText = "SP_Billing"
Set rs = cmd.Execute(, , adCmdStoredProc)

' Copy the results to cell B7 on the first Worksheet
Set WSP1 = Worksheets(1)
WSP1.Activate
If rs.EOF = False Then WSP1.Cells(8, 2).CopyFromRecordset rs

rs.Close
Set rs = Nothing
Set cmd = Nothing

con.Close
Set con = Nothing

Application.StatusBar = "Data successfully updated."
End Sub

2 个答案:

答案 0 :(得分:1)

只需将MaxRows参数传递给.CopyFromRecordset并循环,直到您点击EOF。每次调用都会将光标前进到记录集中,并从当前光标位置开始复制。我将它提取到Sub之类的东西......

Private Sub SplitRecordsToSheets(records As ADODB.Recordset, perSheet As Long)
    Dim ws As Worksheet
    Do While Not records.EOF
        Set ws = Worksheets.Add
        ws.Cells(8, 2).CopyFromRecordset records, perSheet
    Loop
End Sub

...然后像这样调用它:

' Log into our SQL Server, and run the Stored Procedure
con.Open "Provider=SQLOLEDB;Data Source=67.09;Initial Catalog=TEST..."
cmd.ActiveConnection = con

Application.StatusBar = "Running stored procedure..."
cmd.CommandText = "SP_Billing"
Set rs = cmd.Execute(, , adCmdStoredProc)

SplitRecordsToSheets rs, ActiveSheet.Rows.Count - 8

答案 1 :(得分:0)

如果在解析RecordSet时需要一些自定义处理(例如在打印后切换页面,比如100k行),则无法再使用Range.CopyFromRecordset方法。相反,您可能必须自己遍历记录集。这是一个如何做这样的事情的小样本(当然没有给出整个谜题:

Dim i_RowCount As Long
Dim a_PrintArray As Variant, rg_PrintRg As Range
Dim i_Col As Integer
Const i_MaxRows As Long = 100000
' I recommend filling everything into an Array first and then Printing the array to Excel'

' Using your existing variables also '
ReDim a_PrintArray( 1 to i_MaxRows, 1 to rs.Fields.Count )
Set sh_Current = WSP1
Do Until rs.EOF
    i_RowCount = i_RowCount + 1

    If i_RowCount > i_MaxRows Then 'If we hit the max, print what we have'
        ' Setting up the print range to match the array size '
        Set rg_PrintRg = shCurrent.Cells(8, 2)
        Set rg_PrintRg = Range(rg_PrintRg, rg_PrintRg.Offset(i_MaxRows - 1, rs.Fields.Count - 1))
        rg_PrintRg = a_PrintArray  ' Print the array into the range '
        i_RowCount = 1
        Set sh_Current = sh_Current.Next
        ReDim a_PrintArray( 1 to i_MaxRows, 1 to rs.Fields.Count )
    End If

    For i_Col = 0 To rs.Fields.Count - 1        
        a_PrintArray(i_RowCount, i_Col) = rs.Fields(i_Col).Value
    Next i_Col

    rs.MoveNext
Loop

请注意,此代码snippit仅用于演示。它尚未编译,可能不适合您的特定应用。有关Recordset对象的更多信息:https://msdn.microsoft.com/en-us/library/ms681510%28v=vs.85%29.aspx