SQL VBA 中的查询输出与 SQL Oracle 中的不同

SQL Query output in VBA is different than in SQL Oracle

VBA 有问题。我已经编写了 sql 代码(300 行),它在 SQL 中运行完美,输出为:

 Line   Number     Date    Employee    PN       Tax
  1     1111   2015-10-15      AP     6225-6    L1
  2     1111   2015-10-15      AP     6225-6    L2
  3     1111   2015-10-15    (null)   CHARGE    (null)
  4     1111   2015-10-15      AP     55555     L2

我已将这么大的 sql 插入到我的 VBA 代码中,但出于某种原因,它与我在 ORACLE 中看到的不完全匹配。

我在 VBA 中看到的是这个(不同的第 3 行):

 Line   Number     Date    Employee    PN       Tax
  1     1111   2015-10-15      AP     6225-6    L1
  2     1111   2015-10-15      AP     6225-6    L2
  3     1111   (null)        (null)   6225    (null)
  4     1111   2015-10-15      AP     55555     L2

由于某种原因和某种原因,SQL 工作方式不同,在 VBA 中没有提供所需的输出。什么会导致这个问题???毫无头绪,因为我在 VBA 中写了两次 SQL 以防万一我认为是我的错误。

我的VBA代码:

Sub Update_table_and_data()

'sql failo suformavimas


Dim con As ADODB.Connection
Dim rec As ADODB.Recordset
Dim cmd As ADODB.Command
Dim sql As String


sql = "Driver={Microsoft ODBC for Oracle}; " & _
"CONNECTSTRING=(DESCRIPTION=" & _
"(ADDRESS=(PROTOCOL=TCP)" & _
"(HOST= ODB)(PORT=1525))" & _
"(CONNECT_DATA=(SERVICE_NAME=ABTL))); uid=ID; pwd=PWD;"

 dat1 = (Sheets("Data").Cells(2, "G"))
 dat2 = (Sheets("Data").Cells(2, "H"))

Set con = New ADODB.Connection
Set rec = New ADODB.Recordset
Set cmd = New ADODB.Command

Sheets("Output").Range("A2:AS999999").ClearContents

If ((Not IsEmpty(dat1)) And (Not IsEmpty(dat2))) Then
  con.Open sql


    Set rec = con.Execute(" SELECT distinct ........
             ' " WHERE i.date >= to_date('" & dat1 & "','YYYY.MM.DD') 
             ' " AND i.date <= to_date('" & dat2 & "','YYYY.MM.DD' ) ) XX   order by    XX.number ")

    If Not rec.EOF Then
            Sheets("Output").Range("A2").CopyFromRecordset rec
            rec.Close
        Else
            MsgBox "PLEASE, CHECK DATE FORMAT!", vbCritical
        End If

    If CBool(con.State And adStateOpen) Then con.Close

    Set rec = Nothing
    Set con = Nothing

End Sub

问题是这两个查询相同。

您的 VBA 版本中有以下内容,但 Oracle 版本中没有:

WHERE inh.invoice_date >= to_date('" & dat1 & "','YYYY.MM.DD') 
AND inh.invoice_date <= to_date('" & dat2 & "','YYYY.MM.DD' ) ) XX   

可能还有其他差异,但我立即跳出来了。

问题是 CopyFromRecordset - 它 运行 匹配 255 个字符,而且它不是唯一的 Excel.Range 方法。

问题是:我有没有方法?在您进入写入范围阶段之前,您是否有一个 OLEDB 驱动程序对您的 Recordset 执行此操作?

您应该在 VBA 中遍历您的记录集,并检查 VBA 中的违规字段 是否存在长度超过 255 个字符的值。如果字段已被 t运行 分类,请尝试在连接字符串中使用本机 Oracle 客户端驱动程序,而不是 Microsoft Oracle OLEDB 提供程序 - Connections.com 将提供信息。

一旦您知道记录集实际上包含您的数据,没有 t运行cation,请再次尝试 CopyFromRecordset。我其实不希望它写一个长度超过255个字符的字段,但是我遇到这个错误已经有一段时间了,它可能已经被修复了,给悲观主义者一个惊喜总是好的。

下一步:

A VBA 替代 CopyFromRecordset

这里有三个任务:

  1. 使用数据填充 VBA 数组变体 Recordset.GetRows();
  2. 转置数组,因为 GetRows 是错误的方法 Excel;
  3. 调整目标范围并将数组写为 Range.Value = Array,一项重复性任务 应该在 ArrayToRange() 例程中自动执行。

...可能还需要一些辅助工作来编写字段名称,但我在简短的回答中忽略了这一点。

最终结果是你运行这段代码:


    ArrayToRange rngTarget, ArrayTranspose(rst.GetRows)<BR />

转置数组很简单,但无论如何:


Public Function ArrayTranspose(InputArray As Variant) As Variant
Application.Volatile False<BR />
Dim arrOutput As Variant<BR />
Dim i As Long
Dim j As Long
Dim iMin As Long
Dim iMax As Long
Dim jMin As Long
Dim jMax As Long<BR />
iMin = LBound(InputArray, 1)
iMax = UBound(InputArray, 1)
jMin = LBound(InputArray, 2)
jMax = UBound(InputArray, 2)<BR />
ReDim arrOutput(jMin To jMax, iMin To iMax)<BR />
For i = iMin To iMax
    For j = jMin To jMax
        arrOutput(j, i) = InputArray(i, j)
    Next j
Next i<BR />
ArrayTranspose = arrOutput<BR />
End Function<BR />
...如果您不在目标单元格中​​添加数组维度检查和保留公式,那么 ArrayToRange 是微不足道的:要点是如果范围的维度完全正确,您可以将数据写入单个 'hit'匹配数组的维度:

Public Sub ArrayToRange(rngTarget As Excel.Range, InputArray As Variant)
' Write an array to an Excel range in a single 'hit' to the sheet
' InputArray should be a 2-Dimensional structure of the form Variant(Rows, Columns)
' The target range is resized automatically to the dimensions of the array, with ' the top left cell used as the start point.
' This subroutine saves repetitive coding for a common VBA and Excel task.
' Author: Nigel Heffernan http://Excellerando.blogspot.com

On Error Resume Next
Dim rngOutput As Excel.Range
Dim iRowCount As Long Dim iColCount As Long
iRowCount = UBound(InputArray, 1) - LBound(InputArray, 1) iColCount = UBound(InputArray, 2) - LBound(InputArray, 2)
With rngTarget.Worksheet
Set rngOutput = .Range(rngTarget.Cells(1, 1), _ rngTarget.Cells(iRowCount + 1, iColCount + 1))
Application.EnableEvents = False

rngOutput.Value2 = InputArray
Application.EnableEvents = True
Set rngTarget = rngOutput ' resizes the range This is useful, most of the time
End With ' rngTarget.Worksheet
End Sub

注意事项:在旧版本的 Excel(Office 2000,如果我记得的话)中,数组 'write' 仍然 t运行 为 255 个字符。这不再是问题;如果您仍在使用 XL2000,包含超过 255 个字符的字符串的单元格就已经是一个问题,您可能会对 t运行cation.

感到高兴