I'm working on the design of a database for a client and they would like to work with one of their companies (customers) at a time throughout the entire session.
Ideally I would like to set up the forms so that they select the company to work with first and then can navigate to various other forms to manage the different aspects of that company (locations, departments, employees, etc.). There will obviously be many companies in the database, so I would need to ensure that they only see records for the selected company and adding new values ties them to the selected company.
I've been doing some searching around for how best to accomplish this but I've had no real luck.
Any guidance you can give would be awesome.
PS. I've got the structure of the database tables setup to ensure that any entity that is company-specific has a foreign key that identifies the company.
When the user enters the program, the first form they should see should be the company chooser form. Then the user can continue on to the other forms, which would all be filtered based on the user's initial selection.
You can either have the form write to a module-level variable, and all the forms would be filtered by the value of a function which would return the company ID to filter by.
It may be easier for you to simply hide the form, and filter all the successive forms by the value in the combo box of the hidden form.
You might also want to consider creating a query for each table, which contains only the filtered values per company (either with a function, or by the value of the hidden form) and basing all your forms/reports on those queries. That way you won't accidentally forget to include the filter in a form/report.
Related
I have a question regarding a data entry form for project pricing estimates I am currently building.
To give you some context: The form will be used to enter data and complete calculations. It will replace an excel spreadsheet comprising of 59 columns, 1-15 rows (it varies by requirements) per project estimate. Average number of projects is 50-60 per year saved in respective customer folders. If there is an update to the estimate, a new version of the spreadsheet is created and saved in the respective customer folder. Hence, in certain scenarios, there are can be up to 10 versions saved per customer per project.
I am seeking to create a form-table combination for each of the customers: hence 10-15 forms with the same structure. Currently, I am only creating one form and table combination as a test. The table designed to replace the spreadsheet will use a total of 30 auto number foreign keys to store information. To be user friendly, I am using combo boxes in my form, where the user types in text but is stored as a foreign key in the table.
On top of this, I need to include calculations. For example, if the user selects certain options from my combo boxes, this will result in a calculated answer in an adjoining form field. Part of the calculated answer will use data in a linked table from another access database. Based on the options selected in the form combo boxes, the database will scan specific columns in the linked table to find matching entries to the selected combo box options. If a match exists, a price is extracted from that linked table. So say the combo box options selected are origin Miami and destination Salt Lake City, the database will scan for those 2 entries in the linked table. If that entry combination is found in the linked table, this price is to be used in the calculation. This price will then be multiplied by two other components entered by the user in the form, resulting in the calculated answer.
My questions:
Regarding the calculation example I gave above, can the above scenario be realistically accomplished in Microsoft Access? If so I am assuming I have to use VBA and/or Macros to do so?
a. If so, is it suitable to use my data entry form to complete it? Or is there an alternate way to achieve this result?
Will 30 combo boxes combined with such calculations have a significant impact on the speed of my form and database, especially as more data is added to the form and given that 10-15 forms will use the same structure? I have thus far included half of the combo boxes in 1 form, completed 1 test entry and I find that occasionally there is a slight lag when opening the form.
a. If it will impact my form's performance, what are my options/other form controls I can use to minimize lag and maximize speed?
Many thanks in advance!
As an amateur coder for some years I have generally used sub forms when dealing with linked tables to make the transfer of ID field from primary to sub nice and simple...
However in my latest project the main form is a continuous form with a list of delivery runs (Date, RunName, RunCompleted) etc... Linked to this primary table is a delivery list containing (SKU of product, Qty etc...). I use a simple Relationship between the two tables.
Now, On the main (RUNS) form at the end of each row is a button that opens the DELIVERIES form and displays all records with matching RUNID
This is fine for displaying pre-existing data but when I want to add new records I have been using the following code attached to the OnCurrent event:
Me.RunID = DLookup("[RunID]", "tbl_BCCRuns", "RunID = " & Forms![frm_BCC_Runs_list]![RunID])
I have also used:
Forms![frm_BCC_Deliveries].Controls![RunID] = Forms![tbl_BCCRuns].Controls![RunID]
(Note: above done from memory and exact code may be incorrect but that's not the problem at hand)
Now... Both these options give me what I need however...
I find that as I am working on the database, or if you open certain forms in the right order (a bug I need to identify and fix clearly) you can open the DELIVERIES form without the filter (to view all deliveries for arguments sake) and the top entry (usually the oldest record) suddenly adopts the RUNID of the selected record back in the main form.
Now, my question is this, and the answer may be a simple "no" and that's fine, I'll move on...
Is there a better way, a way I am not familiar with or just don't know about due to my inconsistent Access progress, to transfer ID's to a form without risking contamination from improper use? Or do I just have to bite the bullet and make sure that there is just no possible way for that to happen?
In effort to alleviate the issue, I have created a Display Only form for viewing the deliveries but there are still times when I need to access the live historical data to modify other fields without wanting to modify the RUNID.
Any pointers greatly appreciated...
Since you only want to pull the RunID if the form is on a new record row, do a check to verify this is a new record.
If Me.NewRecord Then
Me.RunID = DLookup("[RunID]", "tbl_BCCRuns", "RunID = " & Forms![frm_BCC_Runs_list]![RunID])
End If
Could also consider a technique to synchronize parent and child forms when both are subforms on a main form (the main form does not have to be bound) https://www.fmsinc.com/MicrosoftAccess/Forms/Synchronize/LinkedSubforms.asp
So I've started learning access due to necessity, as the person who was in charge of it passed way and someone had to keep it going.
I noticed a very bad (at least IMO) behavior in all databases he created: Every single form was bound directly to a table or saved query. This way, if the user opened a form, he had to complete all the steps he was supposed to do, because if he closed the form mid process (or the computer froze, or anything of the sort), the actual data would be compromised as it would be half complete. This often times broke everything in the process chain, rendering sub-sequential steps impossible to be performed and forced me to correct data manually directly in the tables.
As I've start upgrading his stuff and developing my own, I've been trying to learn ways to allow the data to be edited in the form only, making it possible to cancel the process anytime or save the changes all at once in the end.
If the editions were simple, I discovered that I could create a recordset, copy relevant data to unbound fields in the form and, in the end, if the user chose to, copy the data from the form fields back to the recordset.
Other times more complex solutions were required, as I would need to edit several pieces of data at once in continuous forms, "save" them, run more code, maybe add fields to hold the information originated from that processing and so on. I then learned about using temporary tables, but did not like it, since it tended to bloat the db. I even went on to creating temporary databases during code execution that would host the temporary tables and be destroyed in the end, but that added too much unnecessary complexity.
Nowadays I'm using disconnected ADO recordsets to hold the temporary data and fields. It works but has its limitations.
So I'm wondering, what is the best way you - much more experienced than me - guys use to approach this kind of scenario? Is using in memory ADO recordsets really the best way around?
I think you are mixing two things that a form does that have completely different requirements. Editing existing records (and bound forms are great for that) and creating new records (where using a straight bound form can result in creating incomplete records). The way to approach it depends on many things but mainly to how much data is necessary for a new record to be considered "complete".
I usually do one of the following things:
Create an unbound popup modal form for adding new records where only the necessary fields are present. Once complete it loads the new record to the main form for further editing.
Use the above method except the form is not a popup one but a set of unbound fields in the footer or header of the main form.
Let the user create new records but bind validation on the OnClose (and/or other appropriate to your situation) event of the form that deletes the half-filled record if it does not validate.
Let users create new records in the bound form but have a 'cleanup' routine called either on a schedule or based on user actions.
Ultimately if your business process requires the majority of fields to be manually added/edited every time a new record is added or edited, you are better off using an unbound form.
This way, if the user opened a form, he had to complete all the steps
he was supposed to do, because if he closed the form mid process (or
the computer froze, or anything of the sort), the actual data would be
compromised as it would be half complete
No, if the computer freezes, then no data is saved to the table. This is the same if you used a disconnected reocrdset and a un-bound form.
If you use the before update event in the form that has some verification code and does a simple cancel = true, then the forms data is not saved nor is the table updated. Again, if you used a dis-connected record set and the user closes the form, you have to test the data – and again you can either choose to write out the data or not – this effect is ZERO difference from using a bound form to a table or a disconnected form.
If the editions were simple, I discovered that I could create a
recordset, copy relevant data to unbound fields in the form and, in
the end, if the user chose to, copy the data from the form fields back
to the recordset.
No you don’t need to do the above. The above achieves nothing and only racks up additional development hours and increases cost of the application. In near all cases in-bound forms increase development costs over that of a simple form bound to a table. So the original developer had the correct idea. You can control the update of the underlying table in near all cases to achieve the required verification. Forms only save and write the data out if the developer allows as such.
So Access forms when bound no more or less write incomplete data out to a table if you place verification code in the forms before update event. A half-filled bound form, or a half filled un-bound form with dis-connected reocrdset BOTH will not write their data if the computer freezes.
And BOTH types of forms will not write out data to table until such time your verification code has completed.
Access is not designed for un-bound forms, and tools like vb.net, or even VB6 had a whole bunch of cool wizards and support for un-bound forms. In access, we don't have those wizards. And when you use UN-bound forms then you loose tons of form events. You in effect get the worst of both worlds, since you lose use of form events and have no wizards or support for un-bound. Even just the several delete record events we have are rather amazing.
You lose use of me.dirty, on-insert, me.newReocrd, forms after update events - the list of features you toss out and lose is huge. And if you want a button to write data to the table (such as a save button on the form), then just go:
If me.Dirty = True then
me.Dirty = False ' this forces your verification code to run
End if
There are FEW use cases in which in-bound forms will benefit you, but they will cost you rather much in terms of development times.
According to the searching I've done over the past couple of days, what I'm trying to achieve should be fairly straightforward but nothing that I've found has solved my problems. This is my first time at using Access, or SQL at all. Apologies in advance for the length of the question.
Essentially I need to pick up a value from one table and multiply it by another in the another table, and then store the result in the second table, via forms and subforms.
The Problem:
I'm attempting to create a database of projects, part of which is a quotation tool. The database has several tables covering all the required inputs for our project managers, most of which are linked to the PKs of their parent tables.
My current attempt has a form (frmJobDetails) giving the details of the each project (linked to tblJobs). This form has two subforms:
frmJobRolesSubform details who's working on the project in what role ( and, notably, their sale rate.
frmJobProcessesSubform details the tasks, who's allocated to which task and the estimated number of hours to complete.
Both subforms link to their own tables (tblJobs_Roles and tblJobs_Processes respectively).
frmJobProcessesSubform obtains the people working on the project and their roles from frmJobRolesSubform so the manager can allocate a person to a task on frmJobProcessesSubform. This is done via a combobox: cboRole.
So far, so good.
I'm needing to obtain the sale rate of the person working on the given task so that I can calculate the cost of the task. Specifically, I'd like a field on the subform to calculate the cost of the task and then store it in tblJobs_Processes.
My Attempts
I've attempted to build a query (qryProcessCost) that calls cboRole, either as an expression in the Field cell or in the Criteria cell ([Forms]![frmJobsProcessesSubform]![cboRole]).
I'm aware this can't successfully when the form isn't active, but I'm getting Access' request for input for [Forms]![frmJobsProcessesSubform]![cboRole] when selecting from the subform. The query runs successfully when example values are hardcoded into the query. The query should, obviously, only return a single value.
I've tried setting the ControlSource of a textbox to [qryProcessCost]![dblProcessCost] (where dblProcessCost is the calculated field), but this can't then write to the table (as far as I can deduce). Also, I get a #Name? error in the cell and I can't seem to get to the bottom of that.
I've tried setting the RecordSource property of a combobox to SELECT [qryProcessCost]![dblProcessCost] FROM [qryProcessCost], and the ControlSource to the relevant field of the table. While this would be a clunky solution, it actually doesn't work anyway as it fails to pick up the value of [Forms]![frmJobsProcessesSubform]![cboRole].
I've tried using an intermediate textbox to determine what value cboRole is passing, and I'm happy with that - the primary key of the role assigned in frmJobsRolesSubform.
The Question:
I'm guessing that I'm probably going to have to resort to VBA at this point to get what I want but I'm unfamiliar with the Access VBA structures (though I've used Excel VBA a fair bit).
Anyone got any ideas, hints, suggestions or pointers?
Cheers in advance,
Aaron
In case anyone else has a similar problem, I've posted my complete solution below:
I implemented Gene's correction to my references, which provided something, but the query wouldn't update when the fields on the form were changed. As I noted in the question, I also really wanted it to be a text box rather than a combo box for usability reasons but wasn't sure how to have a Record Source and Control Source for a text box.
I ended up going round in circles, via VBA and macros and several types of error and happened upon a suggestion to use a DLookUp here. I hadn't been able to get them to work for this particular problem before, but I managed to make it work this time. Specifically, I put the DLookUp in the following macro:
SetProperty
Control Name txtBudgetCost
Property Value
Value =DLookUp("[dblCostRate]","[tblJobs_Roles]","[pkJobs_RoleID]="[cboRole])*[txtBudgetHours]
This macro was used for the After Update event of the relevant fields on the subform.
Setting the value property of a field to a DLookUp meant that I could set the Control Source property of a the text box txtBudgetCost to the relevant field in the table, to obtain the desired behaviour.
Both cboRole and txtBudgetHours are fields on the same subform as the field txtBudgetCost.
The only problem with this solution is that, when the subform is viewed in the Datasheet view, a #Name? error is given for the new record row. I probably just need to enter some error handling somewhere, though I haven't given much thought for what it should be just yet.
Cheers,
Aaron
A little background:
I have 2 entities (Product and Case). The product entity will hold all product records. A section in the Case will have the ability to choose products and auto-populate all related fields that are located in the product record for that specific product. For example, Product record has fields like hazardous, range, lot ect. The same field appear on the Case record. These fields should only be populated based on the product that was selected.
I was able to accomplish the above by creating a 1:N relationship and adding it to my Case form. I then created a workflow to populate the related fields (hazardous, range, lot ect). However, these fields only populate when the record is saved. Is there a way to make it update the fields once the product is chosen?
I want to refrain form using any type of JavaScript. If possible, I would like to strictly use workflows to accomplish this (if at all possible).
Real time information in your case can be only accomplished by using JavaScript. Maps works too but they have a special behavior.
Workflows that fire when the record is created only execute after all core operations are done (Native logic, Plug-in logic...) and you can't fire workflows if the record is not created.
So using workflows is a good idea even if you can't see the information