Microsoft Access - Combo Box - cannot add record, join key of table is not in recordset - sql

No matter how many tutorial, guides, or example I try to learn from; I can't seem to figure out how to make mine work. Its almost like a hit and miss when it comes to it. I got it working on some forms but I can't seem to get it working on others. Is there a trick to getting a combo box working; That I am missing?!
for example in my vendor form.
frm_vendor
tbl_vendor -> tbl_address -> tbl_addressType
PK vendorID PK addressID PK addressTypeID
FK addressID FK addressTypeID
I am able to create a combo box which allows you to select the addressTypeID <- no problem
control source = addressTypeID
row source =SELECT [tbl_addressType].[addressTypeID], [tbl_addressType].[addressType] FROM tbl_addressType;
row source type = Query/Table
bound to column = 1
limit to list = 1
not editable
But on this new form, I can't see to get it working.
control source = addressTypeID seems to be invalid and gives me a warning.
When you create a form base off a query. Should I be including every PK / FK in this query even thought I wont be displaying it, so the form can understand the links?

Basically yes, if you need to display data through a combobox, you will need to bind that combobox to some data from the query, so that when the form is open on a particular record, it can set the value of the combobox (here, addressTypeID), which in turn will display the value you want from another table (in this case, tbl_addressType.addressType).
In tis particular case, what you are trying to achieve is actually not very clear and that may be one of the reasons you can't get what you want: if you can't define the problem completely, then you can't find a solution.
What is it you need to show exactly?
You list 3 different tables that have some related information, but it's not clear what is the role of tbl_addressType in this.
Maybe if you had a screenshot of the form it may help?
One point regarding your database naming convention: I think the fact that your PK and FK are named the same is part of the confusion.
If you were to adopt something like this, it may make things a bit clearer:
Vendor -> Address -> AddressType
PK ID PK ID PK ID
FK AddressID FK AddressTypeID
.. VendorName .. AddressTitle
All Primary keys are named ID. Foreign keys follow the convention ForeignTableName+ID.
This makes the relationships unambiguous.
Now, your Vendor table is bound to a form:
frmVendor.RecordSource = SELECT ID, AddressID, VendorName FROM Vendor
So now, let's say we want to display the Vendor's AddressTitle and let the user change the Vendor's address to another one by selecting it from the combobox: add a combobox to the frmVendor, name it cbAddress:
cbAddress.ControlSource = AddressID
cbAddress.RowSource = SELECT ID, AddressTitle FROM Address
cbAddress.RowSourceType = Table/Query
cbAddress.BoundColumn = 1 ' Address.ID is bound to Vendor.AddressID
cbAddress.ColumnCount = 2 ' Two columns: ID and AddressTitle
cbAddress.ColumnWidths = 0;3 ' Width 0 for the ID column will hide it
And you are set.
When your form displays a Vendor record, the combobox will also display the corresponding Address' Title.
If your frmVendor.RecordsetType is Dynaset, then if the user selects another address from the combobox the Vendor.AddressID will be updated to the selected Address.ID.
Now, I still have no idea what you want to do with the AddressType table.

The RowSource for the combo box determines where the data comes from to fill the list with values, this list can be from anywhere in the database.
The ControlSource is the bit that maps the combo box selected value to the query that the form is bound to, i.e. the name in the ControlSource needs to be a field that exists in the RecordSource for the form.
So, in your new form, you need to make sure the query you have based the form on has got a field called addressTypeID.

I agree with #Rikalous
you need to make sure the query you have based the form on has got a field called addressTypeID
Hope this link can help:
Microsoft Access cannot add records join key of table not in recordset

Related

Show a name instead of an id

I currently have these options set in a combo box:
This box will show the projectIDs that a current company has which is set with the criteria. I just want to show the name of the project as people will not know just by the id. If I remove the check box for the projectID it will just remove that field completly and not show anything. I have debugged what companyBox.Value is and it is indeed a number for a company and if taken this id and replaced it with the following query which is built from the picture and it returns the results I want. I just cant get the values to show in the combo box.
SELECT projects.projectName
FROM companys INNER JOIN projects ON companys.companyID = projects.companyID
WHERE (((companys.companyID)=7));
Gives me all the projectNames where the companyID is 7
And as seen below that same query just gives me blank spaces instead of the names:
Ok, if you have say a query, then as noted, then you can use a "join" to pull in the other table (based on that "projectID").
So, for a general report etc., then your approach of using the query you have is correct.
HOWEVER!!!
For a combo box? They have this feature and ability built in. In other words you do NOT in general need a join.
The combo box has two parts:
A sql query that "drives" or "fills" the combo box. This can (and will be) of course based on the Projects table.
VERY important:
Our combo box is to save, store, put, use the project ID into a column in our CURRENT form. That form of course is based on a differnt table (the forms current table). So, keep in mind the two concpets:
Combo box can be driven by any table to display data.
Combo box will/can use a column from that "other" table to SAVE into a current column on the current form.
Now of course the Project "id" is the VALUE we want, but we sure as don't want to display that "project id" value, since as you note, humans want the nice looking text.
First Rule:
ALWAYS, but ALWAYS make sure the FIRST column of the combo box "sql query" is the column we WANT to save into the current form, but ALSO the column we are going to HIDE AND NOT show to the user.
So, a combo box can with great ease HIDE the first column. You can hide other columns, but as a general rule a VERY HIGH number of my combo boxs will have two columns. So, you might need company "id", but would want to display company name as nice text to the user, but store/save/use the "id" of company for this purpose.
So, in your case? Change the order of your columns.
You want:
ProjectID, ProjectName, and you ALSO can continue to have a filter based on company.
So, once you get above setup, and you WILL NOT need a sql join. Remember, the combo box has it own "whole sql statement" based on table projects.
So, the combo box will:
Save/store/use the ProjectID when you select a project.
And it will display the project name, but behind the scenes it will use + save ProjectID.
So, just make sure that you set the length of the first column in the combo box to 0 (to hide that projectID from display).
Next, make sure you set WHICH column value from the query the combo box is to save.
That column will be the FIRST column, so you want to set that to 1
Your combo settings will look something like this:
In above, the CONTROL source is your CURRENT form and table.
So, I want to get a Hotel "ID" from the table hotels, but I am going to save the results of the combo box selection INTO a column called Hotel_ID
And note VERY careful - I set the bound column = 1 (that is the FIRST value from the query that drives the combo box.
Next up:
We want to hide the first column value, so you need this setting in format tab of the property sheet for the combo box:
NOTE VERY close in above. I set the FIRST column width = 0. this is HOW you hide the "ID" of hotels - I only want the user to see the nice hotel name. (or in your case Project name).
But, the 2nd column, I have a width for the Hotel name (or in your case project name).
So, make your first column in the query for the combo box the "id" of project id. Set the width of the first column = 0.
So, the query that drives the combo box? It is based on the ONE table, but you need to ensure that the "id" that you going to use is the first column, and simple hide it from display.
So, a combo box has a sql query that drives the combo box, and that query in most cases will NOT be the current table.
So, you have to set BOTH settings (the column the combo sql query will use - but to avoid confusing, then just adopt the habit of making the 1st column the "id" or value you want from that sql.
But, after setting above, you STILL have to set what column to shove/put that column into on the current form. (that setting is the control source).
In effect, a combo box is a kind of look-up into the other table, and it can display nice user friendly text columns, but still use + store the ID.
So, your query should look more like this:
SELECT ID, projectName
FROM projects
WHERE (((companys.companyID)=7));
I don't know if your first column of Projects table is "ID" (or is it ProjectID), but as you can see, the combo box ONLY needs to be based on the one table, and with our new rule - we always use the first column of the query the "id" value we want.
Now, of course the above is "hard coded" for company, and your original query that drives the combo box was fine - just that the order of the columns display was incorrect.

How to display out of list items in a combobox?

I have a tbl_ProjectList that includes the project's Name and End Date.
A qry_cboProject queries this table to only display projects in a combobox on Subform A where the End Date is after the selected date on Subform B, both on Mainform C.
On Subform A, a macro copies (INSERT INTO SQL) projects from Subform B's previous months into the new months. However, if an out-of-date project gets copied over to a new month, the combobox field would be empty for that record, even though the Key exists on the back-end.
I've tried playing with the combobox's properties on Subform A by changing the Bound Column, Column Count, Column Widths, and Limit To List, but am only able to get the out-of-date project to display by its Key, rather than its Name.
The front-end reasoning for this macro is that employees do not have to repetitively select the same projects for each month, and employees already working on out-of-date projects may still need to put in some hours to close out the project.
Does anyone have any suggestions? Thank you in advance!
The order in which fields show up in you combo box depends on how the control source is querying the information i.e. to get name and not the key to show up in a combobox using the a control source query like the following:
SELECT Key, Name FROM tbl_ProjectList
You would need to set the following attributes:
Column Count: 2
Column Width: 0"; 2"
Bound Column: 1
It sounds like you may need to requery the control source as well. This should cause all the information to update.
#Parfait - apologies for not describing my problem in more detail. There are multiple subforms on one main form to allow the user to select a date in one subform, which populates projects on a second subform and responsibilities on a third subform.
Jeffrey's suggestion made me realize that the underlying query to the combobox should be adjusted for projects that are carried over into new months, where a foreign key exists in the underlying tbl_ProjectUserEntry
Therefore, I added a WHERE criteria to the query, which uses a DLookUp function to see if the foreign key exists:
DLookUp("[DateID]","tbl_ProjectUserEntry","[DateID] =" & Forms.frm_UserEntry.tbDateID) IS NOT NULL
frm_UserEntry is the main form..
Again, apologies for my brief description to a complex problem.

How do I display all records in a subform EXCEPT the one being displayed in the main form in Access 2010 without VBA?

I'm working on a database in Access 2010 which stores addresses. I've carefully designed the tables so that I can store a person and an address separately and then relate them through two other tables (relationship between the people is necessary to store separately from their address as well).
I have the following tables (for this question, focus is on PERSON and RELATIONSHIP):
PERSON RELATIONSHIP ADDR_REL ADDR
------------ ------------ ----------- -----------
(PK)PERSON_ID (FK)PERSON_ID (FK)RELATIONSHIP_ID (PK)ADDR_ID
FIRST (K)RELATIONSHIP_ID (FK)ADDR_ID ADDR_LINE1
LAST RELATIONSHIP_TYPE (PK)ADDR_REL_ID ADDR_LINE1
(PK)REL_PK ...
Without using VBA (if possible), I want to be able to display a given PERSON on a Form, and have a Subform which displays the other PERSONs in the matching RELATIONSHIP, but NOT display the original PERSON (whichever record is on display in the parent Form) in the subform result set.
FYI: I am able to build a solution to this in VBA myself, but it just seems like their aught to be a way to pull this off without it.
I've tried hidden fields, linked subforms, and custom Queries, but I always end up with all people in the relationship showing in the subform (or no results at all, or parameter prompts). Is there really no way to beat this without writing code?
set the recordsource of the subform to include all the rows in the relationship except the record displayed on the main form. I'm not really sure what the logic defining "the matching relationship" looks like, but I've taken a guess below: (this is all one query but I've broken it up a bit with comments for understanding purposes - remove the comments to use it)
'get all persons in a given relationship
SELECT p.Person_ID, First, Last
FROM Person p INNER JOIN Relationship r ON p.Person_ID = r.Person_ID
'define given relationship
WHERE Relationship_ID = (
SELECT Relationship_ID FROM Relationship
WHERE Person_ID = Forms(nameOfYourMainForm)!nameOfTextboxInMainFormContainingPersonID)
'and the person isnt the person displayed on the main form:
AND p.Person_ID <> Forms(nameOfYourMainForm)!nameOfTextboxInMainFormContainingPersonID;
Yes there is. It has been a little while since I have used Access. It sounds like at one point you were very close.
You first create your main/master form. Then create your subform/details form. Simply drag the details form onto the master form and if your relationships are correct it will automatically set the parent / child relationship for you.
Once your parent / child relationship is set then you modify your subform/details form's record source information. if it is based on a table then then change it to a query. This can be done in the form design view.
The simple answer is, in the query builder you can hide fields. In your case probably you want to hide the Person_ID field in the sub form.
The query must contain the key fields so the parent child relationship is preserved.
Also if your subform is a form with text boxes you can also just delete the text boxes you don't want visible.
So the correct answer is yes, but did I explain it enough for you to understand?

Dynamic query creation

I have a scenario wherein with the following details:
I have a form that contains fields like firstname,middle name,lastname,dob,pin,address for Client 1.
Now this form has to cater more than one client . The problem statement is - different clients may require different number of fields to be displayed on front end. For eg: a 2nd client would want - Country field instead of pin, would not require address on the form.
Now when i submit the form , currently i have a constant query which takes values of - firstname,middle name,lastname,dob,pin,address and inserts it into database for Client 1. I want to develop a query in a way that it is created at runtime and inserts only the values that come from the form into the database..
I hope my problem is clear. Can anyone help?????????????
You need to think about why you are doing this.
It will get hideously complex with just person form, add in more and it will balloon big style.
Dynamically building queries isn't particularly complicated, but it's a lot of code to do it.
Just think about each field you want to add to the query and it's type. What if a property on your person record was an image of them.
Do you have a configuration of the form, is the promary key on the record an auto inc, is it a compound key, do you use defaults, are some fields not null. How are you going to bubble back referential integrity exceptions...
Do the all singing all dancing version and basically you reinvent something like the Access IDE....
Personally I'd have a Person object with a set of Person Properties, they would have name, a value and a boolean to say whether they'd been changed.
Once you have teh list of chnaged properties and beacseu you are in the Person object you know the table is persons, it's keyed by an autoinc bigint, gender is mandatory and defaults to Male...
You have a fighting chance.
Your query should use parameters
So it would be say Insert Persons(FirstName, LastName, PIN) Values(#FirstName,#LastName,#PIN)
Then you'd nip through your changed fields and add parameters with same name, type and value.
As I said you can really go to town with this one, may be it's time for a night in though.
This should mean that some fields in your table like address and pin can be empty, in that case you can do without a dynamic query. Just collect all the inputs from your form and insert them into your table. Those form fields that were left empty due to different user needs will consequently have their corresponding field in your table empty. So just list all the needed fields in your table and all the possible input from your form in your insertion query.

How can I bind a multi-row update or insert statement to a form?

I have a table Prices:
ID -- primary key, autonumber long integer
PriceDate -- Date
Price - Currency
Quantity - Number, DECIMAL subtype
UnitPrice - Number, DECIMAL subtype (an update statement is run to keep this in synch with price and quantity, but it's just a convenience for indexing... probably it'll be replaced with an expression in my queries)
ItemNote - Text
NewStores_ID - long integer key, lookup to another table of stores
NewItems_ID - long integer key, lookup to another table of items
To enter prices for a given store on a given day, I would like to be able to select the store and date ONCE on a form, then enter the items individually in a datasheet. For reasons unexplained, this proves difficult.
I can create a subform binding everything but the store and price to a temp table TempPrices with the same structure as the original. Then I run the SQL statement
INSERT INTO Prices
(PriceDate,Price,Quantity,UnitPrice,Brand,ItemNote,NewStores_ID,NewItems_ID)
SELECT
PriceDate,Price,Quantity,Price/Quantity AS
UnitPrice,Brand,ItemNote,NewStores_ID,NewItems_ID)
FROM Temp_Prices;
This will feed all the new rows into the main table. But, when I want to set the store and date only once, I run into problems. I've tried using named parameters for date an store in the insert statement... which can cause a pop-up prompt, but I cannot bind it to a form control. I've tried binding an update statement for those fields in the temp table to a form... but it doesn't even show an option to bind a multi-row update.
How can I get this to work with a minimum of clumsy hackery? It seems like there ought to be a simple solution, and if I were using something like PHP or JDBC I'd just run an extra query.
Edit: changed storage type for Quantity and UnitPrice to Number, Decimal subtype in place of double float. Just so people won't cry about using a float in any proximity to currency. It doesn't pose a problem in my use, but there are enough people who have a knee-jerk reaction to that.
Edit 2: Form/Subform
I'm trying to structure this as a master form with a either fields for entering store name and date, or a subform for the same, then a subform mapping to the temporary table for entering pricing data. There is an action button to run the insert/update queries to dump the temp table into my main prices table and clear out the temp table. However, the problem is that I can't figure out how to get the date/store fields in the master (or subform) to bind to an insert/update value applied to all the new rows at once.
Edit 3: SQL Statements (for clarity)
INSERT INTO
PRICES(NewStores_ID,PriceDate,NewItems_ID,Brand,Price,Quantity,
UnitPrice,ItemNote)
SELECT
#MyStore_ID,#MyPriceDate,NewItems_ID,Brand,Price,Quantity,
Price/Quantity,ItemNote
FROM TempPrices;
UPDATE TempPrices SET PriceDate=#MyPriceDate,NewStores_ID=#MyStoreID;
For these queries, I cannot bind parameters for #MyStore_ID or #MyPriceDate to fields in any form. The queries don't show up as options when trying to link them to a form. I can run them and get popup boxes to input parameters, but that's not what I want.
This is the target I'm aiming at:
"I would like to be able to select the store and date ONCE on a form, then enter the items individually in a datasheet."
However, if you have a reason why you need to do it with a temp table and DML statements, then this suggestion will not be useful.
I created a Prices table with only 4 fields, then a query on that table which I used as the Record Source for a form, "fsubPrices":
SELECT p.ID, p.NewStores_ID, p.PriceDate, p.Price
FROM Prices AS p
ORDER BY p.NewStores_ID, p.PriceDate;
The form has text boxes (txtNewStores_ID, txtPriceDate, and txtPrice) bound to the similarly-named query fields. I set Enabled=Yes for txtPrice, and Enabled=No for the other two.
Then I created an unbound form "frmPrices", and in the form header added a combo box "cboStores" and a text box "txtPriceDate". The combo has Bound Column = 1 with this query for its Row Source:
SELECT l.Store_ID, l.Store_name FROM tblkupStores AS l ORDER BY l.Store_name;
Then I added fsubPrices as a subform control to the detail section of frmPrices. The tricky part is setting the Link Master/Child Fields. There is a "wizardy dialog thing", but it will only allow you to select from the available fields, and I needed to link controls on the main form with fields on the subform. To do that, I had to type what I wanted directly into the subform control's property sheet:
Link Child Fields......NewStores_ID;PriceDate
Link Master Fields.....cboStores;txtPriceDate
The result is ... choose a store and date combination in the main form ... any matching records are displayed in the subform. You can navigate to the "new record" in the subform to add records for that store/date combination. But the txtNewStores_ID and txtPriceDate controls don't show the updated values until the new record is saved.
I hope this is close to what you want. It's actually fairly quick and easy to create; not so easy to describe.
You can't really do that. You are always going to have one row being worked with at a time.
What you can do is simulate it by changing the form's Default View from "Single Form" to "Continuous Form" or perhaps "Data sheet" and making is a child(sub) form of a master form.
Then you can put the store and date on the Master form, and linking to the child form using the NewStores_ID and PriceDate fields.