VBA: объект закрыт ошибка в sql запросе при использовании таблицы соединений - PullRequest
1 голос
/ 15 апреля 2020

Я получаю сообщение об ошибке для строки ws.Cells(2, 2).CopyFromRecordset adoDbRs:

операция не разрешена при закрытии объекта

Если я удаляю JOIN в временная таблица #reporttable, она работает нормально, я чувствую, что набор записей пуст, потому что я отправляю его во временную таблицу, а затем пытаюсь JOIN и вытащить из этого, но я не уверен, как взять Вывод окончательного запроса на выборку выполняется корректно, он отлично работает при переформатировании и вводе непосредственно на сервер SQL.

Вторичный вопрос:

Поскольку я боролся с этим, но всегда могу заставить его работать на сервере, есть ли способ настроить пользовательский вызов на SQL сервер, который похож на command(var1,var2,var3), который выполняет сохраненный блок рабочего кода на сервере SQL и возвращает то, что он возвращает, вместо мой текущий процесс, который заставляет его работать на SQL сервере, а затем пытается приспособить его к VBA?

Private Sub Run_Summary_Click()

Dim adoDbConn As New ADODB.Connection
Dim adoDbRs As New ADODB.Recordset
Dim selectCmd As New ADODB.Command

Dim Machvar As Integer
Machvar = Worksheets("SumImport").Range("A1").Value
Dim DateYMD As String
Dim DateStart As Date
Dim DateEnd As Date
Dim SQL As String
DateYMD = Format(Worksheets("SumImport").Range("A2").Value, "YYYY-MM-DD")

' Open connection to the SQL Server database
 adoDbConn.Open "Provider=SQLOLEDB;   Data Source=********;  Initial Catalog=SMP;    User Id=Query;"

' Execute the select query
selectCmd.ActiveConnection = adoDbConn
   selectCmd.CommandText = "IF OBJECT_ID('tempdb.#reporttable2') IS NOT NULL DROP TABLE #reporttable2 " & _
    " SELECT " & _
    " DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5)*5, '20000101') as Date_Time " & _
    " ,max(Part_Count)-min(Part_Count) as PartsMade " & _
    " ,max(convert(char(5),  DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5)*5, '20000101'), 108)) as times " & _
    " ,max(Alarm_Light) as AlarmLight " & _
    " ,max(PV_Alarm) as AlarmCode " & _
    " INTO #reporttable2 " & _
    " FROM [33_TestImport]" & _
    " Where [DateTime]>= DateAdd(Hour, DateDiff(Hour, 0, '" & DateYMD & "')-0, 0) AND [DateTime]<= DateAdd(Hour, DateDiff(Hour, 0, '" & DateYMD & "')+24, 0) " & _
    " AND Machine_Number = " & Machvar & " " & _
    " Group BY DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5)*5, '20000101') " & _
    " select * " & _
    " from #reporttable2 p " & _
    " right join SMP.dbo.Timerange c " & _
    " ON c.mins = p.times " & _
    " order by mins "

Set adoDbRs = selectCmd.Execute(, , adCmdText)

' Clear the contents in cells where we're going to display the result
Dim cellRange As Range
Dim ws As Worksheet
Set ws = Worksheets("SumImport")
   ws.Activate
Set cellRange = Worksheets("SumImport").Range("B1:M1800")
   cellRange.ClearContents

' Activate the Worksheet
Set ws = Worksheets("SumImport")
   ws.Activate
' Put the query results starting from cell B2
ws.Cells(2, 2).CopyFromRecordset adoDbRs
' Set the column header
   ws.Cells(1, 2) = "DateTime"
   ws.Cells(1, 3) = "Part Total"
   ws.Cells(1, 4) = "TimeSync"
   ws.Cells(1, 5) = "Alarm Light"
   ws.Cells(1, 6) = "Alarm Code"
' Close the connection and free the memory
Set adoDbRs = Nothing
Set selectCmd = Nothing
   adoDbConn.Close
Set adoDbConn = Nothing
Set ws = Worksheets("Summary")
   ws.Activate

End Sub

И код, который работает в SQL напрямую

drop table #reporttable2
declare @dateget as date
set @Dateget = '2020-03-19'

SELECT
    DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5)*5, '20000101') as Date_Time
    ,max(Part_Count)-min(Part_Count) as PartsMade
    ,max(convert(char(5),  DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5)*5, '20000101'), 108)) as times

into #reporttable2

FROM 
    [SMP].[dbo].[33_TestImport]

where [DateTime]>= DateAdd(Hour, DateDiff(Hour, 0, @Dateget)-1, 0)
    and [DateTime]<= DateAdd(Hour, DateDiff(Hour, 0, @Dateget)+24, 0)


GROUP BY
    DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5)*5, '20000101')

    select * 
    from #reporttable2 p
    right join SMP.dbo.Timerange c 
    ON c.mins = p.times
    order by mins

1 Ответ

1 голос
/ 15 апреля 2020

В VBA соединения ADO не поддерживают многострочные SQL команды. Поэтому набор записей, возможно, создается на основе самой первой строки SQL или оператора DROP и может ничего не возвращать.

Однако, если присмотреться к вашей ситуации, рассмотрите Общее табличное выражение (CTE), избегайте необходимости во временной таблице и затем интегрируйте параметризованный запрос для вашей переменной даты. При этом ваши первоначальные 5 операторов преобразуются в один:

SQL

WITH reporttable2 AS (
   SELECT
       DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5) * 5, '20000101') AS Date_Time
       , MAX(Part_Count) - MIN(Part_Count) AS PartsMade
       , MAX(CONVERT(CHAR(5),  DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5)*5, '20000101'), 108)) AS times

   FROM 
      [SMP].[dbo].[33_TestImport]

   WHERE [DateTime] >= DATEADD(Hour, DATEDIFF(Hour, 0, @Dateget) - 1, 0)
     AND [DateTime] <= DATEADD(Hour, DATEDIFF(Hour, 0, @Dateget) + 24, 0)

   GROUP BY
       DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5) * 5, '20000101')
)

SELECT *
FROM reporttable2 p
RIGHT JOIN SMP.dbo.Timerange c 
   ON c.mins = p.times
ORDER BY mins

VBA

' ASSIGN DATE (NOT STRING) VARIABLE FOR PARAMETER
myDate = Worksheets("SumImport").Range("A2").Value

' PREPARED STATEMENT WITH QMARKS ?
sql = "WITH reporttable2 AS ( " _ 
      & " SELECT " _
      & "      DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5) * 5, '20000101') AS Date_Time " _
      & "      , MAX(Part_Count) - MIN(Part_Count) AS PartsMade " _
      & "      , MAX(CONVERT(CHAR(5),  DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5)*5, '20000101'), 108)) AS times " _
      & " FROM " _
      & "   [SMP].[dbo].[33_TestImport] " _
      & " WHERE [DateTime] >= DATEADD(Hour, DATEDIFF(Hour, 0, ?) - 1, 0) " _
      & "   AND [DateTime] <= DATEADD(Hour, DATEDIFF(Hour, 0, ?) + 24, 0) " _
      & " GROUP BY " _
      & "   DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 5) * 5, '20000101') " _
      & ")" _
      & " " _
      & " SELECT * " _
      & " FROM reporttable2 p " _
      & " RIGHT JOIN SMP.dbo.Timerange c " _
      & "    ON c.mins = p.times " _
      & " ORDER BY mins"

With selectCmd
    .ActiveConnection = adoDbConn
    .CommandText = sql
    .CommandType = adCmdText

    ' BIND TWO PARAM VALUES
    .Parameters.Append .CreateParameter("param1", adDate, adParamInput, , myDate)
    .Parameters.Append .CreateParameter("param2", adDate, adParamInput, , myDate)

    ' ASSIGN RECORDSET TO RESULT
    Set adoDbRs = .Execute
End With
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...