object is closed vba excel ADODB - excel

I get Operation is not allowed when the object is closed error.
Why I do get this error?
[Error location][2]
There is nothing wrong with the connection.
I can do SQL queries on the same cmd connection and have no problems with them.
Only this query messes me up.
I usually don't use Set search path or table short names, but just incase got
into very detail this time.
When I run the same query in PostgreSQL I get the result:
[postgres output for the same SQL query][1]
I have been digging around google for hours and I can't find any answers.
Does it have to do something with drivers?
How do I know what driver I use for excel?
What driver I should use?
How I change driver?
[References I use][3]
https://i.stack.imgur.com/R4nLe.png
https://i.stack.imgur.com/k4uJo.png
https://i.stack.imgur.com/Ytrlk.png
CODE
Public Function getDBArray(cmd, strSQL)
Dim recordID As Long, recordAmount As Long, totalFields As Integer, fieldID As Integer
Dim rs As New ADODB.Recordset
Set rs = CreateObject("ADODB.Recordset")
cmd.CommandText = strSQL '' << this is the strSQL i copy pasted directly to pgadmin and it worked
Set rs = cmd.Execute
totalFields = getTableAmount(rs.Fields)
recordAmount = getTableAmount(rs) ' << error in this function
recordID = 0

Apparently I was not suppose to used SET SEARCH PATH

Related

Reference for DB2 access from Excel?

I am having a terrible time trying to get the most simple code to execute consistently in an Excel VBA module.
I'm just trying to assign the value of a field (column) in DB2 to a variable in the module. I've tried the following:
Connection:
Dim odbcName as String
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strCmd As String
'ACME is the name of the ODBC connection I've established and verified/validated.
conn.Open("ACME")
strCmd = "SELECT UNIQUEID, MARKET, SECTOR, CLIENTID FROM PROJECTINFO WHERE UNIQUEID=1234567"
rs.Open Source:=strCmd, ActiveConnection:=conn, CursorType:=adOpenDynamic, LockType:=adLockOptimistic
All is good to that point. The next bit of code is:
If rs.EOF then
'Do some work to add a record if it doesn't already exist - this works fine.
Else
Dim sqlMarket as String
sqlMarket = rs.Fields("MARKET").Value
End If
I also tried:
sqlMarket = rs!MARKET
Both of those attempts, ON THAT LINE where I was attempting to assign a local variable the contents of the MARKET field in the recordset, caused it to crash. I mean, the entire workbook closes, then Excel reopens and tries to open the worksheets, but the module has crashed completely.
Ultimately, my intent is to check all the fields in the recordset against another set of data (in another Excel workbook), and if anything has changed, to update the DB2 recordset. But right now, I can't even seem to LOOK AT the contents of the DB2 recordset without Excel crashing.
Can anyone offer some advice as to what I'm either doing wrong, or what I'm missing?
Excel 365 (Version 1908) 64-bit
IBM DB21085I 64-bit (SQL11050 with level identifier 0601010F)
DB2 v11.5.0.1077
Windows 10 64-bit Version1909 (Build 18363.900)

Ado returning wrong Values for adNumeric(21,6) via ODBC

I am getting weird return Values from my ADO Recordset.
I tried it in VBA, VB and C++, but everytime i get the same weird and wrong values.
The Data is stored in our ERP System as Dec(21,6), this information is passed to ADO correct (adNumeric, Precision 21, Scale 6).
I am connecting to the DB via ODBC and ADO, the connection works fine and varChar, Date and other formats are just passed fine, only the dec(21,6) values are showing this weird result.
However, if i run a MS Query, it returns the correct Values, so i think i am missing some settings, but can atm not figure out which ones ...
I already tried to cast/convert the values, but this is not supported by the ODBC.
I wrote an VB and an C++ Program and received the same wrong values.
Here is my simple VBA Code for testing:
Sub test()
Dim ADOODBCConnection As ADODB.Connection
Dim ADOODBCConnectionString As String
Dim ADOODBCRS As ADODB.Recordset
Dim TestString As String
Dim TestVariant As Variant
ADOODBCConnectionString = "DSN=myDSN" 'DSN Name
Set ADOODBCConnection = New ADODB.Connection
Set ADOODBCRS = New ADODB.Recordset
ADOODBCRS.Source = "SELECT quantity_amount FROM ENTITY.app_production_ProductionOrder WHERE type_BK ='101' AND number ='PA00041825';"
ADOODBCConnection.Open ADOODBCConnectionString
ADOODBCRS.ActiveConnection = ADOODBCConnection
ADOODBCRS.Open
'wrong Values are already in the recordset
TestString = ADOODBCRS.Fields(0).Value 'wrong Value
TestVar = ADOODBCRS.Fields(0).Value 'wrong ValueUrsprungspost
ADOODBCRS.Close
ADOODBCConnection.Close
End Sub
Here are some expected and some received values:
Expected Received
1 -13511005043556401
2 -13511005043556402
3 -13511005043556403
7 -13511005043556407
8 -13511005043556408
9 -13511005043556409
10 -885457226534512230449
500 -885456663593148743733
Ok, i found that ADO is returning the wrong Values, but not .NET ODBC, so i switched from Excel to VB and used .NET ODBC (system.data.odbc).
I am still confused, why this behaves the way it does, but it seems to be in the configuration of ADO or our ODBC, both i can not change, so i use an alternative.
Long story short: ADO gets wrong values, .NET ODBC gets the correct ones

Refreshing multiple ODBC connections via background query

I am using a set of scripts that pull a lot of different data from iSeries via ODBC.
ActiveWorksheets.RefreshAll does not work as it doesn't leave enough time to run the background queries
I've tried the below,but to no avail
Dim qry As Connections
'Set qry =
For Each qry In ActiveWorksheets.Connections
qry.BackgroundQuery = False
qry.RefreshAll
DoEvents
Next qry
This gives me the expected Error 424 Object expected.
I don't expect to use Set qry = here, as I need to run through 30 different connections
Let's just call them connection1, connection2 etc for now, as their names are all over the place
Is the simplest option to stop the background query, refresh, activate background query - before the data import, or is there a better way?
I've looked all over SO - but can't find info on multiple ODBC connections
EDIT:
Dim qry As WorkbookConnection
For Each qry In ActiveWorkbook.Connections
qry.Refresh
DoEvents
Next qry
I believe your
Dim qry As Connections
should read
Dim qry As WorkbookConnection
The ActiveWorksheets.Connections.Item property returns an object of type WorkbookConnection. If you are trying to refresh the connections one at a time as it seems from your For Each statement, that object represents a single connection with methods like Refresh rather than the collection of all connections.
I managed to work this out. So all who may need this in the future can see:
Dim qry As WorkbookConnection
For Each qry In ActiveWorkbook.Connections
qry.ODBCConnection.BackgroundQuery = False
qry.Refresh
qry.ODBCConnection.BackgroundQuery = True
Next qry
Although it doesn't look like BackgroundQuery = True/False doesn't look like it's vital here. Turning it off means when you qry.Refresh, it pulls the data and refreshes it.
Also using For Each qry means that rather than writing out out 20 times, I can just look every connection and turn them off, refresh, and turn them back on

Use Excel spreadsheet from within Access

I have an Excel Spreadsheet that calculates a risk (of perioperative mortality after aneurysm repair) based on various test results.
The user inputs the test results into the spreadsheet (into cells) and then out comes a set of figures (about 6 results) for the various models that predict mortality. The spreadsheet acts as a complex function to produce the results one patient at a time.
I also have a (separate) access database holding data on multiple patients - including all the data on test results that go into the spreadsheet. At the moment I have to manually input this data into the spreadsheet, get the results out and then manually enter them onto the database.
Is there a way of doing this automatically. Ie can I export data1, data2, data3... from Access into the spreadsheet to the cells where the data needs to be input and then get the results (result1, result2, result3...) from the cells where the results are displayed ported back into access.
Ideally this could be done live.
I suppose I could try to program the functionality of the spreadheet into a complex function in access, but if I'm honest, I am not really sure how the algorithm in the spreadsheet works. It was designed by anaesthetists who are much cleverer than me....
Hope this makes sense. Any help much appreciated.
Chris Hammond
It's possible to automate Excel from Access.
Const cstrFile As String = "C:\SomeFolder\foo.xls"
Dim xlApp As Object
Dim xlWrkBk As Object
Dim xlWrkSt As Object
Set xlApp = CreateObject("Excel.Application")
xlApp.Workbooks.Open cstrFile, ReadOnly:=True
Set xlWrkBk = xlApp.Workbooks(1)
Set xlWrkSt = xlWrkBk.Worksheets(1)
With xlWrkSt
.Range("A1") = 2
.Range("A2") = 19
Debug.Print .Range("A3")
End With
xlWrkBk.Close SaveChanges:=False
However, that seems like it would be cumbersome to repeat for each row of an Access table and I'm uncertain whether doing that live is reasonable.
I would try to adapt the Excel calculations to Access VBA functions and use those custom functions in an Access query. But I don't know how big of a task that would be. I suggest you shouldn't be scared off the the anaesthetists' cleverness; that doesn't mean they actually know much more about VBA than you. At least look to see whether you can tackle it.
To push the data back to Access, you can insert data from within the Excel VBA as follows:
dim val as variant
dim db as DAO.Database
val=thisworkbook.range("a1").value
set db=OpenDatabase("c:\myAccessDB.accdb")
db.execute "insert into patientData (someField) values (" & val & ")",dbFailOnError
db.Close
You'll need to add a reference to the Microsoft Office Access Database Engine Object Library.
Not sure to perfectly understand what you want, but if you just want to export the results of a query to a spreadsheet, you could use the following:
Private Sub ExportAccessDataToExcel()
Dim SqlString As String
SqlString = "CREATE TABLE testMeasurements (TestName TEXT, Status TEXT)"
DoCmd.RunSQL (SqlString)
SqlString = "INSERT INTO testMeasurements VALUES('Average Power','PASS')"
DoCmd.RunSQL (SqlString)
SqlString = "INSERT INTO testMeasurements VALUES('Power Vs Time','FAIL')"
DoCmd.RunSQL (SqlString)
SqlString = "SELECT testMeasurements.TestName, testMeasurements.Status INTO exportToExcel "
SqlString = SqlString & "FROM testMeasurements "
SqlString = SqlString & "WHERE (((testMeasurements.TestName)='Average Power'));"
DoCmd.RunSQL (SqlString)
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel7, "exportToExcel", "C:\TestMeasurements.xls", True, "A1:G12"
End Sub
Source: http://www.ehow.com/how_7326712_save-access-query-excel-vba.html
This could be done either directly from the database or from Excel (you would need to open the database with Excel VBA to do so, but most of the Office Suite products interact well with each other).
If you want to push the data of your spreadsheet into an Access database, that's different. You just have to open the database and loop through INSERT query. Here is a quick example, you just need to add the loop:
Dim db as DAO.Database
Set db = OpenDatabase(myDataBase.mdb)
Call db.Execute("INSERT INTO myTable (Field1, Field2) VALUES('Value1', 'Value2')")

Connection string syntax for Classic ADO / ODBC / Oracle 10g EZConnect

I'm trying to connect various VBA projects to an Oracle 10g back end using ADO (2.8) and no TNS. After various attempts, we've decided that the simplest series of steps for a clean installation include:
Set up an Oracle Instant Client
Install the accompanying ODBC driver
(Test the connection using EZCONNECT via SQL Plus)
(Test the connection by creating a Windows DSN)
Everything up to here works fine. Problem is, I cannot figure out the syntax to tell ADO to use the instant client ODBC driver, which appears in my ODBC driver list as "Oracle in MyTest" (no quotes). Using the MSFT ODBC driver with EZConnect as this post suggests does not work any better than it did prior to setting up the instant client (which is to say, not at all). But this post seems to suggest it's possible, without stating exactly how, and connectionstrings.com only tells you what the Data Source portion of the string looks like, i.e.
SomeUser/SomePassword#AServer:PortNumber/InstanceName
Short version: What is the exact syntax of a classic ADO connection string referencing an instant client ODBC driver?
Thanks in advance for your help. Took me a stupid long time to get going with SO...
Similar to 'user1206604's answer - I set up an ODBC connection using ODBC Data Source Administrator (for example's sake we'll name it 'DEMO') and connect like this:
Dim conn As New adodb.Connection
Set conn = New adodb.Connection
connStr = "Provider=OraOLEDB.Oracle;Data Source=DEMO;User Id=yourUserID;Password=yourPassword;"
conn.Open connStr
Dim api As New adodb.Recordset
Set api = New adodb.Recordset
yourQueryString = "SELECT foo FROM bar"
api.Open yourQueryString, conn, adOpenDynamic, adLockReadOnly
'adjust above setting as needed
while not api.EOF
'do interesting stuff here
wend
'clean up resources
api.Close
Set api = Nothing
conn.Close
Set conn = Nothing
The ODBC data source administrator is found (on my machine) in start menu > Programs > Oracle - oraClient10g > Configuration and Migration Tools > Microsoft ODBC Administrator and looks like this:
Try this and replace the values as appropriate:
Set Connection = CreateObject("ADODB.Connection")
blnTest = Connection.Open("Driver={Oracle in instantclient};Dbq=127.0.0.1:1521/SERVICENAMEHERE", "USERNAME", "PASSWORD")
If Oracle in instantclient doesn't work check the HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers registry key to see what the value is for the Oracle Instant Client (there may be a version number appended).
If this still doesn't work for you. Leave a comment with the details of what happened and I'll try to adjust the answer for you.
' Create a connection object.'
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
' Create a recordset object.'
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
' Provide the connection string.'
Dim strConn As String
Dim str As String
'Use the SQL Server OLE DB Provider.'
strConn = "Driver=(Oracle in OraHome92);" & "Data Source=;Uid=;Pwd=;"
'Now open the connection.'
cn.Open strConn
With rs
' Assign the Connection object.'
ActiveConnection = cn
' Extract the required records.'
.Open "SELECT ", cn
End With

Resources