Excel存储过程调用中的行重复

时间:2018-07-02 12:28:20

标签: excel vba excel-vba

我有一个存储过程调用,该过程通过Excel复制行,我认为这与我用于从记录集中复制的方法有关。手动运行查询时的数据会输出正确的数据。

Private Sub Refresh_Click()
    Dim Conn As ADODB.Connection, RecordSet As ADODB.RecordSet

    Dim Command As ADODB.Command
    Dim ConnectionString As String, StoredProcName As String
    Dim StartDate As ADODB.Parameter, EndDate As ADODB.Parameter

    Application.ScreenUpdating = False

    Set Conn = New ADODB.Connection
    Set RecordSet = New ADODB.RecordSet
    Set Command = New ADODB.Command

    ' I blanked out the details here as they are not required as this is working
    ConnectionString = "PROVIDER=SQLOLEDB;DATA SOURCE=xxxx;INITIAL CATALOG=xxxx; User Id=xxxx;Password=xxxx;"

    On Error GoTo CloseConnection

    Conn.Open ConnectionString
    SellStartDate = Format(Sheets("Sheet1").Range("B2").Value2, "yyyy-mm-dd")
    SellEndDate = Format(Sheets("Sheet1").Range("B3").Value2, "yyyy-mm-dd")
    StoredProcName = "fsp_PLReportByDates"

    With Command
        .ActiveConnection = Conn
        .CommandType = adCmdStoredProc
        .CommandText = StoredProcName
    End With

    Set StartDate = Command.CreateParameter("@DateFrom", adDBDate, adParamInput, , SellStartDate)
    Set EndDate = Command.CreateParameter("@DateTo", adDBDate, adParamInput, , SellEndDate)

    Command.Parameters.Append StartDate
    Command.Parameters.Append EndDate    
    Set RecordSet = Command.Execute    

    Sheets("Sheet1").Range("A7").CopyFromRecordset RecordSet
    For intColIndex = 0 To RecordSet.Fields.Count - 1
       Range("A6").Offset(0, intColIndex).Value = RecordSet.Fields(intColIndex).Name
    Next


    RecordSet.Close
    Conn.Close
    On Error GoTo 0
    Application.ScreenUpdating = True
    Exit Sub

    CloseConnection:
     Application.ScreenUpdating = True
     MsgBox "SQL Stored Procedure Did Not Execute Sucessfully!", vbCritical, "SQL Error"
     Conn.Close

End Sub

1 个答案:

答案 0 :(得分:2)

假设您的旧记录集/上一记录拉取值大于新记录集,并且当您将新记录集/旧记录放在旧记录集上时,某些旧记录仍存在于工作表中...

创建一个随数据动态增长的命名范围。假设您的Proc中有10列要返回并且有任意行,请创建一个名为rng_PLReportByDates的命名范围并将其设置为:

=OFFSET(Sheet1!$A$7, 0, 0, COUNTA(Sheet1!$A$7:$A$5000)+1, 10)

这将创建一个具有10列,最多4993行的命名范围。我认为这对于您的记录集来说已经足够了,否则会将5000扩大到有意义的范围。 +1只是为了确保如果范围完全为空(无值),则此公式将至少返回1行,否则将出错。

然后...就在您运行之前:

Sheets("Sheet1").Range("A7").CopyFromRecordset RecordSet

添加此内容:

Range("rng_PLReportByDates").ClearContents

您还可以更改CopyFromRecordset来使用新的动态大小的命名范围:

Range("rng_PLReportByDates").CopyFromRecordset Recordset

每次将记录集转储到工作表时,我都会使用此方法。我使用相同的公式创建了一个动态大小的命名范围,然后对其进行.ClearContents.CopyFromRecordset的创建。

如果列数发生变化,则只需将Counta()公式添加到命名范围公式中的最后一个参数即可:

=OFFSET(Sheet1!$A$7, 0, 0, COUNTA(Sheet1!$A$7:$A$5000)+1, COUNTA(Sheet1!$A$7:$IV$7)+1)

就标题而言,您可能需要调整命名范围,使其位于行6之后。然后,您可以执行以下操作:

 Range("rng_PLReportByDates").ClearContents
 Range("rng_PLReportByDates").Offset(1).CopyFromRecordset Recordset

然后您的范围也一样。