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

VBA中的SQL查询输出与SQL Oracle中的不同,sql,oracle,vba,excel,recordset,Sql,Oracle,Vba,Excel,Recordset,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)

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
我在VBA代码中插入了那个大sql,由于某种原因,它与我在ORACLE中看到的不完全匹配

我在VBA中看到的是(不同的第三行):

由于某种原因,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
子更新表和数据()
'sql failo suformavimas
Dim con作为ADODB连接
作为ADODB.Recordset的Dim rec
Dim cmd作为ADODB.Command
将sql设置为字符串
sql=“Driver={Microsoft ODBC for Oracle};”和_
“CONNECTSTRING=(DESCRIPTION=“&”_
“(地址=(协议=TCP)”和_
“(主机=ODB)(端口=1525))”&_
“(CONNECT_DATA=(SERVICE_NAME=ABTL));uid=ID;pwd=pwd;”
dat1=(表(“数据”).单元格(2,“G”))
dat2=(表(“数据”).单元格(2,“H”))
Set con=New ADODB.Connection
Set rec=New ADODB.Recordset
Set cmd=New ADODB.Command
纸张(“输出”)。范围(“A2:AS999999”)。清晰内容
如果((非等空(dat1))和(非等空(dat2)),则
con.opensql
设置rec=con.Execute(“选择不同的……)。。。。。。。。
其中i.date>=截止日期(“&dat1&”,“YYYY.MM.DD”)

'和i.date问题是这两个查询不完全相同

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

WHERE inh.invoice_date >= to_date('" & dat1 & "','YYYY.MM.DD') 
AND inh.invoice_date <= to_date('" & dat2 & "','YYYY.MM.DD' ) ) XX   
其中inh.invoice\u date>=截止日期(“&dat1&”,“YYYY.MM.DD”)

而在inh.invoice\u date中,问题在于CopyFromRecordset——它被截断为255个字符,而且它不是唯一一个这样做的Excel.Range方法

问题是:我有没有一种方法没有呢?你有没有一个OLEDB驱动程序,在你还没到写入范围的阶段之前就已经对你的记录集进行了操作

您应该在VBA中循环查看您的记录集,并检查VBA中有问题的字段的长度是否超过255个字符。如果字段已被截断,请尝试在连接字符串中使用本机Oracle客户端驱动程序,而不是Microsoft Oracle OLEDB provider-Connections.com将获得信息。

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

下一步:用VBA替代CopyFromRecordset

这里有三项任务:

  • 使用以下命令使用数据填充VBA数组变量 Recordset.GetRows()
  • 转置数组,因为GetRows对于 卓越
  • 调整目标范围的大小并将数组写入 Range.Value=Array,这是一项重复性任务 应在ArrayToRange()例程中自动执行
  • …也许还需要一些辅助工作来编写字段名,但我在简短的回答中忽略了这一点

    最终结果是运行以下代码:

    阵列范围rngTarget,阵列传输(rst.GetRows)

    转置数组很简单,但无论如何,这里是: 公共函数ArrayTranspose(InputArray作为变量)作为变量 Application.Volatile False
    变光输出作为变量
    我想我会坚持多久 Dim j尽可能长 长的 暗iMax与长iMax相同 我会尽可能长 将jMax变长
    iMin=LBound(输入阵列,1) iMax=UBound(输入阵列,1) jMin=LBound(输入阵列,2) jMax=UBound(输入阵列,2)
    ReDim arrOutput(jMin到jMax,iMin到iMax)
    对于i=iMin到iMax 对于j=jMin到jMax arrOutput(j,i)=输入阵列(i,j) 下一个j 下一个我
    ArrayTranspose=ArroOutput
    结束函数
    …如果不在目标单元格中添加对数组维度的检查并保留公式,那么ArrayToRange就无关紧要了:关键是,如果范围的维度与数组的维度完全匹配,则可以在一次“命中”中写入数据:

    公共子数组范围(rngTarget作为Excel.Range,InputArray作为Variant) '在工作表的一次“点击”中,将数组写入Excel范围 '输入阵列应该是形式变量(行、列)的二维结构
    '目标范围将自动调整为数组的尺寸,带有 '左上角的单元格用作起点。
    '此子例程保存了常见VBA和Excel任务的重复编码。
    作者:奈杰尔·赫弗南 出错时继续下一步
    尺寸输出为Excel.Range
    暗淡的iRowCount尽可能长 Dim iColCount尽可能长
    iRowCount=UBound(输入阵列,1)-LBound(输入阵列,1) iColCount=UBound(输入阵列,2)-LBound(输入阵列,2)
    使用rngTarget.工作表
    设置rngOutput=.Range(rngTarget.Cells(1,1)_ RNG目标单元格(iRowCount+1,iColCount+1))
    Application.EnableEvents=False

    rngOutput.Value2=输入阵列
    Application.EnableEvents=True
    Set rngTarget=rngOutput'调整范围大小这在大多数情况下都很有用
    以“rngTarget.工作表”结尾
    端接头


    注意事项:在旧版本的Excel中(Office 2000,如果我记得的话)数组“write”仍被截断为255个字符。这不再是一个问题;如果您仍在使用XL2000,则包含超过255个字符的字符串的单元格已足够成为一个问题,您可能会很高兴进行截断。

    请显示您的原始查询…在VBA脚本中,这几乎不像300行SQL代码。是的……没有orig最后的SQL和VBA中的实际SQL代码,我们无法提供太多帮助。因为上面的SQL是您的SQL,所以100%没有意义,它很可能是这个问题的罪魁祸首。为什么您需要查看它?我的意思是
    WHERE inh.invoice_date >= to_date('" & dat1 & "','YYYY.MM.DD') 
    AND inh.invoice_date <= to_date('" & dat2 & "','YYYY.MM.DD' ) ) XX   
    
    ArrayToRange rngTarget, ArrayTranspose(rst.GetRows)
    Public Function ArrayTranspose(InputArray As Variant) As Variant Application.Volatile False
    Dim arrOutput As Variant
    Dim i As Long Dim j As Long Dim iMin As Long Dim iMax As Long Dim jMin As Long Dim jMax As Long
    iMin = LBound(InputArray, 1) iMax = UBound(InputArray, 1) jMin = LBound(InputArray, 2) jMax = UBound(InputArray, 2)
    ReDim arrOutput(jMin To jMax, iMin To iMax)
    For i = iMin To iMax For j = jMin To jMax arrOutput(j, i) = InputArray(i, j) Next j Next i
    ArrayTranspose = arrOutput
    End Function
    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