VBA中的SQL查询输出与SQL Oracle中的不同
VBA有问题。我已经编写了sql代码(300行),它在sql输出中工作得非常完美: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)
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