In Access VBA, Find field name, insert column into table - sql

I am trying to create a new table where the field name in the source file is a variable. For example, the ID field in the source data could be "ID" or "HB_REF_NO", Date of birth may be DoB, Date of Birth or Date_of_birth
I've made a code that searches for various field names and returns the column they are in but am struggling to transfer the data from those columns into a table
Here is the code, please excuse its no doubt brutish methodology...
Private Sub cmdCompare_Click()
Set db = CurrentDb()
Set RecordSet1 = db.OpenRecordset("OriginalData")
Dim Fld As DAO.Field
Dim FldArray() As String
Dim i As Integer
Dim j As Integer
Dim SQLCreate As String
Dim SQLInsert As String
Dim s As Integer
Dim d As Integer
Dim b As Integer
Dim p As Integer
j = RecordSet1.Fields.Count - 1
ReDim FldArray(j)
'Assigns field names to the array
For Each Fld In RecordSet1.Fields
FldArray(i) = Fld.Name
i = i + 1
Next
For i = 0 To j
If FldArray(i) = "Surname" Then
s = i
Else
End If
Next
For i = 0 To j
If FldArray(i) = "HB_REF_NO" Then
d = i
Else
End If
Next
For i = 0 To j
If FldArray(i) = "NC_DATE_OF_BIRTH" Then
b = i
Else
End If
Next
For i = 0 To j
If FldArray(i) = "POSTCODE" Then
p = i
End If
Next
SQLCreate = "CREATE TABLE OriginalComp" & _
"(ID varchar(255), Surname varchar(255), DoB varchar(255), Postcode varchar(255))"
DoCmd.RunSQL SQLCreate
SQLInsert = "INSERT INTO OriginalComp (ID, Surname, DoB, Postcode) " & _
"VALUES ('" & FldArray(d) & "','" & FldArray(s) & "','" & FldArray(b) & "','" & FldArray(p) & "');"
DoCmd.RunSQL SQLInsert
End Sub

It would be simpler to examine the source table's TableDef.Fields collection and find the current names for each of your variable field names. You don't need to open the table as a Recordset and you don't need to use an array.
This example will find and use a birth date field whose name matches either *Dob* or *Date*Birth*. (If more than one field in the table could match those patterns, you'll need to substitute patterns which are more selective.)
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim fld As DAO.Field
Dim strDateOfBirth As String
Dim strInsert As String
Set db = CurrentDb
Set tdf = db.TableDefs("OriginalData")
For Each fld In tdf.Fields
With fld
If .Name Like "*DoB*" Or .Name Like "*Date*birth*" Then
strDateOfBirth = .Name
End If
End With
Next
If Len(strDateOfBirth) > 0 Then
strInsert = "INSERT INTO OriginalComp (ID, Surname, DoB, Postcode) " & _
"SELECT HB_REF_NO, Surname, [" & strDateOfBirth & "], POSTCODE " & _
"FROM OriginalData;"
Debug.Print strInsert '<- inspect this in Immediate window; Ctrl+g will take you there
db.Execute strInsert, dbFailOnError
Else
MsgBox "Birth date field not found!"
End If
Extend that example to deal with the HB_REF_NO vs. ID field.

The problem is here:
SQLInsert = "INSERT INTO OriginalComp (ID, Surname, DoB, Postcode) " & _
"VALUES ('" & FldArray(d) & "','" & FldArray(s) & "','" & FldArray(b) & "','" & FldArray(p) & "');"
The FldArray variable is a list of all of the column names, so the dth entry will be the dth column name, which is why you are inserting column names instead of values!
If you want to insert into OriginalComp those values then why not do:
Private Sub cmdCompare_Click()
Set db = CurrentDb()
SQLCreate = "CREATE TABLE OriginalComp" & _
"(ID varchar(255), Surname varchar(255), DoB varchar(255), Postcode varchar(255))"
DoCmd.RunSQL SQLCreate
SQLInsert = "INSERT INTO OriginalComp (ID, Surname, DoB, Postcode) " & _
"SELECT HB_REF_NO, Surname, NC_DATE_OF_BIRTH, POSTCODE " & _
"FROM OriginalData"
DoCmd.RunSQL SQLInsert
End Sub

Related

Variable is crossing different events

Apologies for the vague title, but here is my issue. I have a form that has several select lists and associated text boxes. Basically the way it works is if you select a name from the first list, an AfterUpdate event is triggered to query the DB to see if the Eng_ID and Person_ID already exist in the table. If so, then delete that row then insert the updated row. If there is not any records, then just insert the data. The problem is that when I click a name in the first list, then move to the second list, what's happening is that the the Person_ID of the first list is used for the DLookup query, then it delets the record, then inserts the record of the new person I selected in a different listbox. The code is below: Thanks in advance
' Add/Remove Participant 1
Private Sub lstPar1_AfterUpdate()
Dim n As Integer
Dim strCriteria As String
Dim strSQL As String
With Me.lstPar1
For n = .ListCount - 1 To 0 Step -1
strCriteria = "Eng_ID = " & Nz(Me.Eng_ID, 0) & " And Person_ID = " & .ItemData(n)
If .Selected(n) = False Then
' If a person has been deselected, then delete row from table
If Not IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
strSQL = "DELETE * FROM tblEngParRole WHERE " & strCriteria
CurrentDb.Execute strSQL, dbFailOnError
End If
Else
' If a person has been selected, then insert row into the table
If IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
strSQL = "INSERT INTO tblEngParRole (Eng_ID, Person_ID, ParticipantNumber, Role)" & "VALUES(" & Me.Eng_ID & "," & .ItemData(n) & "," & 1 & ",'" & Me.txtParRole1.Value & "' )"
CurrentDb.Execute strSQL, dbFailOnError
End If
End If
Next n
End With
End Sub
' Add/Remove Participant 2
Private Sub lstPar2_AfterUpdate()
Dim n As Integer
Dim strCriteria As String
Dim strSQL As String
With Me.lstPar2
For n = .ListCount - 1 To 0 Step -1
strCriteria = "Eng_ID = " & Nz(Me.Eng_ID, 0) & " And Person_ID = " & .ItemData(n)
If .Selected(n) = False Then
' If a person has been deselected, then delete row from table
If Not IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
strSQL = "DELETE * FROM tblEngParRole WHERE " & strCriteria
CurrentDb.Execute strSQL, dbFailOnError
End If
Else
' If a person has been selected, then insert row into the table
If IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
strSQL = "INSERT INTO tblEngParRole (Eng_ID, Person_ID, ParticipantNumber, Role) " & "VALUES(" & Me.Eng_ID & "," & .ItemData(n) & "," & 2 & ",'" & Me.txtParRole2.Value & "' )"
CurrentDb.Execute strSQL, dbFailOnError
End If
End If
Next n
End With
End Sub
Using this image, if I select Daniel and enter his role, then the eng_ID, Person_ID, ParticipantNumber and Role are entered into the database as 130, 118, 1, Collaborator.
If I select Kristin, it deletes Daniel becuause it's still using Person_ID of 118 instead of hers which is 134, and since there is a corresponding record, it delets Daniel then adds Kristin.
I don't have Access to test this with, but it seems like you need to separate Participant1 records from Participant2 records when you perform your DLookups.
Also you can generalize your code by pulling the common parts into a separate sub.
Private Sub lstPar1_AfterUpdate()
CheckParticipant Me.lstPar1, 1, Me.txtParRole1.Value
End Sub
Private Sub lstPar2_AfterUpdate()
CheckParticipant Me.lstPar2, 2, Me.txtParRole2.Value
End Sub
Sub CheckParticipant(objList As Object, participantNum As Long, role As String)
Dim n As Integer
Dim strCriteria As String
Dim strSQL As String
With objList
For n = .ListCount - 1 To 0 Step -1
strCriteria = "Eng_ID = " & Nz(Me.Eng_ID, 0) & " And Person_ID = " & .ItemData(n) & _
" And ParticipantNumber=" & participantNum
strSQL = ""
If Not .Selected(n) Then
' If a person has been deselected, then delete row from table
If Not IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
strSQL = "DELETE * FROM tblEngParRole WHERE " & strCriteria
End If
Else
' If a person has been selected, then insert row into the table
If IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
strSQL = "INSERT INTO tblEngParRole (Eng_ID, Person_ID, ParticipantNumber, Role)" & _
" VALUES(" & Me.Eng_ID & "," & .ItemData(n) & "," & participantNum & _
",'" & role & "' )"
End If
End If
If Len(strSQL) > 0 Then CurrentDb.Execute strSQL, dbFailOnError
Next n
End With
End Sub

How to auto-increment primary key in SQL INSERT INTO statement

Private Sub btnAddInfo_Click()
On Error GoTo Error_Routine
'Declare variables
Dim intStudentID As Integer
Dim intTestID As Integer
Dim dblMark As Double
Dim intResultID As Integer
'Declare database
Dim db As DAO.Database
Dim rst As DAO.Recordset
'Set the database
Set db = CurrentDb
Set rst = db.OpenRecordset("Select ResultId FROM StudentResult ORDER BY RESULTID DESC", dbOpenDynaset)
'assign value to intResultID variable
intResultID = rst!ResultId
'Adds the additional 1 to the latest result id that was used
If Not rst.EOF Then
intResultID = intResultID + 1
End If
'Assigns value to variables
intStudentID = Forms!frmAdd!lstStudentID
strDescription = Forms!frmAdd!lstTest
dblMark = txtMark.Value
intTestID = Forms!frmAdd!lstTest
'Checks that Student ID has been selected
If Not IsNull(lstStudentID) Then
'Inserts new test record into StudentResult table
db.Execute "INSERT INTO StudentResult " _
& "(ResultId,StudentId,TestId, Mark) VALUES " _
& "('" & intResultID & "','" & intStudentID & "','" & intTestID & "','" & dblMark & "');"
End If
'Clears fields
txtMark.Value = ""
lstStudentID.Value = ""
lblExistingStudent.Caption = "Existing Student Name:"
'Closes database
Set db = Nothing
I'm trying to add new records. There is a list of 4 tests. ResultId is the primary key and it is an AutoNumber column.
The button adds tests scores just fine if the selected StudentID has not added a score for that TestId yet. But when I try to add a StudentId and TestId combination that has been entered before, it does not add a new record or even update the existing one.
Both StudentId and TestId allow duplicates. I've tried doing this counter variable but it has not worked. This is for a class and the professor says a student should be able to retake tests and it should just add a new record.
Thank you in advance for your help. Please let me know if you need any pictures of the form, tables, or more of my code.
Exclude the AutoNumber field, and don't wrap numbers in quotes:
If Not IsNull(lstStudentID) Then
' Verify values:
Debug.Print "StudentID:", intStudentID, "TestID:", intTestID, "Mark:", Str(dblMark)
'Inserts new test record into StudentResult table
db.Execute "INSERT INTO StudentResult " _
& "(StudentId, TestId, Mark) VALUES " _
& "(" & intStudentID & "," & intTestID & "," & Str(dblMark) & ");"
End If

Multiple Record Insertion in Microsoft Access through VB

I've created DB within Access and given Data Type "Short Text."
Now I'm trying to prompt record into this table through Visual Basic. I wrote a code so far but need help to fix an error. I'm getting the compile error:
Duplicate declaration in current scope
I can't figure it out what it is?
Option Compare Database
Sub arrayData()
Dim CustomerName() As Variant
Dim num As Integer, dbs As Database, InsertRecord As String
Dim CustomerID As Long, num1 As Long, CustomerName As String
Set dbs = CurrentDb()
CustomerID = 0
For num1 = 0 To 49999
CustomerID = CustomerID + 1
CustomerName = Array("Peter", "Mary")
CustomerAddress = Array("163 City Rd, SOUTHBANK", "65 Orange St, BENTLEIGH EAST")
CustomerPhoneAddress = Array("0416874963", "0478937534")
num = Int((200 - 0 + 1) * Rnd + 0)
CustomerName = CustomerName(num)
CustomerAddress = CustomerAddress(num)
CustomerPhoneNo = CustomerPhoneNo(num)
InsertRecord = "INSERT INTO Customers (CustomerID,CustomerName,CustomerAddress,CustomerPhoneNo) VALUES (" & "'" & CustomerID & "'" & "," & "'" & CustomerName & "'" & "," & "'" & CustomerAddress & "'" & "," & "'" & CustomerPhoneNo & "'" & ")"
dbs.Execute InsertRecord
Debug.Print CustomerID, CustomerName, CustomerAddress, CustomerPhoneNo
Next
End Sub
What can I do in this situation? Any help would be appreciated.
The language you are using is "Visual Basic for Applications" (VBA). This language is line-oriented. It menas that one statement must fit on one single line, unless you are using a line continuation character (_) preceeded by at least one whitespace.
Dim CustomerID As Long, num1 As Long, CustomerName As String, CustomerAddress _
As String, CustomerPhoneNo As String
But I would place the Long and String variables on separate lines and write:
Dim CustomerID As Long, num1 As Long
Dim CustomerName As String, CustomerAddress As String, CustomerPhoneNo As String
The second syntax error is in the InsertRecord = "INSERT INTO ... statement. same problem here. It shoul look like this:
InsertRecord = "INSERT INTO CUSTOMERS (CustomerID,CustomerName," _
& "CustomerAddress,CustomerPhoneNo) VALUES " _
& "(" & "'" & CustomerID & "'" & "," & "'" & CustomerName & "'" & "," & "'" _
& CustomerAddress & "'" & "," & "'" & CustomerPhoneNo & "'" & ")"
Also, what are the - 0 and + 0 good for in Int((200 - 0 + 1) * Rnd + 0). The expression is equivalent to Int(201 * Rnd).
After your edits it seems that you have no line continuations.
THE ERROR IS: You have 2 variables named CustomerName. Variable names must be unique:
Dim CustomerName() As Variant
Dim CustomerName As String
For instance, name the array CustomerNames:
Dim CustomerNames() As Variant
And you should indent your code. It makes it much easier to read.
Sub arrayData()
Dim CustomerName() As Variant
...
CustomerID = 0
For num1 = 0 To 10
CustomerID = CustomerID + 1
...
Debug.Print CustomerID, CustomerName, CustomerAddress, CustomerPhoneNo
Next
End Sub

Generate INSERT INTO statements in MS-Access

I like to export data (single records) from one Access database to another one in another country. The idea is that I want to send a text file with INSERT INTO statements per email and the receiving PC just executes these INSERT INTO statements. I wrote already the code to read and execute the INSERT INTO statements in these text files.
Obviously I have to generate the INSERT INTO statements.
Here is an example.
I have the following table:
Table1
Id number
PersonName text
DoB date, can be empty
NumberOfChildern number, can be empty
I select the data like this:
SELECT Id, PersonName, DoB, NumberOfChildern FROM Table1;
What I want to generate are statements like this:
INSERT INTO Table1 (Id, PersonName, DoB, NumberOfChildern ) VALUES (1, ‘Peter’, #5-17-1990#, 1)
If all fields are always filled in then I could write one time the code and that's it. But there is a problem if a couple of fields might contain data or maybe no data.
Here are some similar but different versions of the above statement:
INSERT INTO Table1 (Id, PersonName, DoB, NumberOfChildern ) VALUES (1, ‘Peter’, #5-17-1990#, 1)
INSERT INTO Table1 (Id, PersonName, NumberOfChildern ) VALUES (1, ‘Peter’, 1)
INSERT INTO Table1 (Id, PersonName, DoB ) VALUES (1, ‘Peter’, #5-17-1990#)
INSERT INTO Table1 (Id, PersonName ) VALUES (1, ‘Peter’)
With just two fields which can contain NULL values there are already 4 different versions of this statement and with more fields it becomes more and more complicated (not really complicated but more work).
I think about writing code in VBA which analyzes the table and the records which I want to export to check which kind of fields are used (i.e. date) and then generate statements like above.
I am sure I can do this but I wonder if maybe others did this before.
I don't want to reinvent the wheel.
But searching for "generate SQL insert statements" is not really efficient.
Any ideas?
It's your lucky day. I have done this for SQL Server - with a few modifications done below it should work for Access SQL.
The key is to insert VALUES NULL, not create different statements if values are null.
The SET IDENTITY_INSERT ON/OFF probably isn't needed for Access.
Gustav has posted a generic function that can replace all Sqlify/SqlDate etc. helper functions and covers more data types.
Public Sub InsertStatementsSql(ByVal sTABLE As String)
Dim DB As DAO.Database
Dim TD As DAO.TableDef
Dim RS As DAO.Recordset
Dim fld As DAO.Field
Dim sKpl As String
Dim sStart As String
Dim sValues As String
Dim S As String
Dim v As Variant
Dim i As Long
Dim bIdentity As Boolean
Set DB = CurrentDb
Set TD = DB.TableDefs(sTABLE)
Set RS = DB.OpenRecordset(sTABLE, dbOpenSnapshot)
' Check for Autonumber/IDENTITY column
bIdentity = False
For i = 0 To TD.Fields.count - 1
If (TD.Fields(i).Attributes And dbAutoIncrField) > 0 Then
bIdentity = True
Exit For
End If
Next i
If bIdentity Then
sKpl = sKpl & "SET IDENTITY_INSERT " & sTABLE & " ON;" & vbCrLf & vbCrLf
End If
' "INSERT INTO ... VALUES " for every line
For i = 0 To TD.Fields.count - 1
sStart = StrAppend(sStart, TD.Fields(i).Name, ", ")
Next i
sStart = "INSERT INTO " & sTABLE & " (" & sStart & ") VALUES "
' One line per record
Do While Not RS.EOF
sValues = ""
For i = 0 To TD.Fields.count - 1
v = RS(i)
If IsNull(v) Then
S = "NULL"
Else
Set fld = TD.Fields(i)
Select Case fld.Type
Case dbText, dbMemo: S = Sqlify(CStr(v))
Case dbDate: S = SqlDate(CDate(v))
Case dbDouble, dbSingle: S = SqlNumber(CDbl(v))
Case Else: S = CStr(v)
End Select
End If
sValues = StrAppend(sValues, S, ", ")
Next i
' Append line to full SQL
sKpl = sKpl & vbCrLf & sStart & " (" & sValues & ");"
RS.MoveNext
Loop
RS.Close
Set TD = Nothing
If bIdentity Then
sKpl = sKpl & vbCrLf & vbCrLf & "SET IDENTITY_INSERT " & sTABLE & " OFF;" & vbCrLf
End If
Debug.Print sKpl
' see https://support.microsoft.com/en-us/kb/210216 or https://msdn.microsoft.com/en-us/library/office/ff192913.aspx
' or https://stackoverflow.com/a/25431633/3820271
'ClipBoard_SetData sKpl
End Sub
' ------------------- helper functions -----------------
' ein'string --> 'ein''string'
Public Function Sqlify(ByVal S As String) As String
S = Replace(S, "'", "''")
S = "'" & S & "'"
Sqlify = S
End Function
Public Function SqlDate(vDate As Date) As String
SqlDate = "#" & Format(vDate, "yyyy-mm-dd") & "#"
End Function
Public Function SqlNumber(num As Double) As String
SqlNumber = Replace(CStr(num), ",", ".")
End Function
Public Function StrAppend(sBase As String, sAppend As Variant, sSeparator As String) As String
If Len(sAppend) > 0 Then
If sBase = "" Then
StrAppend = Nz(sAppend, "")
Else
StrAppend = sBase & sSeparator & Nz(sAppend, "")
End If
Else
StrAppend = sBase
End If
End Function

VBA macro in Excel to Run SQL Insert statement

Hey im quite new to VBA and I was hoping someone could help me with last bit of code.
I am trying to take cells from a spreadsheet and add them to a SQL table but I am having trubble running the SQL statement. Here is the code I have so far.
Private Sub ConnectDB()
Dim oConn As Object
Set oConn = CreateObject("ADODB.Connection")
oConn.Open = "DRIVER={SQL Server};" & _
"SERVER=SERVER02;" & _
"DATABASE=platform;" & _
"USER=5y5t3mus3r;" & _
"PASSWORD=*******;" & _
"Option=3;"
If oConn.State = adStateOpen Then
MsgBox "Welcome to Database!"
Else
MsgBox "Sorry No Database Access."
End If
Dim rs As ADODB.Recordset
Dim strSQL As String
Dim Company As String
Dim Address As String
Dim Address1 As String
Dim Address2 As String
Dim County As String
Dim Contact As String
Dim Phone As String
Dim Fax As String
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFile _
& ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
Sheets("wsheet").Activate
Set rs = New ADODB.Recordset
rs.Source = Sql
With wsheet
MyFile = "C:\Users\Ryan.ICS\Documents\Documents\InsertStatement.txt"
fnum = FreeFile()
Open MyFile For Output As fnum
myRow = 2
myCol = 4
For myRow = 2 To InputBox(Prompt:="What is the last row of data?", Title:="Data Row", Default:=1)
myCol = 4
Company = ActiveSheet.Cells(myRow, myCol)
myCol = myCol + 1
Address = ActiveSheet.Cells(myRow, myCol)
myCol = myCol + 1
Address1 = ActiveSheet.Cells(myRow, myCol)
myCol = myCol + 1
Address2 = ActiveSheet.Cells(myRow, myCol)
myCol = myCol + 1
Address3 = ActiveSheet.Cells(myRow, myCol)
myCol = myCol + 2
Phone = ActiveSheet.Cells(myRow, myCol)
myCol = myCol + 1
Fax = ActiveSheet.Cells(myRow, myCol)
myCol = myCol + 1
strSQL = "INSERT INTO [sandbox].[5y5t3mus3r].[ryan] (Organisation, Address1, Address2, TownCity, County, Telephone, Fax) VALUES('" & Company & "', '" & Address & "', '" & Address1 & "', '" & Address2 & "', '" & Address3 & "', " & Phone & ", " & Fax & ");"
Print #fnum, strSQL
DoCmd.RunSQL strSQL ***Here is where I am haveing an error it will not run the SQL command.****
oConn.Execute strSQL **** here is another tag I tried in a number of different ways but i still couldnt get the SQL statement to run
Next
End With
' Find out how many rows were affected by the Insert.
Set rs = oConn.Execute("Select ##rowcount")
' Display the first field in the recordset.
MsgBox rs(0) & " rows inserted"
oConn.Close
Set rs = Nothing
Set oConn = Nothing
Close #fnum
End Sub
Function esc(txt As String)
esc = Trim(Replace(txt, "'", "\'"))
End Function
The error arises when I am trying to run the SQL statement do I need to create an object or method for this or something.
Any help with this would really be appreciated thanks!
I'd guess it's this line:
rs.Source = Sql
The Source property accepts an IStream as well as a string, so since Sql isn't declared anywhere, it's implicitly an object with a value of Nothing.
My next guess is a couple of lines below that, where does wsheet get assigned?
Of course, all this would be easier if we knew which line the error occurs on... easier still if you set a break point and step into the code -- you don't need to dump variable values to file, you can view them interactively in the debugger.
Instead of using the INSERT statement, I would suggest creating a stored procedure and passing values into it using the ADOBO.Command object.