Append CSV file to existing Access table - csv

I have an Access database with a ton of tables, forms, and queries in it. With one of my forms I have an upload button that I would like to use for appending csv files to a specific table in the database.
I have an OnClick function for the button that I am getting hung up on..
Every time it get to the line
adoCSVConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strPathToTextfile & ";" & _
"Extended Properties=""text;HDR=YES;FMT=Delimited"""
It says that: the provider cannot be found or it is not installed properly..
Does this have anything to do with the settings in the Data Source Admin settings? Am I missing a reference?
Here is all of the code if you are interested in seeing what all I have
Private Sub uploadBTN_Click()
'Dim adoCSVConnection, adoCSVRecordset, strPathToTextfile
'Dim strCSVFile, adoJetConnection, adoJetCommand, strDBPath
Dim adoCSVConnection As ADODB.Connection
Dim adoCSVRecordset As ADODB.Recordset
Dim adoJetConnection As ADODB.Connection
Dim adoJetCommand As ADODB.Command
Set adoCSVConnection = New ADODB.Connection
Const adCmdText = &H1
' Specify path to CSV file. ex: c:\Scripts\
strPathToTextfile = "C:\Desktop\"
' Specify CSV file name. ex: Users.csv
strCSVFile = "testfile2.csv"
' Specify Access database file. ex: c:\Scripts\MyData.mdb
strDBPath = "\\folder\NewMasterclient.mdb"
' Open connection to the CSV file.
Set adoCSVConnection = CreateObject("ADODB.Connection")
Set adoCSVRecordset = CreateObject("ADODB.Recordset")
' Open CSV file with header line.
adoCSVConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strPathToTextfile & ";" & _
"Extended Properties=""text;HDR=YES;FMT=Delimited"""
adoCSVRecordset.Open "SELECT * FROM " & strCSVFile, adoCSVConnection
' Open connection to MS Access database.
Set adoJetConnection = CreateObject("ADODB.Connection")
adoJetConnection.ConnectionString = "DRIVER=Microsoft Access Driver (*.mdb);" _
& "FIL=MS Access;DriverId=25;DBQ=" & strDBPath & ";"
adoJetConnection.Open
' ADO command object to insert rows into Access database.
Set adoJetCommand = New ADODB.Command
Set adoJetCommand.ActiveConnection = adoJetConnection
adoJetCommand.CommandType = adCmdText
' Read the CSV file.
Do Until adoCSVRecordset.EOF
' Insert a row into the Access database.
adoJetCommand.CommandText = "INSERT INTO testfile2" & "(a, b, c, d, clientid, reg) " & "VALUES (" _
& "'" & adoCSVRecordset.Fields("a").Value & "', " _
& "'" & adoCSVRecordset.Fields("b").Value & "', " _
& "'" & adoCSVRecordset.Fields("c").Value & "', " _
& "'" & adoCSVRecordset.Fields("d").Value & "', " _
& "'" & adoCSVRecordset.Fields("clientid").Value & "')" _
& "'" & adoCSVRecordset.Fields("reg").Value & "')"
adoJetCommand.Execute
adoCSVRecordset.MoveNext
Loop
' Clean up.
adoCSVRecordset.Close
adoCSVConnection.Close
adoJetConnection.Close
End Sub

Related

MS Access MDB query with VBScript

I can look up ALL the records from images with a VBScript:
cn.Execute "SELECT * INTO [text;HDR=Yes;Database=" & exportDir & _
";CharacterSet=65001]." & exportFile & " FROM IMAGES"
This works perfectly. However, I want to narrow down that search from all the records to just the ones where column B (ProjectName) == "spoon"
Dim projName
projName = "spoon"
cn.Execute "SELECT * INTO [text;HDR=Yes;Database=" & exportDir & _
";CharacterSet=65001]." & exportFile & " FROM IMAGES" & " WHERE ProjectName=" & projName
But I get the error:
No value given for one or more required parameters.
Mu SQL-fu is weak and not sure where I'm going wrong.
To conclude (and reduce slightly):
Dim projName
projName = "spoon"
cn.Execute "SELECT * INTO [text;HDR=Yes;Database=" & exportDir & _
";CharacterSet=65001]." & exportFile & " FROM IMAGES WHERE ProjectName='" & projName & "'"
As #allen-wang points out the reason for the error is lack of string value being identified as a string by encapsulating it in single quotes ('...').
However this and other issues such as SQL Injection weaknesses can be avoided by using the ADODB.Command to execute a Parameterised Query.
Dim cmd, sql, exportDir, exportFile
'Shouldn't be configurable outside this procedure.
exportDir = "..."
exportFile = "..."
Const adCmdText = 1
Const adParamInput = 1
Const adCmdVarChar = 200
Const adExecuteNoRecords = &H00000080
Set cmd = CreateObject("ADODB.Command")
sql = "SELECT * INTO [text;HDR=Yes;Database=" & exportDir & _
";CharacterSet=65001]." & exportFile & " FROM IMAGES WHERE ProjectName = ?"
With cmd
Set .ActiveConnection = cn
.CommandType = adCmdText
.CommandText = sql
Call .Parameters.Append(.CreateParameter("#ProjName", adVarChar, adParamInput, 255))
Call .Execute(, , adExecuteNoRecords)
End With
Just make sure that both exportDir and exportFile are not exposed or you leave the code open to SQL Injection.

Looping through folder with SQL query

strQuery = _
"SELECT * FROM [Sheet1$A15:E999] " & _
"IN '" & ThisWorkbook.Path & "\Source1.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;ExtendedProperties='HDR=YES;'] " & _
"UNION " & _
"SELECT * FROM [Sheet1$A15:E999] " & _
"IN '" & ThisWorkbook.Path & "\Source2.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"UNION " & _
"SELECT * FROM [Sheet1$A15:E999] " & _
"IN '" & ThisWorkbook.Path & "\Source3.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"ORDER BY A;"
Good morning,
I have one last nail to go on this coding I have and any help is much appreciated. I am gathering numerous files from a single folder and file names are different (although data order and data are same).
Question is:
Is it possible to get all files via the 'strQuery' without slowing down the code? How do I go on to do this? (eg: I think maybe loop but it might slow down? - see below)
Is it possible to get (say) 100 excel file data read at once? (although I do not know names of it?)
I can modify strQuery (via assigning it a text string) and input a loop to go through every file but I recon this would require me to create a connection for every single file rather than all at once?
Any help is appreciated!
Thanks in advance.
--
Full Code below (I didn't know where to put this in a visible manner)
Sub SqlUnionTest()
Dim strConnection As String
Dim strQuery As String
Dim objConnection As Object
Dim objRecordSet As Object, qText As String
strConnection = _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"User ID=Admin;" & _
"Data Source='" & ThisWorkbook.FullName & "';" & _
"Mode=Read;" & _
"Extended Properties=""Excel 12.0 Macro;"";"
Dim sFile As String
sFile = Dir(ThisWorkbook.Path & "\*.xlsx")
Do While sFile <> ""
strQuery = _
"SELECT * FROM [Sheet1$A15:E999] " & _
"IN '" & ThisWorkbook.Path & "\" & sFile & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;ExtendedProperties='HDR=YES;'] " & _
"UNION "
sFile = Dir()
Loop
strQuery = Left(strQuery, Len(strQuery) - 7) 'to remove last UNION which is not necessary
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open strConnection
Set objRecordSet = objConnection.Execute(strQuery)
RecordSetToWorksheet Sheets(1), objRecordSet
objConnection.Close
End Sub
Sub RecordSetToWorksheet(objSheet As Worksheet, objRecordSet As Object)
Dim i As Long
With objSheet
.Cells.Delete
For i = 1 To objRecordSet.Fields.Count
.Cells(1, i).Value = objRecordSet.Fields(i - 1).Name
Next
.Cells(2, 1).CopyFromRecordset objRecordSet
.Cells.Columns.AutoFit
End With
End Sub
You can use the DIR() function to loop through all the .xlsx files in the folder without knowing the specific file names. If you need to weed out any files, you can place conditional testing inside the loop.
Code untested
Dim sFile As String, strQuery As String
sFile = Dir(ThisWorkbook.Path & "\*.xlsx")
Do While sFile <> ""
strQuery = strQuery & _
"SELECT * FROM [Sheet1$A15:E999] " & _
"IN '" & ThisWorkbook.Path & "\" & sFile & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;ExtendedProperties='HDR=YES;'] " & _
"UNION;"
sFile = Dir()
Loop
strQuery = Left(strQuery, Len(strQuery) - 7) 'to remove last UNION which is not necessary

Access SaveAs function with database data

I'm trying to save a template on a specific place. For example, if a product have the GnrSerie = 1000, it should go to that folder, and then the if the Gnr = E2000, it should go to that folder and then name the file GnrSerie + "-" + Gnr.
I use the following code to save the file:
.SaveAs "CAN'T SHOW THIS\" & rst![GnrSerie] & "\" & rst![Gnr] & "\" & rst![GnrSerie] & "-" & rst![Gnr], wdFormatDocument
Further more, I am connected to the databases/tables where GnrSerie and Gnr is placed
Dim rst As DAO.Recordset
Dim sql As String
Dim db As Database
Set db = CurrentDb
sql = "SELECT * FROM Projektdata WHERE Sagsnr Like '*" & Forms!Sag_Form!SagNr & "*'"
Set rst = db.OpenRecordset(sql, dbOpenDynaset)
When I run it, it just pops up and ask me where I want to save the file.
You probably will have to specify the drive as well:
.SaveAs "D:\CAN'T SHOW THIS\" & rst![GnrSerie] & "\" & rst![Gnr] & "\" & rst![GnrSerie] & "-" & rst![Gnr], wdFormatDocument

Access VBA to update Access table from SQL Server table source

I have created the code below to test whether I can run a query and retrieve a data from an SQL server table. And so far I can return the result using a MessageBox, but somehow I just don't know how to use this connection to update the table inside this Access file. Basically I want to use this as a front end file. Then, when the form is open it will automatically update the table inside this access file and load the data to the combo box as a list. I tried searching it here and read many discussions here and in Google but currently I can't find the right solution.
Option Compare Database
Sub LocalServerConn_Test()
Set conn = New adodb.Connection
Set rst = New adodb.Recordset
strDBName = "DataSet"
strConnectString = "Provider = SQLOLEDB.1; Integrated Security = SSPI; " & _
"Initial Catalog = " & strDBName & "; Persist Security Info = True; " & _
"Worksation ID = abc123;"
conn.ConnectionString = strConnectString
conn.Open
strSQL = "SELECT DISTINCT dbo.abc.abc123 FROM dbo.abc"
rst.Open Source:=strSQL, ActiveConnection:=strConnectString, _
CursorType:=adOpenDynamic, LockType:=adLockOptimistic
If rst.RecordCount = 0 Then
MsgBox "No records returned"
Else
rst.MoveFirst
Do While Not rst.EOF
MsgBox rst.Fields("abc123").Value
rst.MoveNext
Loop
End If
conn.Close
rst.Close
End Sub
You should be able to use code very similar to this:
Dim cdb As DAO.Database
Set cdb = CurrentDb
cdb.Execute _
"DELETE FROM LocalTable", _
dbFailOnError
cdb.Execute _
"INSERT INTO LocalTable (abc123) " & _
"SELECT DISTINCT abc123 " & _
"FROM " & _
"[" & _
"ODBC;" & _
"Driver={SQL Server};" & _
"Server=.\SQLEXPRESS;" & _
"Database=DataSet;" & _
"Trusted_Connection=yes;" & _
"].[dbo.abc]", _
dbFailOnError
Set cdb = Nothing
You can just keep the combo box bound to [LocalTable] and the updated values from the SQL Server table should appear.

VB.net update query is not giving errors and not updating my sql database

Dim conntps As MySqlConnection
Dim myconnstringtps As String
conntps = New MySqlConnection()
Dim mycommand As New MySqlCommand
Dim Updatepayments As String = "update payments set payments.payorname='" & _
epayorname.Text & "', payments.cardnumber='" & eccnumber.Text & _
"', payments.bankname='" & ebankname.Text & "', payments.checkaccountnumber='" & _
eaccountnumber.Text & "', payments.checkroutingnumber='" & _
erouting.Text & "', payments.cardexpirationdate='" & eexpmonth.Text & "/" & _
eexpireyear.Text & "', payments.cardexpirationmonth='" & _
eexpmonth.Text & "', payments.cardexpirationyear='" & eexpireyear.Text & _
"', payments.cardaddress='" & eaddy.Text & "', payments.cardzipcode='" & _
ezip.Text & "', payments.threedigitnumber='" & ecvv.Text & _
"' where payments.filenumber='" & TextBox1.Text & "' and paymentstatus='PENDING';"
myconnstringtps = "server=localhost; user id=root; " & _
"password=1C0cac0la; database=collectionsmax"
Try
conntps.Open()
Try
mycommand.Connection = conntps
mycommand.CommandText = Updatepayments
mycommand.ExecuteNonQuery()
conntps.Close()
mycommand.Dispose()
Catch myerror As MySqlException
MsgBox("error connecting:" & myerror.Message)
End Try
Catch myerror As MySqlException
MsgBox("error connecting:" & myerror.Message)
Finally
If conntps.State <> ConnectionState.Closed Then conntps.Close()
MsgBox("Successfully Changed")
End Try
I am not getting any errors or exceptions when attempting to run the code.
I have tried to output the generated update query to a text box and running the code though mysql management studio, and it works perfectly. so im pretty sure its not an issue with the actual query being sent to the server.
I have used almost this exact same code to do insert into statements with no issues.
It is not updating the database when the code is ran through my VB.net application using the above outlined code.
You don't set the connection string in the MySqlConnection
myconnstringtps = "server=localhost; user id=root; password=1C0cac0la;......"
conntps = New MySqlConnection(myconnstringtps)
apart from that, you need to use parametrized query to avoid problems with single quotes inside your strings and the Sql Injection Attack security problem
Dim Updatepayments As String = "update payments " & _
"set payments.payorname=#name," & _
"payments.cardnumber=#cnum," & _
"payments.bankname=#bank," & _
"payments.checkaccountnumber=#actnum," & _
"payments.checkroutingnumber=#routing," & _
"payments.cardexpirationdate=#monthyear," & _
"payments.cardexpirationmonth=#month," & _
"payments.cardexpirationyear=#year," & _
"payments.cardaddress=#address," & _
"payments.cardzipcode=#zip," & _
"payments.threedigitnumber=#digits " & _
"where payments.filenumber=#file and paymentstatus='PENDING'"
Dim mycommand As New MySqlCommand(Updatepayments, conntps)
mycommand.Parameters.AddWithValue("#name", epayorname.Text)
mycommand.Parameters.AddWithValue("#cnum", eccnumber.Text)
mycommand.Parameters.AddWithValue("#bank", ebankname.Text)
mycommand.Parameters.AddWithValue("#actnum", eaccountnumber.Text);
mycommand.Parameters.AddWithValue("#routing", erouting.Text)
mycommand.Parameters.AddWithValue("#monthyear", eexpmonth.Text & "/" & eexpireyear.Text)
mycommand.Parameters.AddWithValue("#month", eexpmonth.Text)
mycommand.Parameters.AddWithValue("#year", eexpireyear.Text)
mycommand.Parameters.AddWithValue("#address", eaddy.Text)
mycommand.Parameters.AddWithValue("#zip", ezip.Text)
mycommand.Parameters.AddWithValue("#digits", ecvv.Text)
mycommand.Parameters.AddWithValue("#file", TextBox1.Text)
Other problematic point: Are you sure that your fields are all of string type? You pass for every field a string and surround the value with single quotes. This could fail if someone of your fields are not of string type. (these fields in particular could be not of string type payments.cardnumber, payments.checkaccountnumber, payments.cardexpirationmonth,payments.cardexpirationyear,payments.threedigitnumber)
Use command parameters. This makes it both safer (SQL injection) and easier to handle.
Dim Updatepayments As String = "UPDATE payments SET payments.payorname=#1, " & _
"payments.cardnumber=#2, ..." & _
"WHERE payments.filenumber=#11 AND paymentstatus='PENDING';"
mycommand.Parameters.AddWithValue("#1", epayorname.Text);
mycommand.Parameters.AddWithValue("#2", eccnumber.Text);
...
You can also use parameter names like #epayorname with SQL-Server but some connection types (like ODBC) only allow positional parameters.
Red alert You are obviously dealing with credit card information here and yet you are leaving yourself and your customers vulnerable to SQL injection attacks!
Also you have a password in your code that you posted on the public Internet!
(And Steve seems to have the right answer.)