Runtime error 3705, operation is not allowed when object is open - excel

I am getting error 3705 after adding the line
[MTSU_Data].[Tool no]=" CInt(WsInput.Range("J" & c).value) & ";"
The highlighted line where the error occurs is at
.ActiveConnection = conn
Full code
Dim conn As ADODB.Connection
Dim Accdata As ADODB.Recordset
Dim Accfield As ADODB.Field
Dim wsQueryR As Worksheet, wsFinal As Worksheet
Set wsFinal = Worksheets("Final")
Set conn = New ADODB.Connection
Set Accdata = New ADODB.Recordset
conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\wongki7\Desktop\MTSU Db.accdb;"
conn.Open
'G:\BusUnits\MTSU\MTSU\Mold Tool Set Up\MTSU Reports\Shift Reports\MTSU Db.accdb;"
' On Error GoTo CloseConnection
For c = 2 To WsInput.Range("J" & Rows.Count).End(xlUp).Row
With Accdata
.ActiveConnection = conn
.Source = "SELECT * FROM [MTSU_Data] Where [MTSU_Data].[Date]>= #" _
& Format(CDate(WsInput.Range("A2").value), "mm/dd/yyyy") & " # AND [MTSU_Data].[Date]<= #" _
& Format(CDate(WsInput.Range("A3").value), "mm/dd/yyyy") & " # AND [MTSU_Data].[LT] = " _
& CInt(WsInput.Range("M2").value) & " AND [MTSU_Data].[Tool no]=" _
& CInt(WsInput.Range("J" & c).value) & ";"
.LockType = adLockReadOnly
'.CursorType = adOpenForwardOnly
.Open
End With
Next
Worksheets("Result").Select
Sheets("Result").Range("a2").CopyFromRecordset Accdata
Accdata.Close
conn.Close
Any help is appreciated. Thanks and have a good day ahead.

Can you not try to move the line
.ActiveConnection = conn
To outside the loop. Obviously fully qualifying it..
Accdata.ActiveConnection = conn
That looks to me that you are trying to make the connection for each iteration and I think it is only necessary once... maybe.

To best fit your code, Id try something like:
Sub SomeRoutine()
Dim conn As ADODB.Connection
Dim Accdata As ADODB.Recordset
Dim Accfield As ADODB.Field
Dim wsQueryR As Worksheet, wsFinal As Worksheet
Dim c As Long
Set wsFinal = Worksheets("Final")
Set conn = New ADODB.Connection
Set Accdata = New ADODB.Recordset
conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\wongki7\Desktop\MTSU Db.accdb;"
conn.Open
Accdata.ActiveConnection = conn
Accdata.LockType = adLockReadOnly
For c = 2 To WsInput.Range("J" & Rows.Count).End(xlUp).Row
Call Accdata.Open("SELECT * FROM BLah Blah")
Sheets("Result").Range("a2").CopyFromRecordset Accdata
Accdata.Close
Next
conn.Close
End Sub
You may be able to look at the way you build the SQL request to build a query to get the data in one go and and do a single paste to Excel with the CopyFromRecordset.... but that's a different issue.

A mistake I've made many times before. When assigning objects, you need to use Set. Change the line to
Set .ActiveConnection = conn
.Source and .LockType are scalar properties, so they don't need Set, but .Activeconnection does.

Related

Querying Excel sheet, find out if rs is empty

I wrote the proc below, and it's working fine, except that I would like to check if the recordset is empty or not. However, rs.EoF and rs.BoF always return False, even if there is no data. What is the trick to make this work ?
Sub PrepData()
Dim ws As Worksheet, wb As Workbook
Dim cn As New ADODB.Connection
Dim rs As ADODB.Recordset
Dim rs2 As ADODB.Recordset
Dim strSql As String, recs As Long
Set wb = ActiveWorkbook
Set ws = ActiveSheet
'create connection
With cn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=" & wb.FullName & ";" & _
"Extended Properties=""Excel 12.0;HDR=YES"";"
.Open
End With
'check trades without matching couterparty
strSql = "select distinct tf.counterPart from [TradeFile$A3:G5000] tf " & _
"left join [CounterpartiesMapping$] c on tf.counterpart = c.counterpart " & _
"where c.investee is null"
Set rs = cn.Execute(strSql, recs)
'HERE I'd like to see if the recordset is empty,
'but rs.eof and rs.bof are always FALSE regardless of the result
Debug.Print rs.BOF, rs.EOF, rs.RecordCount
ws.Range("p3").CopyFromRecordset rs
rs.Close
cn.Close
End Sub
Have you tried using the RecordCount property for the recordset to find the number of rows returned?
Debug.Print rs.RecordCount
I finally found the solution here:
Just replace
Set rs = cn.Execute(strSql, recs)
By
Set rs = New ADODB.Connection
rs.CursorLocation = adUseCLient
rs.Open strSql, cn
Now Debug.Print rs.BOF, rs.EOF, rs.RecordCount works as expected!

recordset count returning -1

I have tried every iteration I can find online, but I am still returning -1^ for my recordset count instead of the actual count. I tried multiple combinations of the CursorType, LockType, & CursorLocation. Here is my code.
Sub test()
Dim FullQry As String
Dim qry1 As String
Dim qry2 As String
Dim qry3 As String
Dim qry4 As String
'DECLARE VARIABLES FOR CONNECTION (HOW THE QUERY CONNECTS TO TERADATA)
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
'DECLARE VARIABLES FOR RECORDSET (THE RESULTS OF THE SQL QUERY)
Dim rs As ADODB.Recordset
Set rs = CreateObject("ADODB.Recordset")
'DECLARE VARIABLES FOR COMMAND (I THINK THIS MAKES TERADATA RUN THE QUERY AFTER A CONNECTION IS ESTABLISHED)
Dim cmdSQLData As ADODB.Command
Set cmdSQLData = New ADODB.Command
'Connect to Teradata
cn.Open "Data Source = MOSAIC_PROD; Database= prod_flight_ops_combined_vw; Persist Security info=True; User ID=758673; Password=PSPL444eae???; Session Mode=System Default;"
Set cmdSQLData.ActiveConnection = cn
rs.CursorType = adOpenStatic
rs.LockType = adLockReadOnly
rs.CursorLocation = adUseClient
'Define Qry
qry1 = "SELECT AIRLINE, FLT_NUM, SKD_ORIG, SKD_DEST, ACT_ORIG, ACT_DEST, SKD_TAIL, ACT_TAIL, SKD_SUBFLEET, ACT_SUBFLEET, SKD_OUT_GMT, SKD_IN_GMT, ACT_OUT_GMT, ACT_ON_GMT, ACT_IN_GMT, ACT_OUT_DATE_GMT, ACT_IN_DATE_GMT, ACT_OFF_GMT, "
qry2 = "SKD_OUT_DATE_GMT , SKD_IN_DATE_GMT, SKD_BLK, ACT_BLK, SKD_AIR, ACT_AIR, SKD_TXOT, ACT_TXOT, SKD_TXIN, ACT_TXIN, SKD_OFF, ACT_OFF, SKD_ON, ACT_ON, SKD_TURN, ACT_TURN, AVAIL_TURN, MOGT, OP_STATUS, OP_STATUS_DESC, SUB_DIVERT_DESC , DELAY_MSG "
qry3 = "FROM prod_flight_ops_combined_vw.OPS_FLIGHT_LEG "
qry4 = "WHERE act_out_date_gmt > current_date - 45 and act_in_date_gmt < current_date - 1 and Airline = 'AA';"
FullQry = qry1 & qry2 & qry3 & qry4
cmdSQLData.CommandText = FullQry
cmdSQLData.CommandType = adCmdText
cmdSQLData.CommandTimeout = 0
Set rs = cmdSQLData.Execute()
x = rs.RecordCount
Set rs = Nothing
Set cmdSQLData = Nothing
cn.Close
End Sub
Thanks for the assistance.
Sub test()
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.Open "Data Source=MOSAIC_PROD"
Dim rs As ADODB.Recordset
Set rs = CreateObject("ADODB.Recordset")
rs.CursorLocation = adUseClient
rs.Open "SELECT * from FROM prod_flight_ops_combined_vw.OPS_FLIGHT_LEG", cn
MsgBox (rs.RecordCount)
cn.Close
Set rs = Nothing
Set cn = Nothing
End Sub

How to copy a powerpivot table down to an excel sheet with vba?

I need to get my table up in the powerpivot model down to the excel worksheet.
So far I have tried to use a Recordset but I cant get an ActiveConnection to the powerpivot table. Is it possible? Or is there an other better way to do this?
I use the following code:
Dim name As ADODB.Recordset
Set name = New ADODB.Recordset
With name
.ActiveConnection = ConnectionName
.Source = "TableName"
.LockType = adLockReadOnly
.CursorType = adOpenForwardOnly
.Open
End With
But with this piece of code I get an error at .ActiveConnection. (Run-time error 3001, it complains about non-allowed connection interval)
This is an example of how to read the records from a named range (assuming 'TableData' is named range).
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
With cn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=" & ThisWorkbook.FullName & ";" & _
"Extended Properties=Excel 8.0;"
.Open
End With
rs.Open "SELECT * FROM [TableName]", cn
Dim r
For Each r In rs.GetRows
'Do whatever you want per record
Debug.Print r
Next r
rs.Close
cn.Close

VBA - provider cannot be found with accdb format

With the below code i get the following error when ran provider cannot be found, The below code is copied and edited from the net, It previously used .mdb files but I tried to change it to .accdb because thats the format I need it in. I'm trying to make a macro that when ran copies certain cells into a database, adding to it.
I get this error
run-time error "3706"
Provider cannot be found it may not be properly installed
-
Const TARGET_DB = "testdb.accdb"
Sub AlterOneRecord()
Dim cnn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim fld As ADODB.Field
Dim MyConn
Dim lngRow As Long
Dim lngID As String
Dim j As Long
Dim sSQL As String
'determine the ID of the current record and define the SQL statement
lngRow = ActiveCell.Row
lngID = Cells(lngRow, 1).Value
sSQL = "SELECT * FROM tblPopulation WHERE PopID = " & lngID
Set cnn = New ADODB.Connection
MyConn = ThisWorkbook.path & Application.PathSeparator & TARGET_DB
With cnn
.Provider = "Provider=Microsoft.ACE.OLEDB.12.0;"
.Open MyConn
End With
Set rst = New ADODB.Recordset
rst.CursorLocation = adUseServer
rst.Open Source:=sSQL, _
ActiveConnection:=cnn, _
CursorType:=adOpenKeyset, _
LockType:=adLockOptimistic
'Load contents of modified record from Excel to Access.
'do not load the ID again.
For j = 2 To 7
rst(Cells(1, j).Value) = Cells(lngRow, j).Value
Next j
rst.Update
' Close the connection
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
End Sub
Is there an easier way to do this? or should I try and fix this?
What you are missing is complete connection string to your data base file.
(More about connection string)
I give you a rough idea which usually works with my code:
remove this line in your code:
.Provider = "Provider=Microsoft.ACE.OLEDB.12.0;"
instead use this one:
.ConnectionString= "Provider=Microsoft.ACE.OLEDB.12.0;"
or you could use this one instead:
.Provider = "Microsoft.ACE.OLEDB.12.0"
For further information you could see this w3schools website.

Run access query from Excel and pass parameters to the query

How to execute a query in MS Access db from Excel VBA code or macro.
MS-Access query accepts some parameters, that needs to be passed from Excel.
Thanks
Here is one possibility:
Dim cn As Object
Dim strFile As String
Dim strCon As String
Dim strSQL As String
strFile = "C:\docs\Test.mdb"
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFile
''Late binding, so no reference is needed
Set cn = CreateObject("ADODB.Connection")
cn.Open strCon
strSQL = "INSERT INTO ATable (AField) " _
& "VALUES (" & Sheet1.[A1] & ")"
cn.Execute strSQL
cn.Close
Set cn = Nothing
You can also refer in-line in the sql to a dataset from Excel.
EDIT re comments
Using a command:
strSQL = "SELECT * FROM ATable " _
& "WHERE AField = #AField"
With cmd
Set .ActiveConnection = cn
.CommandText = strSQL
.CommandType = 1 'adCmdText
''ADO Datatypes are often very particular
''adSmallInt = 2 ; adParamInput = 1
.Parameters.Append .CreateParameter("#AField", 2, 1, , Sheet1.[A1])
End With
Set rs = cmd.Execute
See also: http://support.microsoft.com/kb/181782
This uses ADODB.
Set m_Connection = New Connection
If Application.Version = "12.0" Then
m_Connection.Provider = "Microsoft.ACE.OLEDB.12.0"
Else
m_Connection.Provider = "Microsoft.Jet.OLEDB.4.0"
End If
m_Connection.Open <full path to Access DB>
If m_Connection.State > 0 Then
Dim rsSource As New Recordset
rsSource.Open strQuery, m_Connection, adOpenForwardOnly, adLockReadOnly
Dim result As Long
Dim rngTarget As Range
rngTarget = ThisWorkbook.Worksheets(m_SheetName).Range("A1")
If Not rsSource.BOF Then
result = rngTarget.CopyFromRecordset(rsSource)
End If
If rsSource.State Then rsSource.Close
Set rsSource = Nothing
End If
So it runs the query and puts it where you like. strQuery is the name of a query in the db or an SQL string.

Resources