I have created a macro that sends a new CommandText to an ODBC Connection in my Excel spreadsheet and then refreshes the table of results associated with the query. This has been working fine, but I've noticed that each time I run the macro it overwrites the connection string with some default values that work on my machine but will not work on other users' machines because they do not have the saved connection file that I have. The more specific connection string that specifies a server address works when entered manually, but will get overwritten anytime the macro is run.
I figured I would just have the macro write the connection string at the same time it sends the new CommandText, but I'm running into errors.
My code is as follows:
Sub NewData()
Dim lStr As String
lStr = ""
lStr = lStr & " USE myDBname; "
lStr = lStr & " WITH X AS ("
lStr = lStr & " SELECT"
lStr = lStr & " column1, column2, column3, etc"
lStr = lStr & " FROM"
lStr = lStr & " etc. etc. etc."
With ActiveWorkbook.Connections("PayoffQuery").ODBCConnection
.CommandText = lStr
.Connection = "SERVER=myserveraddress;UID=SYSTEM;Trusted_Connection=Yes;APP=2007 Microsoft Office system;WSID=SYSTEM;DATABASE=myDBname;"
End With
End Sub
The .CommandText still updates just fine, but the .Connection throws runtime error 1004: Application-defined or object-defined error.
Any idea what I'm doing wrong here? TIA.
In your VBA code, add ODBC; to the beginning of your new connection string.
.Connection = "ODBC;SERVER=myserveraddress;UID=SYSTEM;Trusted_Connection=Yes;APP=2007 Microsoft Office system;WSID=SYSTEM;DATABASE=myDBname;"
Related
I'm using the following code to export information from an excel file to an access database. It worked fine last time I used it but ever since I started it up today I've been running into the following issue.
Public Sub Export_to_ACCDB()
Set cn = CreateObject("ADODB.Connection")
dbPath = Application.ActiveWorkbook.Path & "\Newdatabase.accdb"
dbWb = Application.ActiveWorkbook.FullName
dbWs = Application.Worksheets("DATABASE").Name
scn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath
dsh = "[" & Application.ActiveSheet.Name & "$]"
cn.Open scn
'ssql = "INSERT INTO Database ([Column1],[Column2],[Column3]) "
ssql = ssql & "SELECT * FROM [Excel 8.0;HDR=YES;DATABASE=" & dbWb & "]." & dsh
cn.Execute ssql '<<< The error occurs here
End Sub
I get the following error running this code:
Run-time error '-2147217900 (80040e14)':
The INSERT INTO statement contains the following unknown field name: 'F12'. Make sure you have typed the name correctly, and try the operation again.
I don't have a field name called 'F12' in either my excel file or my access database. I can't seem to figure out what's going on.
Column headers are written correctly.
Column headers do not contain spaces or other irregularities.
EDIT:
Seems like Excel thinks you got a 12th column (maybe by accidentally entering something). Mark column L and delete it #FunThomas
This seemed to be the problem. I had to delete all the columns after the last one which contained the correct fieldname. Now it's working again.
I am having trouble getting data from an Access Database. I found this code online, and it seems to work (to an extent), but for some reason it will only pull the column headers, and none of the data from the query. I am not too familiar with Access, that is why I pulled one from offline.
Someone had a similar post a while back, where the code they used was the same, and our queries were exactly the same, but we had different issues.
Importing Data From Access Using Excel VBA
Would anyone happen to know why the data won't pull?
Sub getDataFromAccess()
Dim DBFullName As String
Dim Connect As String, Source As String
Dim Connection As ADODB.Connection
Dim Recordset As ADODB.Recordset
Dim Col As Integer
Dim startdt As String
Dim stopdt As String
Dim refresh
refresh = MsgBox("Start New Query?", vbYesNo)
If refresh = vbYes Then
Sheet1.Cells.Clear
startdt = Application.InputBox("Please Input Start Date for Query (MM/DD/YYYY): ", "Start Date")
stopdt = Application.InputBox("Please Input Stop Date for Query (MM/DD/YYYY): ", "Stop Date")
DBFullName = "X:\MyDocuments\CMS\CMS Database.mdb"
' Open the connection
Set Connection = New ADODB.Connection
Connect = "Provider=Microsoft.ACE.OLEDB.12.0;"
Connect = Connect & "Data Source=" & DBFullName & ";"
Connection.Open ConnectionString:=Connect
Set Recordset = New ADODB.Recordset
With Recordset
Source = "SELECT * FROM Tracking WHERE [Date_Logged] BETWEEN " & startdt & " AND " & stopdt & " ORDER BY [Date_Logged]"
.Open Source:=Source, ActiveConnection:=Connection
For Col = 0 To Recordset.Fields.Count - 1
Range(“A1”).Offset(0, Col).Value = Recordset.Fields(Col).Name
Next
Range(“A1”).Offset(1, 0).CopyFromRecordset Recordset
End With
ActiveSheet.Columns.AutoFit
Set Recordset = Nothing
Connection.Close
Set Connection = Nothing
End Sub
An easy way to get data in Excel, especially from Access, is to use the menu "Data > Access". This creates a connection to a table, that you can freely edit.
At the very least, that is a convenient way to limit your investigations to:
the query you typed (the connection string will always be OK, so if you're getting no values, it comes from the query)
or the VBA itself (if the table is returning values but not the corresponding VBA Sub, then you know it comes from the VBA itself, not the SQL).
I'm skipping the creation of connection becuse it's really straightforward; it's better to focus on what you can do once the table has been created.
Edit the connection
When you select the table and go to menu "Data > Properties", then in the window you click on the top right button "Connection properties", you get to the definition of the connection, i.e. some properties in the first tab and the actual definition in the second tab.
If you move the .mdb file, you'll have to change the connection string accordingly. There should be no other events forcing you to alter it.
If you want to type an actual complex query, you'll need to:
Change the command type from "Table" to "SQL"
Type the query in the bottom edit box.
Note if you want to define dynamic parameters in the WHERE clause, you can put question marks (?) instead of hardcoded values. Question marks can be linked to either constants (with a prompt to change their values) or cell.
Use in VBA
Once you checked with the connection that everything works, you have 2 solutions to put that in VBA.
Either use exactly the code you have above; in that case, you can make things easy by simply copying the connection string and the query.
Alternatively and this is what I would recommend, the table we have built previously can be updated very easily in VBA.
Use this piece of code:
WorksheetWithTable.ListObjects(1).QueryTable.Refresh
You really don't need more than this 1 line of code to do the refresh.
If you set your query to automatically refresh when a cell's value is being modified, then you do not even need it at all.
Note #1: Instead of an index in .ListObjects(1), you can use the table name.
Node #2: Refresh has an optional parameters to drive if the query is to be refresh in the background. True means the VBA code will not wait for the execution to end before moving to the next instruction. False, obviously, is the opposite.
The posted code is missing End If line. Perhaps this is just a posting typo because code should not compile and run.
The query SQL needs # delimiters for the date parameters:
Source = "SELECT * FROM Tracking WHERE [Date_Logged] BETWEEN #" & startdt & "# AND #" & stopdt & "# ORDER BY [Date_Logged]"
Text field would need apostrophe delimiters. Number field does not need delimiters.
I solved the answer to my own question after hours, i found a different set of code that worked fine. Thank you all for your help!
Sub getdatamdb()
Dim cn As Object, rs As Object
Dim intColIndex As Integer
Dim DBFullName As String
Dim TargetRange As Range
10 DBFullName = "X:\MyDocuments\CMS\CMS Database.mdb"
20 On Error GoTo Whoa
30 Application.ScreenUpdating = False
40 Set TargetRange = Sheets("Sheet1").Range("A1")
50 Set cn = CreateObject("ADODB.Connection")
60 cn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & DBFullName & ";"
70 Set rs = CreateObject("ADODB.Recordset")
80 rs.Open "SELECT * FROM Tracking WHERE [Date_Logged] BETWEEN #" & startdt & "# AND #" & stopdt & "# ORDER BY [Date_Logged]", cn, , , adCmdText
' Write the field names
90 For intColIndex = 0 To rs.Fields.Count - 1
100 TargetRange.Offset(1, intColIndex).Value = rs.Fields(intColIndex).Name
110 Next
' Write recordset
120 TargetRange.Offset(1, 0).CopyFromRecordset rs
LetsContinue:
130 Application.ScreenUpdating = True
140 On Error Resume Next
150 rs.Close
160 Set rs = Nothing
170 cn.Close
180 Set cn = Nothing
190 On Error GoTo 0
200 Exit Sub
Whoa:
210 MsgBox "Error Description :" & Err.Description & vbCrLf & _
"Error at line :" & Erl & vbCrLf & _
"Error Number :" & Err.Number
220 Resume LetsContinue
End If
End Sub
In my excel sheet "Progress Status" I have 2 columns, the first one contain the list of all the test cases that are including during my cycle and in the second column I want to get the latest status of the test case from an other sheet named "All run TestCases".
I tried using some excel function to get the latest date and time so that I can get the latest status of a test case but I didn't succeed because I don't have a deep knowledge of them, Can someone please help me with this.The picture shows how my two sheet look like.
Okay here is the answer. Be sure executionDate and executionTime columns are in the Date and Time format respectively. Create a new column as FinalTime with the following function =B3+C3. Apply this for the rest. Then you can use the following macro. You may need to check Tools > preferences in the VBA screen if OLEDB connection is clicked. I assumed your sheets' names as TestCases and ProgressStatus. And header of Test case name is changed as Test. You can either change them on your sheet or in macro.
Sub makro()
Dim deneme As String
Dim queryStr As String
Dim con As Object, rs As Object, sorgu$, a$
Set con = CreateObject("adodb.connection")
Set rs = CreateObject("adodb.recordset")
con.Open "provider=microsoft.ace.oledb.12.0;data source=" & _
ThisWorkbook.FullName & ";extended properties=""Excel 12.0;hdr=yes"""
queryStr = "Select u.[Test]" & _
",u.[Status] " & _
"From [TestCases$] As u " & _
"Inner Join ( " & _
"Select [Test] " & _
",max(FinalTime) as [LastDate] " & _
"From [TestCases$] " & _
"Group By [Test]) As [q] " & _
"On u.Test = q.Test " & _
" And u.FinalTime = q.LastDate"
Set rs = con.Execute(queryStr)
Sheets("ProgressStatus").Range("A2").CopyFromRecordset rs
Set rs = Nothing
Set con = Nothing
End Sub
Here is the TestCases and ProgressStatus-with results- sheets I worked on.
I would like to connect to my Access tables using VBA. I want to be able to type in a purchase order number, and reference that value in a query to the Access table. I want to print the results of that query to my Excel worksheet. This is what I have so far.. any ideas?
Sub CommandButton1_Click()
Dim myValue As Variant
myValue = InputBox("Enter Purchase Order Number:")
Range("A1").Value = myValue
Call ADO_Conn(myValue)
End Sub
Sub ADO_Conn(myValue)
Dim conn As New Connection
Dim rstAnswer As New ADODB.Recordset
Dim connected As Boolean
Dim RootPath, DBPath As String
Dim tempString As String
connected = False
RootPath = "Z:\BSD Internship Program\FY14 Intern Files\John Jameson\Vouchers"
DBPath = RootPath & "Acquisition Support Datamart Build 9.11-03.accdb"
conn.Open "Provider=Microsoft.ACE.OLEDB.12.0; Data Source= Z:\BSD Internship Program\FY14 Intern Files\John Jameson\Vouchers\Acquisition Support Datamart 9.1103.accdb;"
connected = True
rstAnswer.Open "SELECT VW_PUB_PURCHASE_ORDER.PO_NO FROM VW_PUB_PURCHASE_ORDER " & _
"WHERE VW_PUB_PURCHASE_ORDER.PO_NO = ' " & myValue & " ';", conn, adOpenKeyset, adLockOptimistic
Do Until rstAnswer.EOF
tempString = CStr(rstAnswer!VW_PUB_PURCHASE_ORDER)
Application.ActiveWorkbook.Worksheets("Sheet1").Range("A5").Value = tempString
rstAnswer.MoveNext
Loop
rstAnswer.Close
conn.Close
connected = False
End Sub
A couple of things about your initial query:
rstAnswer.Open "SELECT VW_PUB_PURCHASE_ORDER.PO_NO FROM VW_PUB_PURCHASE_ORDER " & _
"WHERE VW_PUB_PURCHASE_ORDER.PO_NO = ' " & myValue & " ';", conn, adOpenKeyset, adLockOptimistic
You are searching only for PO_NO in this query, so that is the only value that will return. If you want more than just that data (as I assume you might), then you want this:
rstAnswer.Open "SELECT * FROM VW_PUB_PURCHASE_ORDER " & _
"WHERE VW_PUB_PURCHASE_ORDER.PO_NO = ' " & myValue & " ';", conn, adOpenKeyset, adLockOptimistic
... where the asterisk means "all".
In addition, this bit concerns me:
' " & myValue & " '
You are adding leading and trailing blanks to your search term. This may or may not be what you want, but I assume that you do not want this. You probably want:
'" & myValue & "'
And if your PO_NO is a numeric value, you need to omit the apostrophes:
" & myValue & "
Lastly, I don't think you want to loop at all. The SELECT query will return all the results without requiring you to iterate rows. Maybe you should try getting rid of your "do" loop and using this instead:
Worksheets("Sheet1").Range("A5").CopyFromRecordset rstAnswer
Your query values will then be dropped into a dynamic range starting at the designated sheet & cell.
I didn't test the code so I might not have caught everything, but those jumped out at me.
Hope that helps!
Nate
I am trying to pull data from an ACD call data system, Nortel Contact Center 6.0 to be exact, and if you use that particular system what I am trying to capture is the daily call by call data. However when I use this code
(sCW is a common word string that equals eCallByCallStat and
sDate is
dDate = Format(Month(deffDate) & "/" & iStartDay & "/" & Year(deffDate), "mm/dd/yyyy")
sDate = Format(dDate, "yyyymmdd")
)
sSql = ""
sConn = "ODBC;DSN=Aus1S002;UID=somevaliduser;PWD=avalidpassword;SRVR=Thecorrectserver;DB=blue"
sSql = "SELECT " & sCW & sDate & ".Timestamp, "
sSql = sSql & sCW & sDate & ".CallEvent, "
sSql = sSql & sCW & sDate & ".CallEventName, "
sSql = sSql & sCW & sDate & ".CallID, "
sSql = sSql & sCW & sDate & ".TelsetLoginID, "
sSql = sSql & sCW & sDate & ".AssociatedData, "
sSql = sSql & sCW & sDate & ".Destination, "
sSql = sSql & sCW & sDate & ".EventData, "
sSql = sSql & sCW & sDate & ".Source, "
sSql = sSql & sCW & sDate & ".Time " & vbCrLf
sSql = sSql & "FROM blue.dbo.eCallByCallStat" & sDate & " " & sCW & sDate & vbCrLf
sSql = sSql & " ORDER BY " & sCW & sDate & ".Timestamp"
Set oQT = ActiveSheet.QueryTables.Add(Connection:=sConn, Destination:=Range("A1"), Sql:=sSql)
oQT.Refresh BackgroundQuery:=False
Do While oQT.Refreshing = True
Loop"
When I run this I get an odd error message at oQT.Refresh BackgroundQuery:=False
Oddly enough it worked for a month or so then just died
# loopo
I actually added the "" to the connection string and actually have the user name and password hard coded into the query with out quotes, I have since removed them for clarity in the posting
The error I recieve is
Run-time error '-2147417848(80010108)':
Method 'Refresh" of Object "_QueryTable' Failed
Thanks for your input Kevin. The Database is never in a state where no one is accessing it, it is a Call Handling system that is on 24 x 7 and always connected to is clients. At least that is my understanding. If I do this manually through Excel I never get an error, or have any issues only when I am doing this via a macro does it give me issues which lead me to think that it was my code causing the issue.
I am connecting to the database via ODBC as recommended by the manuafacturer, but I wonder if they ever envisioned this sort of thing.
I will see if I can leverage this into a .NET project and see if that helps.
Seems like an error with the query itself...
If you can step through your code and post the contents of sSql, it would probably help troubleshoot...
When you go through it, be sure quotes are getting escaped properly.
Looks like your connection string has double quotes in it.
This could potentially be due to some parsing by the website
you should probably set sConn using "double double" quotes, as in:
sConn = "ODBC;DSN=Aus1S002;UID=""somevaliduser"";PWD=""avalidpassword"";SRVR=""Thecorrectserver"";DB=blue"
What is the actual error message you're getting?
In the FROM clause, are you trying to SELECT from 2 different tables, with the same name in different namespaces? (In which case I think they should be separated by a comma rather than a space)
Or is there supposed to be another '.' instead of the space in the FROM clause? Or is it an alias?
Do you need to specify the table for every field? why not just do:
SELECT Timestamp, CallEvent, ... ,Time
FROM blue.dbo.eCallByCallStat" & sDate & " ORDER BY Timestamp
First off, if you're connecting to a non-generic database (SQL Server, Oracle, etc.), try using a database connection that's specific to it.
Secondly, since you said this error comes and goes, can you test whether it still happens when no one else is accessing the system? Perhaps it is an issue with certain rows being locked while your query is trying to read them...
Third, either switch to a different reporting method or find a different way to get the data. There are limits to this type of call within Excel. While, yes, it certainly does allow you to connect to databases and pull in data, you may find it falling short if you're working with large sets of data, complex queries, or finicky database connections.
I start by deleting the contents of sSQL with sSql=""
after that, because the query is run in a for loop I build the query in each of the next lines, each line builds on the previous line, I made it that way so it would be easier to edit and understand by the next guy.
After running through the sSQL looks like this
sSQL=SELECT eCallByCallStat20081001.Timestamp, eCallByCallStat20081001.CallEvent,
eCallByCallStat20081001.CallEventName, eCallByCallStat20081001.CallID,
eCallByCallStat20081001.TelsetLoginID, eCallByCallStat20081001.AssociatedData,
eCallByCallStat20081001.Destination, eCallByCallStat20081001.EventData,
eCallByCallStat20081001.Source, eCallByCallStat20081001.Time FROM
blue.dbo.eCallByCallStat20081001 eCallByCallStat20081001 ORDER BY
eCallByCallStat20081001.Timestamp
I was having this same issue when trying to refresh a Query.
For some reason that I don't know. When refering to a QueryTable object the refresh only works the first time you run the vba code. If you run it again the runtime error will prompt Run-time error '-2147217842(80040e4e): Method 'Refresh' of object '_QueryTable' failed occurs
This is an example of a Query refresh that fails.
Ws.ListObjects("TableName").QueryTable.Refresh BackgroundQuery:=False
Here is the solution found.
ThisWorkbook.Connections("ConnectionName").Refresh
If someone knows the reason why the refresh method of the QueryTable object fails. please let us know.