I have two table one (skillsMatrix) the other table is (elementTree) with columns [mediumElement], [ID] in table skillsMatrix the mediumElement is a lookup dropdown of the mediumElements in table two. I want to write a macro to update skills matrix table to add a new record “name”, “new topic”,”” and not duplicate any of the other records when a new mediumElement is added to elementTree.
Table: skillsMatrix
id | employee | mediumElement | completionDate |
---|---|---|---|
autoNumber | Dave | Walking | 10/27/2020 |
Table: elementTree
Id | mediumElement |
---|---|
26 | Walking |
27 | Running |
I’d like the skillsMatrix table to look like this after running the code
id | employee | mediumElement | completionDate |
---|---|---|---|
autoNumber | Dave | Walking | 10/27/2020 |
autoNumber | Dave | Running |
I have tried the following to troubleshoot for building out the logic. The following prints out with RS always starting with 1 and ME starting with the proper ID for the mediumElement in element tree.
rs
1
ME
26
rs
2
ME
27
rs
3
ME
28
rs
4
ME
29
rs
5
ME
30
rs
6
ME
31
rs
7
ME
32
rs
8
ME
33
rs
9
ME
34
rs
10
ME
35
Dim db As DAO.Database Dim rs As DAO.Recordset Dim mediumElements As DAO.Recordset Dim employeeTable As DAO.Recordset Dim strSQL As String Dim strSQLName As String Dim strSQLintegrityCheck As String Dim idValue As Long Dim recordExists As Boolean If Me.Dirty = True Then Me.Dirty = False 'Save any unsaved data Set db = CurrentDb strSQLName = "SELECT employeeTable.ID, employeeTable.[Employee Name] FROM employeeTable WHERE (((employeeTable.[Employee Name])=""" & Me.employeeName & """));" Set employeeTable = db.OpenRecordset(strSQLName) idValue = employeeTable.Fields("ID") Debug.Print (idValue) strSQLintegrityCheck = "Select skillsMatrix.employee, skillsMatrix.mediumElement From skillsMatrix Where skillsMatrix.employee = " & idValue & "" Set rs = db.OpenRecordset("skillsMatrix") strSQL = "Select elementTree.[ID], elementTree.[mediumElement] From elementTree Where ( elementTree.plantPosition = " & Me.jobPosition & ")" 'Debug.Print strSQL Set mediumElements = db.OpenRecordset(strSQL) Debug.Print employeeTable.Fields("ID") If Not mediumElements.BOF And Not mediumElements.EOF Then mediumElements.MoveFirst rs.MoveFirst While (Not mediumElements.EOF) Debug.Print ("rs") Debug.Print rs.Fields("mediumElement").Value Debug.Print ("ME") Debug.Print mediumElements.Fields("id") If (rs![employee] <> employeeTable.Fields("ID") And rs![mediumElement] <> mediumElements.Fields("ID")) Then With rs .AddNew ![employee] = employeeTable.Fields("ID") ![mediumElement] = mediumElements.Fields("ID") .Update End With End If rs.MoveNext mediumElements.MoveNext Wend End If rs.Close Set rs = Nothing Set mediumElements = Nothing Set employeeTable = Nothing
Nothing happens/wrong thing happens as the rs.Fields(“mediumElement”) does not give the what I would expect as the correct value. Instead of rs.[mediumElement] displaying the lookup ID of element from the elementTree table it always displays 1 through number of records in RS for rs.Fields(“mediumElement”). There is an employees table and the IDs are being saved in skillsMatrix. Although I used the lookup wizard when building the connections so that could be the problem. I apologize for my poor vernacular I’m pretty new to access and SQL.
I do not want all employees to be updated with the associated new element. The code is a sub controlled by a button press and the employee to be updated is selected on that form with the control employeeName
EDIT: On of the suggestion looking into Insert Select
the following works for adding the mediumElements to the skills matrix table, based on whether or not they exist for a user. Is there a way to also add the employee name to the skills matrixTable with the same Insert Into?
Dim sqlString As String Dim name As String Dim strSQLName As String Dim db As DAO.Database Set db = CurrentDb Dim employeeTable As DAO.Recordset strSQLName = "SELECT employeeTable.ID, employeeTable.[Employee Name] FROM employeeTable WHERE (((employeeTable.[Employee Name])=""" & Me.employeeName & """));" Set employeeTable = db.OpenRecordset(strSQLName) idValue = employeeTable.Fields("ID") Debug.Print (name) sqlString = "INSERT INTO skillsMatrix (mediumElement)" _ & "SELECT elementTree.ID FROM elementTree " _ & "WHERE NOT EXISTS(SELECT * FROM skillsMatrix Where skillsMatrix.mediumElement = elementTree.ID AND skillsMatrix.employee = " & idValue & " ) " DoCmd.RunSQL sqlString End Sub
Advertisement
Answer
If employee is selected via a combobox on form, there is no need to open a recordset just to get employee ID. EmployeeID should be a hidden column of combobox and combobox should have that as its value.
idValue = Me.employeeName
If Employee ID is not available on form, a recordset is still not needed. Use DLookup.
idValue = DLookup("ID", "employeeTable", "[Employee Name]='" & Me.employeeName & "'")
Include employee field in INSERT clause and concatenate idValue to produce a calculated field in the SELECT from elementTree clause.
sqlString = "INSERT INTO skillsMatrix (employee, mediumElement) " _ & "SELECT " & idValue & " AS Emp, elementTree.ID FROM elementTree " _ & "WHERE NOT EXISTS(SELECT * FROM skillsMatrix WHERE skillsMatrix.mediumElement = elementTree.ID AND skillsMatrix.employee = " & idValue & " ) "
If employee and mediumElement are defined as a compound index in table, then don’t really need the WHERE criteria since duplicate pairs will not be allowed. I don’t know if this WHERE criteria slows or improves performance.
If new element ID can be captured from form, simplify code:
sqlString = "INSERT INTO skillsMatrix (employee, mediumElement) " _ & "VALUES(" & idValue & "," & idElement & ")"
Use CurrentDb.Execute
instead of DoCmd.RunSQL
and won’t get warning popups.