• My NotInList Code Creates a New Record

    Home » Forums » AskWoody support » Productivity software by function » MS Access and database help » My NotInList Code Creates a New Record

    Author
    Topic
    #470900

    In another thread, John Hutchison gave me this code for the NotInList event of combo boxes (it takes what I typed in the combo box, and if it is not in the list of entries for that field, offers to add it). When it adds that new entry to the list it creates a new record.

    This works fine as long as this only comes up once on a form. But, if it comes up two or more times, say if I have a combo box for last names, it will create one new record when I add a new first name to the list, and a second new record when I add a new last name to the list.

    My form does not do this if I choose a first name from the drop down list in its combo box, and a last name from the drop down name in its combo box.

    I can see why this is happening (the rs.AddNew execute every time the function runs), but I’m not sharp enough yet to get that line to execute only when the record is actually new.

    Private Sub cboFirstName_NotInList(NewData As String, Response As Integer)
    If fnAddRecord(“tblPersons”, “firstName”, “first names”, NewData) = True Then
    Response = acDataErrAdded
    Else
    Response = acDataErrContinue
    End If
    End Sub

    Public Function fnAddRecord(strTable As String, strfield As String, strtitle As String, NewData As String) As Boolean
    Dim newEntry As Integer, Title As String, msgDialog As Integer
    Const MB_YESNO = 4
    Const MB_ICONEXCLAMATION = 48
    Const MB_DEFBUTTON1 = 0, IDYES = 6, IDNO = 7

    Title = strtitle & ” not in list”
    msgDialog = MB_YESNO + MB_ICONEXCLAMATION + MB_DEFBUTTON1
    newEntry = MsgBox(NewData & ” is not in the list of ” & strtitle & “. Do you want to add a new entry to the list ?”, msgDialog, Title)
    If newEntry = IDYES Then
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim sql As String
    Set db = CurrentDb
    sql = “Select * from ” & strTable
    Set rs = db.OpenRecordset(sql, dbOpenDynaset)
    rs.AddNew
    rs(strfield) = StrConv(NewData, 3)
    rs.Update
    rs.Close

    Set db = Nothing
    Set rs = Nothing
    fnAddRecord = True
    Else
    fnAddRecord = False
    End If

    End Function

    Viewing 19 reply threads
    Author
    Replies
    • #1238422

      Does your form have two combo boxes that draw data from the same table?

      My code example, which was the simplest of many versions, is really only applicable where the lookup table has only one field of relevance. If you are adding people to a list, you should add first and lastname at the same time.
      Also if you are choosing people with a combo, you would usually use just one combo box, bound to a personID field, but displays first and last names concatenated. So it would have two columns, but the first column width would be 0, and the second column would display Person: [firstname] & ” ” & [lastname].

      An On Not in List event in that case would be more complicated. It would have to split the newdata into two fields (splitting at the space) then create the new record automatically, or open a form with the fields filled in so you could check the data before adding the new record.

    • #1238455

      1) Yes, my form has multiple combo boxes that point to the same table.

      2)

      [indent]My code example, which was the simplest of many versions, is really only applicable where the lookup table has only one field of relevance. [/indent]

      Agreed.

      [indent]If you are adding people to a list, you should add first and lastname at the same time.
      Also if you are choosing people with a combo, you would usually use just one combo box, bound to a personID field, but displays first and last names concatenated. So it would have two columns, but the first column width would be 0, and the second column would display Person: [firstname] & ” ” & [lastname].[/indent]

      Perhaps so. I tried to program this but could not get it to work. I am also not sure if this makes the most sense if I have a secretary entering data – I was thinking it would be more straightforward for a novice to put a first name in one (combo) box and a last name in another (combo) box. The table is now organized with firstName and lastName as different fields, and I’d rather not have to change that.

      3) I am not following your last paragraph. Does it refer to your suggestion from the second paragraph, or to your understanding of how my tables are set up from your first paragraph? Either way, I’m confused by it.

      I am not sure that my trouble is not from applying how I would do this in other languages that I know better. To me, it seems like the easy solution is to pull the creation of the new record out into an if/else that captures whether or not I just created a record. But I think I am going down the wrong road in VBA if I try to do it this way.

    • #1238470

      When you connect tables you should always connect via the primary keys. So if you have a table of people (tblpeople with personID as they key), any other tables that refer to people should only store the personID. I have done this hundreds of times, then used a single combo to choose the person.

      If you use two combo boxes you could easily choose a combination of first and lastnames that do not belong any real person. To avoid this you would need to restrict the second combo to values consistent with what was selected in the first.

      My last paragraph referred to a situation where the user has typed “John Brown” into a combo, and you want the VBA to split this into John and Brown, create a new person record and put John into firstname and Brown into lastname.

    • #1238519

      I think my db is in line with your methodology.

      The problem I am having is that my data entry person is finding my data entry process to be kludgy. I am about 2 weeks out from having to deal with more than 1 part time data entry person instead of 1 full time person. I am taking the full time person’s usability suggestions very seriously in preparation for that.

      My form does refer to a single personID from tblPersons. But the people’s names are broken into different fields: firstName, middleName, and so on.

      I want the ability to create a new person’s record by choosing from the lists in the combo boxes – I have a lot of shared first and last names.* This seemed to me like the best way to get my data entry person to reduce errors. Perhaps this was a bad way to go.

      But, I also want the data entry person to be able to add new people whose names are not in the fields yet, and so are not populated to the combo boxes. My data entry person likes being able to use the drop down list to see if the “new” person really is new. A data entry method based on the “List Items Edit Form” property works fine, but my data entry person doesn’t like this because they have to type the data into the combo box before it fires, and the retype it again in the form that pops open. I tend to agree that there ought to be a better way to do this. Perhaps my solution is really a set of directions on my form that says check the drop-down list before you start typing?

      Alternatively, I could probably do what we want with the following: a combo box and a text box side-by-side, using the combo box only to look up whether someone is already on the list and make a choice if they are, and a text box to allow an addition to the list if the name isn’t in the combo box. This seems inefficient to me, and error-prone, but maybe I’m wrong.

      * Where I’m going with this is that I have external sources that I have to exchange information with that might call me “David”, “David Ralph”, “D.”, “D.R.”, and “David R.”. Each of those might be connected to projects in a many-to-many junction table. For each person I have this problem, so my tblPersons has a unique ID for each person with a single preferred formal name, that I connect with a one-to-many where all their aliases are on the many side, and then I connect that to a many-to-many which matches projects to the specific alias that is listed on its title page. I didn’t invent all the aliases, but I do have to produce reports that combine them all into one person, and different reports that list them as if they were separate people.

    • #1238521

      It also occurred to me that the best way to go might be to have the “List Items Edit Form” set to be the same thing for each of the combo boxes (cboFirst, cboMiddle, cboLast). That way if the data entry person types into one of the boxes and fires the edit form, they have to fill out all the fields on the edit form, and then when they go back to the combo boxes on the original form they’re already populated. Is this how this is supposed to work?

    • #1238543

      If you do have a single personID field then how is that populated?
      If it is attached to any of the combo boxes (and there now seem to be three) then once you choose from the first combo, the other two combos are redundant.

      For people I tend not to use “Not in list events” because:

        [*]Just because someone’s name is in the list does not mean it is actually the same person. There can be two different John Browns.[*]You need to make a decision based on more data.[*]When you add a new person, I usually want to add a lot of extra data such as address, phone numbers , email etc.

      One solution is to use unbound controls for the user to enter a firstname and lastname, then do a search to see if anyone matches, then act on the results of the search.

    • #1238546

      The issues are expanding …

      1) I think you’re first 2 paragraphs have unearthed a problem. When I change the record at the bottom of the form, all the combo boxes update to match, but when I change the datum in one of the combo boxes, the other two don’t update. What do you mean by “attached”.

      2) I actually have 2 classes of people: those that I need a lot of info for, and those that I just need a name. Perhaps I should use a List Items Edit Form.

      3) I think we are on the same page about an unbound control. Do you mean to have an unbound control to look up whether someone is in the DB, and a bound one to add new people?

    • #1238572

      I have gone with the unbound control to check whether someone is in the database, and a button to a form based on text boxes that is purely for adding new people. It works (but I still feel it is kludgy).

      I am wondering if my problems are because I am working at cross-purposes. I need to do 2 things: 1) get existing data into the DB with some degree of normalization and recombine it, and 2) allow incremental additions of data.

      Is my problem really that I am trying to use combo boxes on single forms to do both tasks, instead of creating one set of forms for objective 1 with mostly combo boxes, and a second set of forms for objective 2 with mostly text boxes?

    • #1238576

      In some situations I don’t want users to be able to create new people..(there is another process for this)…in these cases I provide a single combo bound to an ID field, with a hidden first column, and the first name and lastname concatenated in the visible column. Depending on the circumstance, I display this is John Brown or Brown, John. I think the second option is better if the list of people is long.

      However, if I was entering a sale then the customer may be an existing customer or a new one. Here I provide a popup form with two unbound controls.

      Then a search is conducted.

        [*]If no match is found you are taken to a screen where you enter details of the new person. The names previously entered into the unbound form, are used to populate the relevant “new person” form.[*]If one or more matches is found, you see a list of matches, with more details displayed to see if any of the people is the one you want. You can then either choose one, or instead, decide you do need a new person. In that case you are directed to the new person form.

      At the end of the process the new person, or the person chosen from the list, is used as the person for the ‘sale’.

      ********

      When you use 3 combo boxes, what are they bound to? By ‘attached’ I mean ‘bound to”. I don’t understand what you do with the three combos, because I don’t understand what fields you are using. The only person field I would have in the table is the PersonID field, so I don’t know what to do with these combos.

    • #1238722

      I’d be interested in the code that does the search you describe in the middle (plus as much info about what lies behind those 2 screenshots as seems worthwhile) – if you’re willing to upload it.

      Other than that, I think I’m good – I’ve learned a lot from this thread (not what I initially set out to do, but perhaps how not to get into that jam in the first place).

    • #1239317

      I’m back. I ruminated over this for a few days, and I think I’m getting a handle on the issues here: I see them better from a theoretical standpoint, but I’m having a lot of trouble seeing how the controls in Access interface with the theory.

      So, I’ve switched my forms around: one record source for everything feeding information into text boxes, and no combo boxes with potentially different record sources.*

      Now I have a methodological question. My form (frmPersons) has a single record source (a person in tblPersons). But, a field for that record is a foreign key leading to the one side of a relationship (many persons may belong to one job category from tblJob). What is the appropriate way to include a person’s job category (in plain English rather than as the foreign key)? I can do this by adding information to a query underlying frmPersons. I can also do it by constructing a subform for tblJob, and including that subform on frmPersons. How do I decide which is better?

      * My original problem stems from taking something that worked from a subform – that did need combo boxes to restrict users to the data I wanted the data entry person to use – and applying it to the main form with a combo box that got me into trouble because I could give it a record source that was different than that of the overall form.

    • #1239387

      Sorry but this is not clear to me. Can you show a Relationships diagram for the tables involved?

    • #1239428

      File attached.

      I’m currently working the bugs out of the top left.

      My form frmPersons applies to tblPersons. It has a subform that relates to the junction table at the bottom tblPersonDegreeField… That subform works fine, and it’s a situation where a subform is probably the best choice.

      What I’m wondering with this last question is what about the tblDepartment at the top left. Its PK, departmentID is an FK in tblPersons. If I just build frmPersons from tblPersons, then frmPersons will show the value of that key (a number) rather than the name of the department.

      If all I want is for departmentName from tblDepartment to show up on frmPersons, it really doesn’t seem worthwhile to build a subform for it. I can just put together a query that draws from tblPersons and tblDepartments and build frmPersons from that so that it will show departmentName rather than departmentID. This is more user friendly.

      What I’m wondering, is given the mistake I made at the top of the thread (which was a result of not thinking through how I was addressing problems like this), am I now on the right track? And, if so, where is the borderline between when I should use a query to put together data from two or more tables vs using a subform.

      • #1239538

        What I’m wondering with this last question is what about the tblDepartment at the top left. Its PK, departmentID is an FK in tblPersons. If I just build frmPersons from tblPersons, then frmPersons will show the value of that key (a number) rather than the name of the department.

        If all I want is for departmentName from tblDepartment to show up on frmPersons, it really doesn’t seem worthwhile to build a subform for it. I can just put together a query that draws from tblPersons and tblDepartments and build frmPersons from that so that it will show departmentName rather than departmentID. This is more user friendly.

        I would display Department as a combo box bound to DepartmentID in tblPerson, (but drawing its options from tblDepartments) and with the first column having zero width. That would display the Deparment name, and also allows users to be able to change Department if they need to.

        What I’m wondering, is given the mistake I made at the top of the thread (which was a result of not thinking through how I was addressing problems like this), am I now on the right track? And, if so, where is the borderline between when I should use a query to put together data from two or more tables vs using a subform.

        I agree that you need a subform for the degrees as a person can have many of them. But within that subform I would use more combo boxes with a zero width first column to display the words from the other related tables.
        You always need a subform to show multiple related records.

        If there are not multiple records I would always use a combo to display the word value, (but lock the combo if I don’t want it to be changeable.) But if (say) there were a number of fields in tblDepartments that I wanted displayed here once the person was assigned to a department, I would probably use a query to show them. A subform would also be OK, but it usually involves more work.

    • #1239429

      I think you forgot the attachment.

    • #1239534

      Here it is again.

    • #1239569

      Seeing your diagram makes me think we have been talking at cross purposes throughout this thread.

      At the start you talk about separate “not in list” events creating two records.

      The circumstance where it may be appropriate to use a “not in list” event is this. You have a form bound to table X. One of the fields in this form is a combo using values from table Y. You want to allow users to add values to table Y as needed.

      But it now seems to me that your situation was quite different. Your form is bound to table X (tblPersons) but your two combo boxes are also drawing values from the same table X (tblPersons).
      In this circumstance you never want an “on not in list’ events to fire and create new records.

      You might want to use combos for firstname and surname, drawn from the same table to help people spell names, and see what records already exists, but the “limit to list’ properties should be set to “no” so that users can type a different name if they want (one that is not in the list). When you have finished with the new person the record will get saved automatically, and the new firstname or surname will be in the list in future.

    • #1239598

      You’re fine. We’re not talking at cross-purposes. I am. It’s just carelessness and confusion on my part. What you’re saying is helping a lot, but I do keep going back and finding ideas that were in the earlier posts that I’d missed. It is helping me that you are half-a-day ahead of me … it forces me to sit and think for a while about what you’ve written.

      Your last 3 paragraphs about when to use notInList are what I had gathered by about post # 10, and they make good sense now.

      You wrote:

      I would display Department as a combo box bound to DepartmentID in tblPerson, (but drawing its options from tblDepartments) and with the first column having zero width. That would display the Deparment name, and also allows users to be able to change Department if they need to.

      I am set up so that the recordSource of my frmPersons is a select query that includes departmentID from tblPersons, and departmentName from tblDepartments. Then my controlSource for my text box is set to departmentName. Is this consistent with what you mean? (For my purpose, I would set up a combo box the same way).

      You also wrote:

      I agree that you need a subform for the degrees as a person can have many of them.

      To me, this suggests that if someone had more than one department (they don’t in the relationship diagram I posted, but I will run into that case in the future) that you’d use a subform. Right?

      Lastly, you wrote:

      You always need a subform to show multiple related records

      What exactly do you mean by “multiple related”? Do departments not count as “multiple related” because a person is usually attached to just one of them? Or because they come from the same table? Or do you mean that a subform is really only called for when you are drawing records from different tables that are “related” because the particular data that I’m working with relates them outside of the DB: like my degrees and fields, which might stand on their own in someone else’s DB, but don’t in mine because I only care about relating them to a particular person. (I’m not nitpicking John – you’re in the talks-least-says-most category of posters, and I’m trying to make sure I get what you’re saying).

      • #1239852

        To me, this suggests that if someone had more than one department (they don’t in the relationship diagram I posted, but I will run into that case in the future) that you’d use a subform. Right?

        Almost certainly. If someone has just one department, you include a DepartmentID field in tblPersons. If they have more than one Department, you create a PersonDepartment table with (at least ) a PersonID and DepartmentID field (a junction table) and display the data in a subform.
        You use a subform whenever the data is coming from another (related) table.

      • #1239855

        What exactly do you mean by “multiple related”? Do departments not count as “multiple related” because a person is usually attached to just one of them? Or because they come from the same table? Or do you mean that a subform is really only called for when you are drawing records from different tables that are “related” because the particular data that I’m working with relates them outside of the DB: like my degrees and fields, which might stand on their own in someone else’s DB, but don’t in mine because I only care about relating them to a particular person. (I’m not nitpicking John – you’re in the talks-least-says-most category of posters, and I’m trying to make sure I get what you’re saying).

        Does my answer to the previous question clarify this? A record is related to this record if it is in another table, but has a field that is a foreign key from this table. There are multiple if there are (or may be) more than one of them. So when a person has multiple degrees there are multiple records in tblPersonDegree that connect to (or relate to) a particular person.

        So, to repeat, you use a subform whenever the data is coming from another table.

        I am not sure what the relevance of “other Dbs”. If there is another Db somewhere that has information about the same people that has no impact on this DB unless you have linked some tables from the other DB into this one. If you have linked tables from another DB, then they are treated as if they are part of the current DB. So either way, other dbs don’t make any difference.

        I don’t think you are nitpicking. If something is not clear, or raises a question in your mind, please ask. But I don’t try to be a ‘talks-least’ poster. I am trying to write comprehensive and clear answers.

    • #1239851

      I am set up so that the recordSource of my frmPersons is a select query that includes departmentID from tblPersons, and departmentName from tblDepartments. Then my controlSource for my text box is set to departmentName. Is this consistent with what you mean? (For my purpose, I would set up a combo box the same way).

      That is one option but it is the alternative to using a combo box, The point of using a combo box is that it is bound to the DepartmentID field, but it displays the Department Name (assuming you set the width of the first column to 0). So the recordsource of the form does NOT need to include DepartmentName, so it can be based just on tblpersons.

      Typically, you don’t want people to actually deal with the departmentID numbers so you keep them hidden. The combo box allows users to choose a department without seeing the numbers.
      (In your previous thread we did the same thing with Verbs.)

    • #1240763

      That is one option but it is the alternative to using a combo box, The point of using a combo box is that it is bound to the DepartmentID field, but it displays the Department Name (assuming you set the width of the first column to 0). So the recordsource of the form does NOT need to include DepartmentName, so it can be based just on tblpersons.

      So, in the original post to this thread, the problem was not that I was using a combo box for something like departmentName, but that I was using the code in the Not In List event of that combo box, and it was creating a new record in tblPersons (because that is what the form was using) instead of tblDepartments (which is where I wanted to add the new record), correct?

      If the answer to that is yes, I think I’m good for this thread.

    • #1240863

      Your quote showed me that I had left out a NOT in the post you were quoting. I have added that to the post (and to the quote).

      There is nothing wrong with using a combo box for Department, and using “Not In List” code to create new Departments. With a form bound to tblPersons, the “Not In List” creates the new record in tblDepartments (the table is one of the parameters in the code). Not In List code is always used to create records in a different table to the one the form is based on.

      The problem with your original post (which I did not realise at the time) was that you were using Not In List code for Firstname and Surname to create new records in tblPersons while you were also creating the same new person yourself via the form. (as I explained in post ).

    Viewing 19 reply threads
    Reply To: My NotInList Code Creates a New Record

    You can use BBCodes to format your content.
    Your account can't use all available BBCodes, they will be stripped before saving.

    Your information: