VBA LOOP in ORACLE SQL - sql

I was trying to write a VBA to run a query assigned to MySQL only when the HCR_DM.HCR_DM_FACT table is fully loaded. I'm using the count of distinct source in that table to decide if it is fully loaded.
When I was running the Macro below, I got an error message for the Do While line, saying that Object doesn't support this property or method.
I'm quite new to VBA, and I couldn't figure out what need to be adjusted. Can some one help me with this?
Thanks!
Const CNSTR = "Provider = OraOLEDB.Oracle; Data Source =CSDPRO; ODBC;DRIVER={Oracle ODBC Driver};SERVER=CSDPRO;User ID=HCR_SANDBOX;password=******"
Sub FillWithSQLData(strSQL As String, wkSht As String)
' Given a SQL query and worksheet, fills the worksheet with a data dump of the SQL query results
' Define variables
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sql_count As String
' Set variables
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
' Connect to SQL Server
With cn
.ConnectionString = CNSTR
.Open
End With
' Query SQL Server and return results as a data dump in cell A2 of the specified worksheet
With rs
.ActiveConnection = cn
sql_count = "select count( distinct a.src_table) from hcr_dm.hcr_dm_fact a"
Set rf = cn.Execute(sql_count)
Do While rf.Fields.Value = 8
.Open strSQL
Loop
Worksheets(wkSht).Range("A2").CopyFromRecordset rs
.Close
End With
' Close connection
cn.Close
Set rs = Nothing
Set Conn = Nothing
End Sub
Sub Refresh()
' Define SQL query
Dim mySQL As String
mySQL = "select a.oracle_fin_company_id || ' - ' || a.oracle_fin_company_desc as COMPANY " & _
"From hcr_dm.legal_entity_summary a " & _
"where a.Company_Header = 'Filed'"
' Choose worksheet where results should be displayed
Dim myWkSht As String
myWkSht = "Sheet1"
' Call connection sub
Call FillWithSQLData(mySQL, myWkSht)
End Sub

You're not selecting a field. The lines
Set rf = cn.Execute(sql_count)
Do While rf.Fields.Value = 8
Should probably be
Set rs = cn.Execute(sql_count)
Do While rs.Fields(0).Value = 8
Also, note the typo in that you declared rs but you're filling rf with the Recordset.
I recommend you use the Option Explicit statement to help find these. You can read more about it here.

Related

VBA populate sql query into ListBox directly into the spreadsheet (no userform)

So I checked some examples and it seems there are a lot of peoples that populate forms from SQLinto excel but in my case, I have a multi selection Excel listBox that is linked with a Sql recordset.
Basically, I managed to send my full SQL recordset into my spreadsheet. It's a table (1500 rows,9 columns) and in my spreadsheet, Above this generated table I have 9 Listboxes, each Listbox should represents all the entries of its linked column.
I want to start simple and populate one column into my excel Listbox so that users can just select whatever entry(ies) they want into the listbox. My problem is that I don't find the right ListBox method to display my entries. Here is my code so far:
Populating the recordset into SQL (That is working for whom who need this):
Sub Get_Datas_From_SQL()
Dim mobjConn As ADODB.Connection
Dim strConn As String
Set mobjConn = New ADODB.Connection
Dim strSQL As String
strConn = "Provider=SQLOLEDB; Data Source=My_server;" _
& "Initial Catalog=My_db;Integrated Security=SSPI;"
mobjConn.Open strConn
Dim rs As ADODB.Recordset
Dim Rn As Range
Set rs = New ADODB.Recordset
Set Rn = My_sheet.Range("A20")
My_sheet.Range(Rn, Rn.Offset(2000, 20)).ClearContents
strSQL = "SELECT * FROM Stocks_table"
With rs
.ActiveConnection = mobjConn
.Open strSQL
Rn.CopyFromRecordset rs
.Close
End With
mobjConn.Close
Set rs = Nothing
End Sub
Now, as a start, I add the code that is supposed to populate one of the nine Listboxes
Sub init_()
Dim mobjConn As ADODB.Connection
Dim strConn As String
Set mobjConn = New ADODB.Connection
Dim strSQL As String
strConn = "Provider=SQLOLEDB; Data Source=My_server;" _
& "Initial Catalog=My_db;Integrated Security=SSPI;"
mobjConn.Open strConn
strSQL = "SELECT DISTINCT Currency FROM Stocks_table "
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
With rs
.ActiveConnection = mobjConn
.Open strSQL
Dim a()
a = rs.GetRows
?
.Close
End With
End Sub
I took some remarks into account from previous questions and I'll get back to potential answers a fast as possible !
Thanks a lot in advance and have a great day
When you use the GetRows-method of a recordset, the data will be put into a 2-dimensional array. What's a little bit counter-intuitive is that the first index is the index into fields and the second is the index into the rows of the recordset.
You can assign a 2-dimensional array to the List-property of a listbox - but the first index needs to be the row and the second the field number (if you deal with a multi-column listbox). So all you need to do is to transpose the array before assigning it:
a = rs.GetRows
shtEquity.ListBoxCcy.List = Application.WorksheetFunction.Transpose(a)
For those who want to know, here is the answer:
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
With rs
.ActiveConnection = mobjConn
.Open strSQL
Dim a
a = rs.GetRows
For Each Row In a
shtEquity.ListBoxCcy.AddItem Row
Next
.Close
End With
a = Rs.GetRows
Worksheets(1).Shapes(1).ControlFormat.List = a 'control ListBox
Worksheets(1).OLEObjects(1).Object.List = WorksheetFunction.Transpose(a) 'Oleobject listbox
if your Listbox is MSForms.ListBox then refer below.
Dim Ws As Worksheet
Dim oleObjt As MSForms.ListBox
Set Ws = Worksheets(1)
Set oleObjt = Ws.OLEObjects("ListBox1").Object 'Ws.OLEObjects(1).Object
oleObjt.Clear
oleObjt.List = WorksheetFunction.Transpose(a)
Control & Oleobject image

How to return multiple values from table based on specific item that I entered?

I tried to use Tooling_No_AfterUpdate() for both Sub and Function but it prompt me 'Ambiguous name detected' as I know that I can't use the same identifier. Then, I changed the identifier and set it to public function but it doesn't work and prompt me 'User-defined type not defined'.
I'm creating a form for user to enter the tooling number to know the storage location where it can be more than one location. I tried to use ADODB.Recordset to get data from my asset table. So here's what I tried:
Private Function Tooling_No_Enter() As ADODB.Recordset
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
Set Tooling_No_Enter = CurrentProject.Connection.Execute("select FirstName, LastName from Employees")
End Function
Private Sub Tooling_No_AfterUpdate()
Dim strStorage_Location_1 As String
Dim strStorage_Location_2 As String
Dim strStorage_Location_3 As String
Dim strStorage_Location_4 As String
Dim strStorage_Location_5 As String
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
Set rst = Tooling_No_Enter()
Do While Not rst.EOF
strStorage_Location_1 = rst!Storage_Loacation_1
strStorage_Location_2 = rst!Storage_Loacation_2
strStorage_Location_3 = rst!Storage_Loacation_3
strStorage_Location_4 = rst!Storage_Loacation_4
strStorage_Location_5 = rst!Storage_Loacation_5
Debug.Print strStorage_Location_1 + vbCrLf + strStorage_Location_2 + vbCrLf + strStorage_Location_3 + vbCrLf + strStorage_Location_4 + vbCrLf + strStorage_Location_5
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
End Sub
After that, users able to choose the location while the chosen location will be recorded into asset table and transaction table and these are the parts i can't figure it out.
You are using the wrong method to open ADODB recordset. For one thing, Execute is used for action SQL (DELETE, UPDATE, INSERT).
One way to use a recordset object in multiple procedures is to declare recordset variable in module header. Example shows declaring and setting and opening connection and recordset objects which are then referred to in another procedure not shown.
Option Compare Database
Option Explicit
Public strOldLabNum
Dim cn As ADODB.Connection
Dim rsOldSample As ADODB.Recordset
___________________________________________________
Private Sub cbxOldLabNum_AfterUpdate()
Set cn = CurrentProject.Connection
Set rsOldSample = New ADODB.Recordset
strOldLabNum = Me.tbxOldYear & "A-" & Me.cbxOldLabNum
'select old sample info from table zSample
rsOldSample.Open "SELECT * FROM zSample WHERE LabNum='" & strOldLabNum & "';", _
cn, adOpenStatic, adLockPessimistic
End Sub

Parameters in Excel External Data Union Query

I have two queries that pull data from SQL Server into Excel. Both work perfectly fine. I tried to Union them together and pass in a parameter as a date, and now nothing works. Here's a link to an article that describes how to use Microsoft Query, and pass in a parameter.
http://dailydoseofexcel.com/archives/2004/12/13/parameters-in-excel-external-data-queries/
All I want to do is get this working with a Union Query. Is that possible? Or, do I need a VBA solution to achieve this. I'm sure it's do-able, I just don't know exactly how to do it. I'd appreciate any suggestions.
Thanks!
Thanks everyone. I ended up doing it in VBA.
Sub ImportFromDB()
' Create a connection object.
Dim cnPubs As ADODB.Connection
Set cnPubs = New ADODB.Connection
' Provide the connection string.
Dim strConn As String
'Use the SQL Server OLE DB Provider.
strConn = "PROVIDER=SQLOLEDB;"
'Connect to the Pubs database on the local server.
strConn = strConn & "DATA SOURCE=SERVER_NAME;INITIAL CATALOG=Data_Base;"
'Use an integrated login.
strConn = strConn & "Trusted_Connection=Yes;"
'Now open the connection.
cnPubs.Open strConn
' Create a recordset object.
Dim rsPubs As ADODB.Recordset
Set rsPubs = New ADODB.Recordset
Set sht = Worksheets("Impact Analysis")
With sht
.Range("N:U").ClearContents
.Range("N1").Resize(1, 8).Value = Array("CONTACT_ID", "CATEGORY", "COMPANY_CODE", "CUSTOMER_NO", "SECTOR", "DES", "ASOFDATE", "BALANCE")
Set rw = .Rows(2)
End With
With rsPubs
' Assign the Connection object.
.ActiveConnection = cnPubs
' Extract the required records.
.Open "SELECT * FROM MY_TABLE"
' Copy the records into cell A1 on Sheet1.
Worksheets("Impact Analysis").Range("N2").CopyFromRecordset rsPubs
' Tidy up
.Close
End With
cnPubs.Close
Set rsPubs = Nothing
Set cnPubs = Nothing
End Sub

Excel VBA - Get Data from SQL based of Range - Automation Error

When running the below code I keep getting an Automation error, for the life of me I can't figure out why. Can anyone shed some light?
When I use the debug it highlights the below;
rs.Open SQLStr, cn
I saw some references to
I've been tasked to get data from a SQL DB based off the values in Column A Row 3 onwards.
Example of Excel Sheet:
ITEM | QTY TO PICK | QTY ON ORDER | Column 2 | Column 3 etc
PART 1 | 5 | <Data will be populated here>
PART 2 | 12 | <Data will be populated here>
This code runs through a Command Button.
The data pulled from SQL will be populated starting in C3 onwards.
Private Sub CommandButton2_Click()
' Create a connection object.
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
' Provide the connection string.
Dim strConn As String
'Use the SQL Server OLE DB Provider.
strConn = "Provider=SQLOLEDB;"
'Connect to the Pubs database on the local server.
strConn = strConn & "server=<server name>;INITIAL CATALOG=<DB Name>;"
'Use an integrated login.
strConn = strConn & " INTEGRATED SECURITY=sspi;"
'Now open the connection.
cn.Open strConn
'
'
ActiveSheet.Range("C3:G10000").Clear ' clear out existing data
Dim ItemNumber As String
ItemNumber = Range("A3").Value
' Create a recordset object.
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
SQLStr = "Select * from vw_WorksOrder WHERE ITEMNO = " & ItemNumber & ""
rs.Open SQLStr, cn
' Copy the records into cell A1 on Sheet1.
Sheet4.Range("C3").CopyFromRecordset rs
' Tidy up
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
As #Zac points out with incorrect use of quotes which resolves issue, consider not using quotes or variable concatenation at all by employing the industry best practice of parameterization. ADO can parameterize SQL calls using its Command CreateParameter method.
See below example using your setup where a ? is used as placeholder in prepared statement, then a parameter is later appended defining its name, type, direction size, and value.
...
Dim cmd As New ADODB.Command
With cmd
.ActiveConnection = cn
.CommandText = "SELECT * FROM vw_WorksOrder WHERE ITEMNO = ?"
.CommandType = adCmdText
.Parameters.Append cmd.CreateParameter("itemparam", adVarChar, adParamInput, 255, ItemNumber)
End With
Dim rs As New ADODB.Recordset
Set rst = cmd.Execute
...
Also, another industry best practice is error and exception handling for runtime errors as AutomationError is not useful for debugging. And you want to release all Set objects regardless of error or not. In VBA, you can use the On Error handling to output more useful messages and release objects from memory accordingly.
Private Sub CommandButton2_Click()
On Error Goto ErrHandle
'...same code but without any Set obj = Nothing (since used in ExitHandle)
ExitHandle:
Set rs = Nothing
Set cmd = Nothing
Set cn = Nothing
Exit Sub
ErrHandle:
Msgbox Err.Number & " - " & Err.Description
Resume ExitHandle
End Sub

Is there a limit to the query length being passed to ADODB?

I am currently testing a framework that stores a SQL query in a cell on an excel workbook and then passes the cell value to a variable. This variable then gets executed through rs.Open query, cn where:
Dim rs As ADODB.Recordset
Dim cn As ADODB.Connection
and I have tried these for "query" :
Dim query as String
Dim query as Variant
or even playing with fixed length queries:
Dim query as String * 9999
In playing with the output of the query string, it cuts off somewhere around 8000. Google is coming up short for me, so I am coming here for answers. Is there a specific limit to what a variable can pass to recordset.Open()?
NB: The connection string I am using for this particular query is :
ConnectionString = "User ID=User;Password=PW;Data Source=DB;Provider=OraOLEDB.Oracle"
But if you know whether there is a system specific limit for Oracle, NetezzaSQL, or MS SQL Server (SQLOLEDB.1) please let me know. I will need to specify the limitations of each in order to define which new queries will need to be converted into stored procedures.
Here is the essentials of the code:
Sub RunQueryTable()
Dim cn As ADODB.Connection
Dim RS As ADODB.Recordset
Dim iCols As Integer
Dim DB As String, User As String, PW As String
Dim SQLTable As Worksheet
Dim ConnectionString as String
Dim query As String 'Or Dim query As Variant 'Or Dim query As String * 9999
Dim i As Long
etc, etc.
Set SQLTable = Sheet32
Set cn = New ADODB.Connection
Set RS = New ADODB.Recordset
DB = _____
User = ______
PW = ____
ConnectionString = "User ID=" & User & _
";Password=" & PW & _
";Data Source=" & DB & _
";Provider=OraOLEDB.Oracle"
query = SQLTable.Cells(i, 3).Text
cn.Open (ConnectionString)
RS.CursorType = adOpenForwardOnly
RS.Open (query), cn
For iCols = 0 To RS.Fields.count - 1
Worksheets("Output").Cells(1, iCols + 1).Value = RS.Fields(iCols).Name
Next
Worksheets("Output").Cells(2, "A").CopyFromRecordset RS
RS.Close
cn.Close
End Sub
The specific error I am getting from VBA is : "ORA-00923: FROM keyword not found where expected" because the query is getting cut off.
Here's your problem:
query = SQLTable.Cells(i, 3).Text
Consider:
Range("A1").Value=string(12000,"*")
? len(range("a1").value) '>> 12000
? len(range("a1").text) '>> 8221