how to assigne correct client_ID to order record from name, adress or create a new one if it doesn't exist - ms-access

I am trying to build a simple ms Access database.
For the sake of convenience, I will translate into sales, orders and such.
Orders
OrderID - PK (auto number)
Client ID - FK to clientID in the Clients table
Clients
ClientID - PK (auto number)
LastName
FirstName
Company
Address
...
I created a form (main form) that allow the user to specify details for a new order, including the client details.
The same form is used to look the details of older orders, to change their step for instance.
When the clerks types in, I don't know if the client is already registered. After everything has been completed, the clerk saves the new order as a new record in the Orders table.
However, Access complains rightly that the clientID FK has not been set: we set the clients name, first name... but not the ID.
My ultimate goal is that, at the saving of the new record, a request that look up into the Clients table to identify a list of possible candidates that match the client first and last name and open a form (contact form) that nicely displays the data from the first record of the request and allow the clerk to navigate between the records, and eventually select one or select create new record with the data from the main form.
I figured that a good place to do this would be in the save button on my form.
I tried to add something in the event code (macro) with something like (not VBA, a pseudo code I've never seen in the other office applications):
if IsNull([main form]![clientID]) then
bip
launch a request to identify the clients in the clients table with the same first and last name
open a form to look into each selected record and select the correct one or if none is identical generate a new one and return the clientID
end if
executeMenuCommand
command saveRecord
The code I tried above didn't even bipped...
I have placed the bip first, and that didn't bipped either.
I receive a message (explicit) that ms Access could not find a record in the client table with the specified clientID.
So I guess my main question is how do I test if there is a clientID associated with the current record?
The next problem is to come back to the main form with the selected clientID.
From what I have seen in the templates provided by Microsoft, it is avoided by defining a single field for customer in their main form. This field is a list populated from the client table, and if you stray away from the list you get a new form for editing a new client.
This is not the behaviour I am looking into. I need to have the posibility to free text enter every field and chose at the saving moment to create or not a new customer.
I hope I am clear enough, please feel free to ask for more details.
edit: thanks to Gustav's hint, I figured that the event was not to be associated with a button click but on the form itself. It helped me uncover other underlying problems... so I guess my problem is not ripe anymore for soliciting external help.

In VBA, use IsNull, and Me if the form is bound to table Orders:
If IsNull(Me![clientID].Value) Then

Related

How to save row values from one field in subform to main form record? - Access

I have a parent form (frmGroupSession) that has a subform (SubFormParticipants) in datasheet view. The subform is based off a query that selects all participants ([CLIENT ID], [NAME], [ATTENDED]) that had attended a specific group [GroupID] on a specific date [GroupSessionDate]. The parent form saves to a table that logs group sessions (tblGroupSessionLog). I need to save the group's participants [CLIENT ID] to the record within tblGroupSessionLog
Basically, I need to pass data from the subform to the record within tblGroupSessionLog. I'm not sure what the most effective way to do this, if it's possible at all. Ideally, I would like to have each unique participant [CLIENT ID] stored in its own field within tblGroupSessionLog. If there were 20 participants in the subform then each row value from the first column/field [CLIENT ID] would be passed to the corresponding field within tblGroupSessionLog ([ClientID1] thru [ClientID20])
I am relatively new at this. Even asking the question was difficult.
I am not sure what else I can provide to help you wizards with the solve, but let me know and I will.
Thoughts? Ideas?
Access 101 : You have a many to many relationship You should look that term up but in short it means clients can belong to many groups and each group can have many clients. (so bang your data into a normalized structure similar to the following:
First tip make sure to add the relationships under database tools (you should look that up). Access needs to know how the tables are related to manage the keys behind the scenes and sometimes access makes better decisions about automatic form creating when it already knows the relationship structure. Once your data is properly structured access makes it easy to produce functional if much less than styling data entry forms which can also be used as even worse search forms. For instance Click on any table and hit create form on the ribbon and access will create the data entry form form you.
Basic Style tip 1: Always delete primary key fields like ClientID from the form. The field is still there in the form's record source being managed by access. Users almost never need to see any table keys. This gives you a basic data entry form which you can also use to scroll through any clients you have entered using the record selector circled at the bottom of the frmClients.
Play around with the record selector to see how it works. In particular go past the last record and you will find you can enter new clients and access will automatically give them a ClientID. You can also cycle through your Clients and update them using this form it just isn't stylish. In the same way we can make a form for the groups table.
You make a form for the frmGroupSessions table in the same manner as the others but add a step. Replace the text boxes holding ClientID and GroupID with human readable comboboxes. Here is a link to help with that: https://www.google.com/search?q=access+change+text+box+to+combo+box&oq=access+change+text+&aqs=chrome.0.0i457j0l2j69i57j0j0i22i30l2.7503j0j1&sourceid=chrome&ie=UTF-8#kpvalbx=_r0sFYJ7vBcfY5gLz2aTgBw15
Becomes:
At this point play around to learn. Use the Record Selector at the bottom of frmGroupSessions to add and modify data. Play with the Tables and see what happens. Start messing with the form properties in particular the default view. Soon you will have ideas about how the form could be better and you can start figuring out how to style them.

Copy a field from Access to use in another access object

I have a form that uses a query to open and display a specific customer info based on a customer ID that is manually entered by the user.
The form populates with the customer info from a table where the customer ID can only occur one time. A sub form opens below the customer info with a list of items owned by that customer from another table where the customer ID can occur many times but the items owned is limited by a unique Serial Number.
I have this form set to No Edits so someone does not hose up the original data.
I would like for the user to select a particular Owned Item / Serial Number, and have that SN copied and used to automatically populate another query to open a new work request on that SN.
I don't know if this is possible or not but if so some help with the code or macro would be most helpful.
I understand that using Ctrl C and Ctrl V are the simple answer but the people using this don't want the extra effort and in some cases it is beyond them to even that right.
Create a buttom in the subform and write there a code to start a new record with the same serial as the current record in the subform

Use an Access 2010 form based on 1 table to enter data in a linked table

First of all, I am a total NOOB! I am trying to make an Access DB for handling orders through an entire process. As such, I have created tables based on each of the individual processes. The order data, which holds only the basic information is in tblCurrentOrders. Each of the other processes is linked to tblCurrentOrders by the OrderNumber field. The first step of the process is due date information is entered in the tblPlanner table. Obviously, until data is entered in tblPlanner, no OrderNumber exists (this will hold true for the other tables, too, if I ever get that far).
I want to create a form based tblCurrentOrders that shows only the records without corresponding entries in tblPlanner (new orders) and then I want to be able to enter the tblPlanner info in a subform. I have tried making a form based on tblCurrentOrders with a subform based on tblPlanner, but I can't figure out how to only display new orders. I also tried basing the form on a query that only showed new orders, but I don't know how to make the subform based on tblPlanner to work.
Please Help!!
Well, the easiest way to link the tables would be to create your OrderNumber in the tblPlanner when you start a new order. Then add a flag and timestamp as to whether it's "released" yet.
EDIT
Since you provide a little bit more detail, I'll edit my response to more closely align for your desired approach.
Creating a "New Order" is a multi-step process. So it's usually best to create a Command Button on a form that calls VBA code. This will allow you to control each step and make sure it's correct.
Step A: First you want to:
1) Create a Control Form (if you haven't already) that allows you to put Command Buttons which will launch different VBA code or open different display Forms.
2) On the Control Form, create a List Box that allows you to select an existing OrderNumber.
3) On the Control Form, create a Command Button to open an Order Form which uses the selected List Box OrderNumber. When that Order Form opens, it will populate with the tblCurrentOrders data for that OrderNumber and also populate the subform with tblPlanner data. (As long as you have them linked properly.)
4) On the Control Form, create a Command Button to open the Order Form with a set of records which are "New Orders" only. See the more detailed process below in Step C.
5) On the Control Form, create a Command Button to Launch VBA code that will create a "New Order". This is a multi step process detailed below in Step B.
6) Create any other buttons or controls that allow you to monitor or advance your "Order" along the way to completion. (This is a ton of work to get all the pieces in place.)
Step B: When you press the Command Button to create a "New Order" you want to create VBA code that will:
1) Create a new record in the tblCurrentOrders table.
2) Create a Unique OrderNumber on the new Record. It's usually best if you control the generation of this number and don't just let it be a system generated sequence number. But whatever you desire is ok as long as it's Unique.
3) Set your ReleasedFlag to false on the new tblCurrentOrders record.
4) Make sure your ReleasedTimeStamp is null. (Or whatever value you want it to be.)
5) You may want a CreatedTimeStamp which you can populate with a date of Now().
6) Populate any other "Initalization" fields that need to be filled. (Like Backorder status, Return flags, Shorted Flags, etc. etc. etc.)
7) Create a new record in the tblPlanner table.
8) Copy the Unique OrderNumber that you created for the tblCurrentOrders record into the OrderNumber field on the new tblPlanner record. This creates a link for you to use with your subqueries and subforms.
9) Now you can open the Order Form with this new OrderNumber.
Step C: When you press the Command Button to open a set of records which are "New Orders" only:
The Command Button needs to launch a query to find "...tblCurrentOrders that shows only the records without corresponding entries in tblPlanner (new orders)":
You just need to select tblCurrentOrders that have a ReleasedFlag set to false.
`SELECT * FROM tblCurrentOrders WHERE ReleasedFlag = false`
So when you say: "...and then I want to be able to enter the tblPlanner info in a subform"... you can create a subform linking to tblPlanner based on the tblCurrentOrders OrderNumber field.
This is all reliant on you observing that when you say "...records without corresponding entries in tblPlanner..." That you really mean: records without released entries in tblPlanner. And that means: in order for a record to exist in tblCurrentOrders, it has to have a corresponding blank (or starter) record created in tblPlanner. Thus now you can display blank tblPlanner records that are linked to unreleased tblCurrentOrders records.
Then once your data entry people are done monkeying around with the New Order, they can "Release" the order (usually by clicking on a Release Command Button). At that point, you can set your ReleasedTimeStamp to Now() and set your ReleasedFlag to True in the tblCurrentOrders. It's officially no longer a "new order" and is now a live order in your system.
You are at the tip of the iceberg for creating a home grown order entry system. The complexities for building a good one are immense. Best of luck figuring it all out. Just remember to use time stamps and ID fields so you can go back and un-do what may have been done by accident.
Hope this all helps. :)

Access Forms - Catch 22 trying to insert data to multiple related tables

I'm new to Access but have many years experience using "enterprise" databases. I'm having trouble implementing a simple task and suspect that my preconceptions are causing me to miss the point so I'm asking for some help.
The simple task is using Access forms for Data Entry that populates two tables: Customer and CustomerAddress (can be multiple addresses per customer).
The Customer table has primary key CustomerID. The CustomerAddress table has primary key CustomerAddressID and CustomerID as a foreign key with RI on that relationship.
Form1 is bound to the Customer table. After entering info for various fields, the user can click a button to display Form2 which is bound to CustomerAddress and enables data entry for multiple addresses.
Form1 passes the CustomerID (assigned by Access) to Form2. Form2 is not a subform due to size but it could be if that would solve the problem.
In a perfect world, I would want all the new data from both Form1 and Form2 to be committed together. Presumably I could do this using unbound forms and code the insert statements inside a single transaction.
Question 1: Is there a way to do this using bound forms?
If I use Form1 without ever clicking the "Address" button then a row is successfully added to the Customer table. The problem comes when trying to add CustomerAddress row(s) in Form2 before the Customer row has been added to the table.
In Form2, if the CustomerID is not used, then there is an insert error because a CustomerAddress row cannot be added without a CustomerID.
If the CustomerID is used, then there is an insert error because the CustomerID does not exist on the Customer table yet (although the ID appears to have been "reserved").
It's not practical to force the Customer row to be added before opening Form2 as some Customer required fields are not present at that point in the workflow.
Question 2: Is there a way round this? It seems like a common requirement.
I could work around this by removing the RI so that the CustomerAddress rows can be added first, but this seems poor DB design and I'd also need clean-up logic for the case where the Customer add is subsequently cancelled.
As mentioned, I'm probably missing the point and there's a better approach. Any help much appreciated.
I think you would have the same problem regardless of which RDBMS you used if you are enforcing referential integrity. The CustomerID needs to exist in the Customer table before a record can exist in the CustomerAddress table. I'm guessing that CustomerID is an autonumber. What is probably confusing is that Access does immediately 'reserve' an autonumber as soon as a new record is started. However, it does not exist in the Customer table. If that record is never saved, that autonumber value is lost and the next record would get the next number. Requiring an address to be completed before saving the Customer record, sounds like a design problem. It doesn't seem logical. Personally, I would re-think the design. That said, one solution would be to create a temp table for addresses and bind your CustomerAddress form to that. Then, when the customer record is saved, you would run an append query to add the new addresses to the CustomerAddress table. Remember, though, that if a user enters some addresses and the Customer record is never saved, all of that data entry is lost.
With regard to your statement:
It's not practical to force the Customer row to be added before opening Form2 as some Customer required fields are not present at that point in the workflow.
You are correct that you won't be able to insert the Customer row if the "required but not yet known" fields have their Required property set to Yes (i.e., NOT NULL). However, with Access 2010 and later you could use an event-driven data macro to make such fields "not required" on Insert but "required" on Update. In your case, you could
allow the Customer record to be inserted without the "eventually required" fields,
allow the addition of CustomerAddress records (with RI enabled), and then
re-open the Customer record for updating, with the data macro now enforcing the "required" status of the other fields.
The Before Change data macro might look something like this:
I think the answer lies within your Question 1. Yes there is a way to do this with bound forms, and would be the approach I would use.
Form1 is bound to the Customer table. Add Form 2 onto Form 1 as a subform. Select / highlight Form 2, goto the properties sheet. On the Data tab, set the Link Master Field to CustomerID and Link Child Fields to CustomerID.
Then after any action taken on Form 1, requery Form 2.
I think this will get you started and at least should give you an idea on how to proceed once completed.
I fail to see why both must be or one would even want to submit both customer and a record from the child table at the same time.
What about when you want to add an additional address, then that add address button and code now will have to check + test if the main customer already exists, and use separate logic to deal if the customer record exists, or does not. And what about if a user has entered the customer name and info, and does not yet have the address as the customer on the phone might have just moved and has to call back with the new address. I can think of another half dozen cases in which building a design in which both customer and customer address records MUST be added at the same time.
As others noted, you going to have this issue with any relational database, including Access. I should also point out that Access works EXACTLY the same here if you use Access as a front end to SQL server or Oracle.
So it makes little sense to build a different UI and coding process for adding the customer and the address, and then a DIFFERENT set of rules and UI for adding additional address over time. So build a form to search + find a customer, and add that customer and display that customer. Once that process is done, then you add the process (and UI part) to allow the user to view, or add address to that customer. I don’t think I ever seen a UI with separate forms to add/edit customer and a separate form to allow additional address to have some requirement that they are submitted together at the same time.
If the user bails out of the Address because they realize the address is not available, wrong etc., this should not suggest that the customer information entered so far be dumped and not added. If the user after bailing from adding the address (say close or cancel that form), then you return to the customer form. If the user decides at that point in time for some strange reason they do NOT want the customer in the system anymore, then provide a delete button.
If the business rules are that one MUST ALWAYS have at least one address in all cases, then upon closing the customer form you don’t allow the form to be closed and request that that user enter at least one address for this user. And perhaps they bumped or hit the wrong key to exit the address enter part – no need to penalize that user and force them to re-enter the customer info. So don’t let them exit the customer form until they enter an address or provide them (suggest to the user) they can delete/remove the customer fi they want to exit.
If you use a form + sub form setup, then zero code is required for the relational part. And a tab control gets you both forms can be near full screen size. (no need to launch a separate form).
Of course you could write a bunch of code and placed everything in a transaction, but such is a waste of coding time for no benefits and amounts to theft of company hours and time when not required.

Suggestion and auto-complete in form with one-to-many relationship in Access

I am trying to make a form for a very typical scenario: a customer makes an order. The customer might be new or returning. I have created an Access database with two tables: Job and Customer (linked by the primary key 'customer no'). The form I wish to create looks like this:
The customer table data is highlighted.
When the customer's name is beginning to be typed in, I want to see an updating list suggesting possible customer matches. If the customer happens to be returning, I can click on one of the drop-down options and have all other customer fields auto-complete.
What is the best way to create such a form?
I tried to achieve this using a comboBox and some code. However, if I use this method, the comboBox does not allow me to enter a customer name which isn't already in the customer's table. So I can't enter new customer details.
Ideally, this auto-complete/suggestion should work for all customer fields, such as phone number (in case the phone number is the only know customer info).
You could use a combobox which has LimitToList set to false, allowing entry of data not already defined in the combobox's rowsource; With this approach you would define a not-in-list event handler for the combobox to open a popup form for adding a new customer, ideally pre-initialised with the customer name just entered, and when data is saved in that form, control returns to this form, requeries the combobox (as it's contained data is now out of date), re-locks the customer just added, and fires it's after update event to display all the relevant customer-related fields appearing on this form.
However whether this is appropriate or not depends to some extent on the quantity of data that you have. If you've more than say 10000 customers in the database, I'd recommend instead having an elipsis (...) button beside customer name which opens a popup search screen, and provides whatever search options seem best (name, number, city, etc) for the entity being searched, a textbox, and find + add buttons; With huge data quantities you might also want to provide a means to prevent searching for matches (especially by multiple users across a busy network) where there is less than say 4 characters in the textbox, to improve performance.
You'd then use the text_changed event on the textbox to retrieve the data in the database which starts with the text currently existing in the textbox, and display this in a datasheet; The user can then either click Find or double-click the datasheet to select a customer which you then return to the calling form, probably by either a call to a public sub, or setting a tag value on that form - or click Add to add a new customer and invoke logic similar to the above.