I'm working on a simple billing program for my father in law and the Access database is not updating. I built the connection and query inside of a try catch block but the database still won't update outside of it. I know it's probably something simple but I just can't see it. What am I missing?
'Database Connection
Dim Connection As String = "Provider=Microsoft.Jet.OLEDB.4.0; User ID=Admin; Data Source =MBPDatabase.mdb;"
Dim MBP As New OleDb.OleDbConnection(Connection)
MBP.Open()
Dim sqlJob As String
sqlJob = "INSERT INTO Jobs ([jobID], [jobClients], [jobName], [jobPrice])
VALUES("",#jobClients,#jobName,0.00)"
Dim Job As New OleDb.OleDbCommand(sqlJob, MBP)
Job.Parameters.Add(New OleDb.OleDbParameter("jobClients", txtClient.Text))
Job.Parameters.Add(New OleDb.OleDbParameter("jobName", txtJobName.Text))
Job.ExecuteNonQuery()
MBP.Close()
The problem is most likely the double qoute for jobID after the VALUES-keyword.
This leads to the following result (one double qoute):
...VALUES(",#jobClients,#jobName,0.00)
Change it to this (two single quotes):
sqlJob = "...VALUES('',#jobClients,#jobName,0.00)"
Related
I need a method that will let me keep my MSaccess database open throughout the application operation instead of opening and closing everytime i enter data.
Currently Dim provider As String Dim dataFile As String Dim connString As String Dim myConnection As OleDbConnection = New OleDbConnection Dim cmd As New OleDbCommand
is public declared in each form . And the following is declared on private class
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source="
dataFile = "C:\Program Files (x86)\SACCO\SACCO_DB.accdb"
connString = provider & dataFile
myConnection.Open()
Dim str As String
str = "INSERT INTO STAFF([ID_NO],[FULL_NAME],[EMAIL],[PASSWORD]) Values(?,?,?,?)"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
This makes my application slower. Kindly, may someone guide me on how i will keep the database open on startup and closed on exit.
yes, this is a long time known issue - and we see near weekly postings about how LARGE delays can occur when opening the database. So for that 20+ years on a NEAR DAILY basis, from Access Front ends to back ends, the solution has been to force + keep a persistent connection. I can make a long post about how and why this occurs, but it has to do with the windows file system - and thus a open of the file, and Access attempting to open exclusive as it attempts to flip the use of the file into high speed single user mode can cause REALLY large delays. As noted, force and to keep the connection open is the near daily advice we see here for close to 20 years.
So, ok, we now using vb.net?
Simply declare a global var in a standard code module as public. Then in your startup code, you can do 1 of two things:
Open the database object - that means you don't have to know ahead of time to "pick" a particlar table to open.
eg this:
Imports System.Data.OleDb
Module MyGlobalCode
Public gDBCon As OleDbConnection ' global connection object
Public Sub GlobalOpenDatabase()
gDBCon = New OleDbConnection(My.Settings.TESTAce)
gDBCon.Open
End Sub
Public Sub GlobalCloseDatabase()
gDBCon.Close()
End Sub
End Module
So, now in any and all code? You use the above gDBCon and you:
Don't have to create a new connection object over and over.
You eliminate this LONG time known slow opening issue.
Now, it not clear why this big delay does NOT occur on some networks and setup - but, if it is occurring, then the above will show spectacular improvements in performance. Often the issue is even virus scanning software, and sometimes it seems to do with Active Directory. And other times, it has to do with VERY slow file creating times (each time you open the database, a ".ldb" file is also created - the time to create this file can be quite long on some systems - again a forced open connection will eliminate your software speeds being limited by external forces such as AD, or virus software, or a good number of other issues that causes this issue.
I am trying to change the links in an Access 2016 database, but the method I've used in the past is not working as required.
I am using the
t.connect="new connection"
t.refreshlink
method, where t is a the table.
I have seen in the linked table manager that the tables are now grouped by a data source. I can create the new source and link it to the desired table, but I have many as migrating, so would like to do this in code.
I get no errors the current way, but immediately after the .refreshlink the table's .connect is still the same.
Is this still possible?
I currently populate a dictionary with the table name and it's existing connection, but only if non ODBC.
I am then looping through this dictionary, getting the table and changing its connection
CurrentDb.TableDefs(strTableName).Connect = strNewConnection
CurrentDb.TableDefs(strTableName).RefreshLink
Debug.Print CurrentDb.TableDefs(strTableName).Connect
Existing connection = ;DATABASE=\\app01\Access\CRM_Data.mdb
New connection =;DATABASE=C:\CRM_TEST\CRM_DATA_BE_2016.accdb
Many thanks
You should not use CurrentDb.TableDefs when changing tables, as that changes between calls and makes the reference to the tabledef where you change the connection string be a different one than the one where you refresh the link.
Dim d As DAO.Database
Set d = CurrentDb
d.TableDefs(strTableName).Connect = strNewConnection
d.TableDefs(strTableName).RefreshLink
AFAIK this behaviour is not version-dependent, so the code you provided should never have worked.
I am using this code in Access 2016 and it works just fine:
Public Function RelinkTables(environment As Integer)
On Error Resume Next
Dim tblDef As DAO.TableDef
For Each tblDef In CurrentDb.TableDefs
If tblDef.Connect <> "" Then
tblDef.Connect = GetConnectionString(environment)
tblDef.RefreshLink
End If
Next
End Function
Public Function GetConnectionString(environment As Integer) As String
Select Case environment
Case 1 ' connection to Test db
GetConnectionString = "your connection string to Test"
Case 2 ' connection to Prod db
GetConnectionString = "your connection string to Production"
End Select
End Function
If this would not work with your db than may be the path is wrong.
I am currently self learning (2 weeks) vb with visual studio 2015 express.
I am trying to import selected data from an access database to a datagridview. I want to write that data inside sqllite database.
My code is shown below. It works but I am not sure if the transaction is set up correctly. Also I am not sure if I have to use a transaction when writing to the sqllite DB. The operation seems slow and I think that it could be quicker.
Do I have the transaction set up correctly?
My code is:
Dim con As String = "Data Source=C:\clients.db;Version=3;"
Dim sqConnection As New SQLiteConnection(con)
Dim sqCommand As New SQLiteCommand()
sqCommand.Connection = sqConnection
Dim myTrans As SQLiteTransaction '= sqConnection.BeginTransaction()
sqConnection.Open()
' Start a local transaction
myTrans = sqConnection.BeginTransaction()
' Assign transaction object for a pending local transaction
sqCommand.Transaction = myTrans
Try
sqCommand.CommandText = "INSERT INTO Clients (Registered, Name, Number, Details) VALUES (#Registered, #Name, #Number, #Details)"
sqCommand.Parameters.AddWithValue("#Registered", row.Cells(1).Value)
sqCommand.Parameters.AddWithValue("#Name", row.Cells(2).Value)
sqCommand.Parameters.AddWithValue("#Number", row.Cells(3).Value)
sqCommand.Parameters.AddWithValue("#Details", row.Cells(4).Value)
sqCommand.ExecuteNonQuery()
myTrans.Commit()
Application.DoEvents()
Finally
sqConnection.Close()
End Try
I have looked at various questions/replies which left me even more confused. I am getting nowhere fast and seem to be going in circles.
You do not have to use a transaction to add a record to the database. I would use a transaction when you are doing something that preforms multiple operations on the database. If for some reason something goes wrong during the process the transaction can roll back the changes to the database
Resolved I moved the myTrans.Commit() to just before the End Sub and now the insert is twice as fast..
I am new to this forum, please could you help me get this code to work, when i execute it, it simply does nothing and does not update the DB. If i remove the square brackets it gives an error: "SYNTAX ERROR in UPDATE statement"
Any help appreciated!
Dim connection As OleDbConnection
connection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=UserDB.accdb;Jet OLEDB:Database;")
connection.Open()
Dim pass As String
pass = txtconfirm.Text
Dim user As String
user = LoginForm.UsernameTextBox.Text
Dim query As String = "UPDATE [Users] SET [Password]= '" & pass & "' WHERE [Username]= '" & user & "';"
Dim command As New OleDbCommand(query, connection)
command.ExecuteNonQuery()
connection.Close()
Given your actual connection string, the database that will be updated is the one in the directory where your application starts. This means that if you work with a WinForms application this folder is \BIN\DEBUG or x86 variant. If there is not error then you could get the return value of the ExecuteNonQuery call to verify if a record has been updated or not
Dim rowsUpdated = command.ExecuteNonQuery()
MessageBox.Show("Record updated count = " & rowsUpdated)
If this value is not zero then your database has been updated and you are looking for changes in the wrong database. Check the one in the BIN\DEBUG folder.
In any case your code has big problems. If your variables user or pass contain a single quote, then your code will crash again because your string concatenation will form an invalid SQL. As usual the only workaround is to use a parameterized query
Dim pass = txtconfirm.Text
Dim user = LoginForm.UsernameTextBox.Text
Dim query As String = "UPDATE [Users] SET [Password]= #p1 WHERE [Username]= #p2"
Using connection = New OleDbConnection("...........")
Using command As New OleDbCommand(query, connection)
connection.Open()
command.Parameters.Add("#p1", OleDbType.VarWChar).Value = pass
command.Parameters.Add("#p2", OleDbType.VarWChar).Value = user
command.ExecuteNonQuery()
End Using
End Using
The parameterized approach has many advantages. Your query text is more readable, there is no misunderstanding between your code and the values expected by your database engine. And while not easy to exploit with MS-Access there is no problem with Sql Injection
I think Steve presents a much better approach for you coding this...
Let me just throw out a few more things:
The reason you can't take those brackets out is some of your column names are reserved words; just FYI.
Since you report "it does nothing..." when you execute, it sounds like you have a valid connection and sql syntax, in which case my next step would be to copy the sql command text while in debug mode, change it to a select and run it in your DB. You should get one result when you do. If not, either your criteria or field contents are not what you think they are...
Just change the Update table SET field-value ... to SELECT * FROM table and leave the WHERE clause as is.
I'm following code I found on another site. Here's the basics of my code:
Dim SQL As String
Dim connString As String
connString = "ODBC;DSN=DB01;UID=;PWD=;Database=MyDatabase"
SQL = "Select * from SomeTable"
With Worksheets("Received").QueryTables.Add(Connection:=connString, Destination:=Worksheets("Received").Range("A5"), SQL:=SQL)
.Refresh
End With
End Sub
The problem with doing this is every single time they hit the button assigned to this it creates a new connection and doesn't ever seem to drop it. I open the spreadsheet after testing and there are many versions of the connection listed under Connections.
Connection
Connection1
Connection2
I can't seem to find a way to close or delete the connections either. If I add ".delete" after ".Refresh" I get a 1004 error. This operation cannot be done because the data is refreshing in the background.
Any ideas how to close or delete the connection?
You might ask yourself why you're creating a QueryTable every time in your code. There are reasons to do it, but it usually isn't necessary.
QueryTables are more typically design-time objects. That is, you create your QueryTable once (through code or the UI) and the you Refresh the QueryTable to get updated data.
If you need to change the underlying SQL statement, you have some options. You could set up Parameters that prompt for a value or get it from a cell. Another option for changing the SQL is changing it in code for the existing QueryTable.
Sheet1.QueryTables(1).CommandText = "Select * FROM ...."
Sheet1.QueryTables(1).Refresh
You can select different columns or even different tables by changing CommandText. If it's a different database, you'll need a new connection, but that's pretty rare.
I know that doesn't answer your question directly, but I think determining whether you really need to add the QueryTable each time is the first step.
For more on Parameters, see http://dailydoseofexcel.com/archives/2004/12/13/parameters-in-excel-external-data-queries/ It's for 2003, so there are few inconsistencies with later versions. The basics are the same, you just may need to learn about the ListObject object if you're using 2007 or later.
I had the same issue. The previous answer while a definite step in the right direction is a PITA.
It did however allow me to refine my search and the winner is...
http://msdn.microsoft.com/en-us/library/bb213491(v=office.12).aspx
i.e. for your existing QueryTable Object just do this:
.MaintainConnection = False
Works ever so swell. No more Access DB lock file after the data is refreshed.
You should declare the connection as a separate object then you can close it once the database query is complete.
I don't have the VBA IDE in front of me, so excuse me if there are any inaccuracies, but it should point you in the right direction.
E.g.
Dim SQL As String
Dim con As connection
Set con = New connection
con.ConnectionString = "ODBC;DSN=DB01;UID=;PWD=;Database=MyDatabase"
Worksheets("Received").QueryTables.Add(Connection:=con, Destination:=Worksheets("Received").Range("A5"), SQL:=SQL).Refresh
con.close
set con = nothing
I've found that by default new connections created this way are called "Connection". What I am using is this snippet of code to remove the connection but retain the listobject.
Application.DisplayAlerts = False
ActiveWorkbook.Connections("Connection").Delete
Application.DisplayAlerts = True
It can easily be modified to remove the latest added connection (or if you keep track of the connections by their index).
Application.DisplayAlerts = False
ActiveWorkbook.Connections(ActiveWorkbook.Connections.Count).Delete
Application.DisplayAlerts = True
Instead of adding another query table with the add method, you can simply update the CommandText Property of the connection. However you have to be aware that there is a bug when updating the CommandText property of an ODBC connection. If you temporarily switch to an OLEDB connection, update your CommandText property and then switch back to ODBC it does not create the new connection. Don't ask me why... this just works for me.
Create a new module and insert the following code:
Option Explicit
Sub UpdateWorkbookConnection(WorkbookConnectionObject As WorkbookConnection, Optional ByVal CommandText As String = "", Optional ByVal ConnectionString As String = "")
With WorkbookConnectionObject
If .Type = xlConnectionTypeODBC Then
If CommandText = "" Then CommandText = .ODBCConnection.CommandText
If ConnectionString = "" Then ConnectionString = .ODBCConnection.Connection
.ODBCConnection.Connection = Replace(.ODBCConnection.Connection, "ODBC;", "OLEDB;", 1, 1, vbTextCompare)
ElseIf .Type = xlConnectionTypeOLEDB Then
If CommandText = "" Then CommandText = .OLEDBConnection.CommandText
If ConnectionString = "" Then ConnectionString = .OLEDBConnection.Connection
Else
MsgBox "Invalid connection object sent to UpdateWorkbookConnection function!", vbCritical, "Update Error"
Exit Sub
End If
If StrComp(.OLEDBConnection.CommandText, CommandText, vbTextCompare) <> 0 Then
.OLEDBConnection.CommandText = CommandText
End If
If StrComp(.OLEDBConnection.Connection, ConnectionString, vbTextCompare) <> 0 Then
.OLEDBConnection.Connection = ConnectionString
End If
.Refresh
End With
End Sub
This UpdateWorkbookConnection subroutine only works on updating OLEDB or ODBC connections. The connection does not necessarily have to be linked to a pivot table. It also fixes another problem and allows you to update the connection even if there are multiple pivot tables based on the same connection.
To initiate the update just call the function with the connection object and command text parameters like this:
UpdateWorkbookConnection ActiveWorkbook.Connections("Connection"), "exec sp_MyAwesomeProcedure"
You can optionally update the connection string as well.
If you want to delete if right after refresh you should do the refresh not in the background (using first parameter -> Refresh False) so that you have proper sequence of actions
Try setting the QueryTable.MaintainConnection property to False...
"Set MaintainConnection to True if the connection to the specified data source is to be maintained after the refresh and until the workbook is closed. The default value is True! And there doesn't seem to be a UI check box for this (Read/write Boolean)"
Still relevant years later...battling the same issue and this is the most helpful thread out there. My situation is a variant of the above and I will add my solution when I find it.
I am using an Access database for my data source and establish a querytable on a new sheet. I then add two more new sheets and try to establish a querytable using the same connection on each of them, but to a different Access table. The first querytable works just fine and I use .QueryTables(1).Delete and setting the querytable object to Nothing to make it disconnected.
However, the next sheet fails on establishing a new querytable using the same connection, which was not closed. I suspect (and will add the solution below) that I need to drop the connection before deleting the querytable. Rasmus' code above looks like the likely solution.