-6

Having a problem with VBA. I have written sql code (300 lines) which works perfect in SQL giving output:

 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

I have inserted that big sql into my VBA code and for some reason it does not match precisely what i see in ORACLE.

What i see in VBA is this(different 3rd line):

 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

For some reason and somehow SQL work diferently and does not give desired output in VBA. What can cause this problem??? Having no clue, as i wrote twice SQL into VBA in case thought there was my mistake.

My VBA code:

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
15
  • 3
    Please show your original query... this hardly looks like 300 lines of SQL code in your VBA script. Commented Oct 20, 2015 at 13:30
  • YEa... without the original SQL and the actual SQL code from VBA, there is not much we can do to help out. As it is your SQL up there makes 100% no sense and it's the most likely culprit for this problem. Commented Oct 20, 2015 at 13:35
  • Why do you need to see it? I mean what can cause problem in it? Using joins with simple commnads in query: distinct, case, instr,coalesce,nvl, listagg, exists.. Commented Oct 20, 2015 at 13:36
  • My SQL makes sense, otherwise it wont work in Oracle Commented Oct 20, 2015 at 13:36
  • 1
    Also, the purported query output you have shown could not possibly have come from either of the queries. Commented Oct 20, 2015 at 14:04

2 Answers 2

2

The problem is CopyFromRecordset - it's truncating at 255 chars, and it's not the only Excel.Range method that does that.

The question is: do I have a method that doesn't? And do you have an an OLEDB driver that's doing it to your Recordset before you even get to the stage of writing to the range?

You should loop through your recordset, in VBA, and check the offending field in VBA for a value exceeding 255 chars in length. If the fields are truncated already, try using the native Oracle Client drivers in your connection string, instead of the Microsoft Oracle OLEDB provider - Connections.com will have the information.

Once you know that the recordset actually contains your data, without truncation, try CopyFromRecordset again. I don't actually expect it to write a field exceeding 255 chars in length, but it's been a while since I encountered the error, it might have been fixed, and it's always nice to give a pessimist a pleasant surprise.

Next up:

A VBA Substitute for CopyFromRecordset

There are three tasks here:

  1. Populate a VBA array variant with the data using Recordset.GetRows();
  2. Transpose the array, because GetRows is the wrong way 'round for Excel;
  3. Size up a target range and write the array as Range.Value = Array, a repetitive task which should be automated in an ArrayToRange() routine.

...And maybe some ancillary work with writing the field names, but I'm ignoring that in a short answer.

The end result is that you run this code:


    ArrayToRange rngTarget, ArrayTranspose(rst.GetRows)

Transposing the array is trivial, but here it is anyway:


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
...And ArrayToRange is trivial if you don't add checks for array dimensions and preserving formulas in the target cells: the essential point is that you can write your data in a single 'hit' if the dimensions of the range exactly match the dimensions of the array:

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

A note of caution: in older versions of Excel (Office 2000, if I recall) the array 'write' still truncated to 255 chars. This is no longer a problem; and if you're still using XL2000, cells containing a string exceeding 255 chars are enough of a problem that you might be glad of the truncation.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you it worked!! Perfectly, just needed to create a Transpose array and paste it to excel sheet. Thank you once again!
@Nigel Heffernan I tried he solution provided by you. But it was not useful for me. My problem seems to be bit different. When I run same query from VBA and Oracle separately, My RECORDSET values are different.
1

The problem is that the two queries are not identical.

You have the following in your VBA version, but not in your Oracle version:

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

There may be other differences as well, but that jumped out to me immediately.

7 Comments

So ?? It is an extra field to have a date filter. If i incorporate same lines into SQL code and launch through Orace: WHERE inh.invoice_date >= to_date('2015.10.15','YYYY.MM.DD') and inh.invoice_date < to_date('2015.10.16','YYYY.MM.DD') I get same results. Both dat1 & dat2 are taken from another excel sheet which are values of 2015.10.15 and 2015.10.16
You're clearly missing the point... You're asking the database a different question, and confused why you're getting a different answer. I don't have the time to go through the rest of your query, but it's possible that wasn't the only difference.
I made same query 1:1 exactly and still getting this error. If you are not familiar with that problem please do not spam this topic
@Siyual - barring whitespace and case, it does seem to be the only difference, slightly surprisingly.
@orangutangas Spam? You asked a question, I answered. I hardly see that as spam.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.