I have an Access database with a many-to-many relation. The origin table is called Property and the destination table is called Person. A property can have more than one owner, and a person can own more than one property. I created a join table to accommodate this M-M relationship.
Here is the relationship layout:
In order to fill these tables, I created a form for Property with a subform for the Person table. I followed several articles and posts to implement the needed functionality. They are here, here, here and here.
Here is the form:
The PersonName is a combo box with its row source set to the following SQL query:
SELECT Person.idPerson, Person.PersonName FROM Person;
The column count is set to 2 and the width is set to 0cm;1cm
The VBA code I used for the NoInList event of the combo box is:
Private Sub PersonName_NotInList(NewData As String, Response As Integer)
strSQL = "INSERT INTO Person([PersonName]) " & _
"VALUES ('" & NewData & "');"
DoCmd.SetWarnings False
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True
MsgBox "The new person has been added to the list." _
, vbInformation, "Data Entry"
Response = acDataErrAdded
End Sub
Everything is working fine so far but I'm faced with the case where two persons have the same name. The form won't allow this as every time you type a name that is already in the table, predictably you get the existing values associated with this person. Creating a new entry in the Person table makes this entry visible in the form's combo box, but I don't want the data entry user to edit the tables.
How can I implement the functionality to create a new entry in the Person table from the form, while asking the user to confirm the new entry?
P.S. I know the question title doesn't specifically reflect the content, but I couldn't find a better wording for it.
Edit: To keep the question simple, I trimmed down the fields in the tables. There are additional attributes like date of birth that can possibly differentiate between two persons with the same name.
A recommended approach is to popup a form to add the new person to the person table. Your immediate problem of not being able to add the person is probably because you have the [PersonName] field either set as the primary key in the person table or you have that field set as an index duplicates not allowed.
I recommend that you consider looking up information on data normalization. This will help with understanding Primary and Foreign Keys.
I had a similar problem recently. I second the suggestion with the popup form. My problem seems to be similar to the problem you have. Access doesn't like adding things on the one side of a relationship when the many side already has entries.
To second what acr_scout has said: You can simply add a button on your form that opens another form.
Create a form that allows you to enter new persons to the persons table.
In design view of your original form, add a button. In Access 2016, this should just be the one just called "button" (there are other buttons) Access will then start a wizard, and there is an option to select the on-click procedure that opens a form of your choosing.
I just tried it out, it worked flawlessly and no VBA coding was necessary. You can also create a toggle button and add custom OnClick procedure yourself, if you so choose.
Another, less elegant approach might be to include a subform for the persons table in your original form.
EDIT: For what you are doing, no vba code should be ncessary, if I understood your problem correctly. Dr. Gerard Verschuuren has a great tutorial on YouTube, which helped me greatly when creating many-to-many forms.
Related
With my limited knowledge of Access, I have been struggling to figure this one out.
I have 4 tables. tblJobDetails, tblDrawings, tblDrawingFixtureType and tblFixtureType. They are related to each other in that order.
What I have been trying to do is a query based from tblFixtureType. I want my users to have a datasheet where they can input all the fixture types for the given job, but keep them under that particular JobID. I have not had much luck in that department. All queries I have made either show every single type entered in the DB, or nothing.
The JobID is the PK for tblJobDetails and is a FK in tblDrawings. tblDrawingFixtureType is intermediate/junction table that is meant to hold quantities, but has DrawingID and TypeID as its FK's.
So how would I correctly build a query for my users to input all fixture types (designations), but keep them assigned/filtered under that particular JobID?
I am sure more info will probably be needed, so please ask.
You don't build a query to solve this problem. What you do is build a form based on each separate table.
In Access you model the parent to child relationships by using form + sub-form combos.
So, you might have a form that say lists out job (continues form).
You click on a row, and then launch a form with a nice display of the job details, and then in the sub form, you allow entry of tblDrawings.
The sub form will hook up the FK. And to edit/select the tblDrawingFixtureType, that drives a combo box in that sub form to select the fixture type, and it will save the PK of FixtureType in the one column.
All and any of each form (or even the sub form) is to be based on ONE table, and NOT a query. You don't edit data in tables, you build a form based on the table. If there is child records to add to that one record, then you build a sub form (and again, that sub form is based on ONE table).
Not only does this mean you don't have to create any queries, but you also don't have to write any code since when using a form + sub form, you get editing of related data that way.
I apologize for probably silly question, but I've already dont know which words to use for searching what i need. I have the good programming experience but am pretty new to Access.
I have a form with the controls, also it has a subform with read-only list of people contacts. This list is populated by a dynamic query from multiple tables, so i don't know in design-time the count and names of all fields. The user wants to be able to manually pick up several contacts from the list to send them a single e-mail.
I used to a table control allows user to select multiple records (usually with ctrl). But it turned out that in Access datasheet the continuous selection is only allowed.
Then I thought of adding editable checkbox column to a readonly table, where the user would be able to mark the desired rows. But I have not found a way how to do this in Access. It seems that the method Append in Fields collection is available only for tables and indexes, but not for queries or recordsets.
I have also read advice to get rid of the subform, and display data in listbox with property multiselect = extended. But in this case, the user will lose the benefits of the table: he can't move and resize columns, sort and filter data.
I have a feeling that the decision should be very simple, I just do not know the conventional way of how to implement this functionality in Access. Help me please.
This is doable by utilizing the RecordsetClone property of the sub form. Here is an example:
Sub GetSelectedValue()
Dim rs as Recordset
Dim sContact as String
Set rs = Me.[SubFormName Goes Here].Form.RecordsetClone
rs.MoveFirst
rs.Move Me.[SubFormName Goes Here].Form.SelTop - 1
sContact = rs![Recordset Column Name Goes Here]
Set rs = Nothing
End Sub
You can put this on the main form via a button control that takes the active row contact and places that name into a listbox on your main form. Once the user has made all their choices, you can then run your e-mail program off the names within the listbox.
If you want a datasheet (for filter, sort, resize), then an editable checkbox is really your only option.
The column can be part of the original table, or create a join table with ID and check column, where you add the IDs from all records of your base table.
In the subform you can set all controls except the checkbox to Locked = True.
I have a JoinTable, Table1 and Table2. Here is design (example):
JoinTable:
IDx
IDy
Table1:
IDx
Names
Surnames
Table2:
IDy
Address
City
Now, I will create a form, which will have a Recordsource of JoinTable. In this form I will have 2 combobox-es, from which I will select records from Table1 or Table2. Based on combobox selection (that's IDx or IDy), I want to see field values from related table....Example:
If I select from combobox IDx, I want to see in continuos form field values from Table2 under same record (which are joined in JoinTable).
I have managed to do this with subforms, but I have a lot of records that are joined in JoinTable under same ID's, so listing through subforms is not nice when there is a lot of matches, because subform's don't maximize when form is maximized (I tried this too with Iszoommed API, but It's still not good - screen flashes because of scrollbars appearing/dissapearing).
Does anybody have any idea on how I could navigate through records of both tables within same form, and without subforms so that I can maximize form and see all related records easily ?
You do this in Access using sub-forms.
As for design issues, you could maybe use other code (I found some nice ideas googling ms access subform auto resize), but the flashes would probably stay there: Access, as all Office applications, does not support multi-threading, OS will have to halt GUI process in order to allow other processes run, and user sees 'flashes'.
I have solved It. What you must do is a little hard to explain, but in general:
When you create a form that has recordsource from JoinTable - you have to build a recordsource query that contains both ID's from your JoinTable and then all other fields from related tables that you desire to have a look to.
On this form you add fields from those 2 tables that are linked in JoinTable. If desired you can hide/unhide those fields based on what search you would like to do (via combobox for each table or something else).
Then you have to VBA code It, my solution is like this - I have put 2 option buttons on form. When one of them is selected, a combobox is shown and fields from table that will be searched (other combobox and fields from other table are hidden at that time). Code goes something like this (for upper example):
Dim SQL As String
SQL = "SELECT JoinTable.IDx, JoinTable.IDy, Table1.Names, Table1.Surnames" & _
" FROM Table1 INNER JOIN JoinTable ON Table1.[IDx] = JoinTable.[IDx] " & _
" WHERE JoinTable.IDx=" & Me.MyCombo
If IsNull(MyCombo) = True Then
Me.RecordSource = ""
Else
Me.RecordSource = SQL
End If
Put this code in Combobox_After_Update and in Click_Event of Option buttons, and that's It. Now you can navigate through related (joined) records within one form with fields from related tables, using ID's of JoinTable and related tables and without subforms so you can maximize your form as you wish.
I'm sure this has been answered somewhere but I don't know how to ask the question such that I can find an answer.
I'm trying to create a form that can allow me to select a person from one table. The table contains SSN, and First, Last, Middle names. I have that part working.
What I don't yet understand how to do is then populate a group of textboxes and labels on the form with the column headers of a second table.
It should populate with everything but the ID and SSN fields and put that person's information (a selection of dates) in the text boxes to be edited.
Sadly, I've already accomplished this in Excel, but due to runtime issues, I'm trying to port it over to Access, since the dataset is getting larger daily, and Excel is no longer well suited for the task.
I don't have enough rep to post an image into this post, so please go here to see a visual representation of what I'm talking about.
Thanks for the help!
For the list of header, you could loop through the RecordSet field name: rst.Fields(n).Name of a Select * query of you table.
You could then use the field selected by the user to build a second query for you last column that match the good user and the right header such has:
StrSql = " Select " & MySelectedField & " From MyTable where userID = " & MySelectedUser &";"
Hope this helps!
This is complicated. I'm not too familiar with Access and I am a programmer (meaning, I might be making this harder on myself and not seeing the "easy" answer).
So let's consider (example):
We have a library database thing. I have a specific copy of a book. My book can have several status: checked out, on shelf, destroyed, smells weird/sticky/out of commission.... I need/have two forms in Access. One for basic info on my book and one to actually update the status. With a status change there's a significant amount of data that needs to be recorded so this requires a seperate form. The book form itself just consists of basic information and a small sub form for rental history; the book form needs to include current status. My actual status table has a statusid, bookid, timestamp.
Now... since I didn't know Access would have an issue with it... I left both my book and status forms unbound and filled them with a recorset/query from VBA. But then it yelled at me when I tried to connect the two; "unbound" it told me. I decided that's fine and moved the query over to the actual front end Access Query section (to the left) and out of the vba and bound my forms appropriately. BUT NOW. It says my record set is not updateable. I assume because I used joins and nested select statements and such to get the current status for the book. I just need to be able to modify those text fields and I can write the insert/update whatever myself. I found a few things on the net saying to create a table but I also read that doesn't work in a multiuser environment. When the book form is open and the user clicks a button to change the status of my book and the saves/closes that status form I do need to be able to requery the book form to show the updated status.
So... What do I do?
If I understand you correctly your problem is that you have a complicated query in the mainform and want to open a second form to update one underlying table of that query, then want to change the current record in the newly opened form and save it and then requery the original form?
I understand you are a programmer, so the most versatile way to do this seems to me:
Button on the mainform that opens the new form in modal modus with the correct record (that ensures that the rest of the original forms code executes after the modal form is closed), do your magic in the modal form, then requery the mainform.
Try something like this:
Private Sub myButton_Click()
DoCmd.OpenForm "myEditForm", acNormal, , ID = 4, acFormEdit, acDialog
me.requery
End Sub