How can I display a *foreign* field value in a text box? - ms-access

How do I bind a text box with a field, which doesn't belong to form's "Record Source" table, through the Design View?
Example: I have "Order.cust_id" (Record Source=Order) and I want to display "Customers.name". I believe it is trivial but I have no experience with MS Access. I tried to use the text box "Control Source" property but no luck.

One method would be to convert the text box to a combo box. Then set the row source to include both the cust_Id and the Customer.Name from the customer table. SQL statement example
Select Cust_ID, Name From Customer
Order By Name;
By setting the number of columns to 2 and the column widths; the first column as zero (i.e. "0;6") then the foreign key would be hidden from the user and the customer name would be displayed.
Note this method does force you to have limit to list set to true.
Also you do end up with a drop down list which may not be what you want.

You can use DlookUp as the control source of a textbox:
=DlookUp("[Name]", "Customer", "ID=" & Cust_ID)
Syntax: What to look up, table name, where statement
The Where statement should follow the rules for Jet SQL, which means that you must use delimiters if the field is text or date format.
Note that Name is a very bad name indeed for anything. I suggest you rename the field immediately before things get worse.
It can be useful to know the error(s).

You could create a new View (e.g. OrdersAndCustomerNames), select all the columns you want to use in the form, then instead of using the Order table as Record Source, you would just switch to OrdersAndCustomerNames. You say you have no experience with MS Access, so I am guessing you are not building anything huge and overly complicated, so I would do it this way. I am quite sure it can be done more elegantly but this will do for now.

Related

Input mask in Access database

I have a field with a customer ID that should be in the format of C0000000001, where it has a letter at the start and up to 10 numbers after the letter with leading zeros between the letter and the number. I want the users to be able to put in C1 and have the table save C0000000001 or C1234 and have the table save C0000001234.
I want the restriction to be on the hard data in the table. The table should contain the full customer ID but I only want the users to have to enter the C and the number of the customer when entering/searching for customers. I am using Access 2010.
I believe that the first character will always be a C, but either way, it would only be one alpha character if it wasn't.
I understand what you are saying, but the majority of the data (thousands of records) are going to be from another system that stores them that way. Doing it this way limits my margin of error. Otherwise, exports from the other system will need to be manually changed prior to being imported into the database and vice versa.
Searching would only be on existing records that will be saved in the C0000001234 format, but I would like user to be able to omit the leading zeros when entering the search criteria.
This question, combined with your previous question here, suggest to me that you are trying very hard to have the data structure in your Access database exactly match the legacy system from which you receive bulk updates. That may not be necessary, or even desirable.
For example, instead of maintaining the CustomerId as Text(11) (as in the old system) you could store it in your Access database as
CustomerIdPrefix: Text(1), and
CustomerIdNumber: Long Integer or perhaps Decimal if the numeric part really can exceed 2,147,483,647
Your Customers table in Access could also include a calculated field named CustomerId as
[CustomerIdPrefix] & Right("0000000000" & [CustomerIdNumber], 10)
to give you a single 'C0000012345' value for display purposes.
For searching, your form could have a Text Box for the Prefix (default value: 'C') and another text box for the numeric part. The search could then use a condition like
[CustomerIdPrefix] = txtPrefix.Value AND [CustomerIdNumber] = txtNumber.Value
or, if the user wanted to create a Filter on the Form (or Datasheet View) it would probably be sufficient to just filter on the number part.
If you ever needed to feed information back to the legacy system you could just export a query that includes the [CustomerId] calculated field (and omits [CustomerIdPrefix] and [CustomerIdNumber]) and you'd be fine.
My suggestion would be to use forms with associated queries using the FORMAT function.
You do need to clarify where you want this implemented, but I'm going to assume you have a table set up and that you would like to be able to enter/search data from a form.
I'll create one form for input frmAdd. For the input form, I created a query that would run when a button on the form was pressed. Add two text boxes newID and newOther to the forms which are unbounded but which the user can use to enter data. The query will then pull that data and append it to your table in an altered format. Here's the SQL for that query:
INSERT INTO Customers ( [Customer ID], [Other Field] )
SELECT Left([Forms]![frmAdd]![newID].[value],1)
& Format(Right([Forms]![frmAdd]![newID].[value],Len([Forms]![frmAdd]![newID].[value])-1),"0000000000")
AS Expr1, Forms![frmAdd]!newOther AS Expr2
FROM Customers;
I'm not sure exactly what search functionality you're looking for, but this query would pull up the record data matching that of a frmSearch with a textbox search which would have the format C### or whatever entered in:
SELECT Left([Customers].[Customer ID],1) & Replace(LTrim(Replace(Right([Customers].[Customer ID],9),'0',' ')),' ','0')
AS Expr1, Customers.[Other Field]
FROM Customers
WHERE (((Customers.[Customer ID])=Left([Forms]![frmSearch]![search].[value],1)
& Format(Right([Forms]![frmSearch]![search].[value],Len([Forms]![frmSearch]![search].[value])-1),"0000000000")));
Applying the input mask is just a way to ensure that your data is correct. If you feel the need to use one, go to the table in Design View and click on the Data Type box for the customer ID field. Find Input Mask under Field Properties -> General and click it. Then hit go to the toolbar -> Design tab -> Builder. This will walk you through it.
Input mask is not the answer for this. Input mask forces the user to input the data in a certain manner. What you need is some VBA code to run in the AfterUpdate event on a form. There's no way within the table to force the data into this pattern allowing the input method that you've requested.
There may be a more efficient way to do this, but this does the job.
http://pineboxsolutions.com/access/customeriddemo.accdb

Parameter query doesn't return the value of an auto number control

I have a form linked to a table. The form has 4 text boxes: one linked to the autonumber field, and the other three to text fields.
There is also a subform, from which I wish to launch a query (via button and macro) combining results from the subform and a control on the main form. When I specify any of the three text-based controls in a parameter query, this works fine, but asking for the value of the first (autonumber) control results in a symbol being displayed instead of a value.
I wasn't sure what specific information/images would be helpful. Please ask for specific information if you feel it would help.
I've been given the answer elsewhere. I had to implicitly convert the results of the batch field into an int.
INSERT INTO heat_treat_jobs ( card_id, batch ) SELECT atheattreat.id, CInt([Forms]![heat_treat_loads]![batch]) AS Expr1 FROM atheattreat WHERE (((atheattreat.index)=[Forms]![heat_treat_loads]![atheattreat subform].[Form]![index]));

Variation of SELECT * - all columns except those explicitly referenced

Is there any way to convert one column and be able to reference all the other columns without naming them explicitly?
Normally I would do this:
SELECT
,[Id]
,[Name]
,CONVERT(VARCHAR(10),[CreateDate], 104) as [CreateDate]
FROM Customers
What I could do in the perfect world would be:
SELECT
*
,CONVERT(VARCHAR(10),[CreateDate], 104) as [CreateDate]
FROM Customers
Where * would mean all columns that are not explicitly stated in the query.
Is there a keyword that enables one to do this or is there some other way? Please keep in mind that it has to be doable in a query - no changing tables, making views, SPs or something else.
There isn't a programmatic way to say "all the columns except this one" unless you wanted to build dynamic SQL from sys.columns based on a list you provide the query (it would be very difficult to derive the list of referenced columns from the query dynamically, especially as you introduce joins, where clauses, etc).
But there is a pretty trivial way to do this without typing them all. Just expand your table in Object Explorer, and drag the "Columns" node onto the query editor window. Now just remove the CreateDate column from the list.
What I like to do to avoid typing a long list of fields is select the table name in the editor and then press alt-f1. That is the same thing than typing "sp_help table". You will get a result set with all the column names of that table. I copy that list into the editor and add the commas.
An easy way to add commas at the end of all the lines by using the search and replace in the editor:
Select only the lines with the column name.
Check "Use" and select "Regular Expressions" from the drop down.
In the "Find What" type $ (Dollar sign means end of the line)
in the "Replace With" type ,
That will add a comma to the end of each selected line.
Another way is to right click on the table in the Object Explorer and click on "select top 1000" option that will create a script for you in another text editor window.

Add "All" option to ComboBox used to filter for report in MS Access

I'm trying to follow Microsoft's example on how to add an "All" option to a ComboBox in Microsoft Access, but their article does not do an adequate job of providing guidance, aside from specifying the code.
What I'm trying to do is build a form that allows a user to select an option from a ComboBox (the options are generated from records in a table), and then build a report filtered based on the user's selected option. The ComboBox consists of 2 columns: the primary key/ID of the records and their displayable names.
I can't understand the VBA code Microsoft provides enough to figure out what is going on, but I would like the "All" option in my ComboBox to either have a blank primary key/ID, or one that = 0. That isn't the case, as selecting the "All" option when using the form results in the error message "The value you entered isn't valid for this field". This leads me to believe that the "All" text is getting filled into the primary key/ID column instead of the display column. The example instructs me to assign the display column number as the "Tag" property of the ComboBox - and in this case, my display column number is 2. However, this (and pretty much any other value I add) results in the aforementioned error message.
Any idea if Microsoft's example is even applicable to my case, or do I need to adjust their code somehow?
Check the Control Source property of your combo box. Sounds like it may be bound to a field in the form's record source. If you make it an unbound control (nothing in the Control Source property) you should be able to select any item from the combo's Row Source without Access complaining at you.
Say your combo's Row Source is a query like this:
SELECT id, disp_name
FROM YourTable
ORDER BY disp_name;
You can add an "all" row with a UNION query:
SELECT id, disp_name
FROM YourTable
UNION ALL
SELECT TOP 1 0, "**ALL**"
FROM AnyTable
ORDER BY disp_name;
AnyTable can be just that. If you happen to have a table which contains only a single row, use that one ... and you wouldn't even need the TOP 1 part. Just try not to use some ReallyBigTable as AnyTable.
Edit: Actually some ReallyBigTable would be fine if it has a primary key or other unique field which you can use in a WHERE clause to retrieve a single row:
SELECT id, disp_name
FROM YourTable
UNION ALL
SELECT 0, "**ALL**"
FROM ReallyBigTable
WHERE pk_field = 1
ORDER BY disp_name;
UNION ALL will return all combined rows. If you have any duplicate rows, you can thin them out by using just UNION instead of UNION ALL.

Ms access: Autocomplete field with values from another table

please forgive me for my poor english and my big ignorance on programming.
I'm using Ms Access 2003.
Let's suppose i have two tables:
Table1: ID (autonumber), [...], Keywords (memo)
Table2: ID (autonumber), Keyword (text)
I want:
1) As the user types letters in Table1.Keywords that my database searches in Table2.keyword for the nearest value and proposes it by autocompleting (just like google proposes a search word as you type)
2) When user presses ", " that he can add one more keyword in the same field (and the autocomplete still runs for this next value)
3) If he types a keyword not included in Table2 and press ", " that he is asked if he wants this value to be added in Table2
Well, i'm not sure if all these are clear... maybe they are a lot of things...
But i'd appreciate if you could help me...
Thanks in advance
J.
It would be complicated to do it with a single control, but with two controls, a dropdown list for choosing the value to add, and a textbox displaying the memo field, you could have the combo box's AfterUpdate event append a comma and the chosen value to the existing data. Something like this:
Private Sub cmbChooseKeyword_AfterUpdate()
If Not IsNull(me!cmbChooseKeyword) Then
Me!txtKeywordMemo = (Me!txtKeywordMemo + ", ") & Me!cmbChooseKeyword
End If
End Sub
You'd also want the rowsource of your combo box to not list items that are already entered, so this is one way that would work for a relatively short list of keywords:
SELECT tblKeywords.*
FROM tblKeywords
WHERE InStr(Forms!MyForm!txtKeywordMemo, tblKeywords.Keyword) = 0;
Then you'd add:
Me.Dirty = False
Me!cmbChooseKeyword.Requery
...at the end of the AfterUpdate code above (inside the End If):
Private Sub cmbChooseKeyword_AfterUpdate()
If Not IsNull(me!cmbChooseKeyword) Then
Me!txtKeywordMemo = (Me!txtKeywordMemo + ", ") & Me!cmbChooseKeyword
Me.Dirty = False
Me!cmbChooseKeyword.Requery
End If
End Sub
...and you'd want to add the requery to the OnCurrent event of your form, as well (so that when you arrive on a record, the combo box already omits any keywords that are already in the list).
Now, all that said, I'd completely recommend against doing this. This is a denormalized way to store the data, and this leads to problems:
what if you want to delete one keyword?
what if you want the keywords to be sorted in alphabeticsal order?
what if you have 100s of thousands of records and you want to search this field with LIKE "*Keyword*" -- will it bog down to be terribly slow (no indexes, and not used well even if there were)?
You really should use a proper many-to-many structure, with an additional table between the one where you're currently storing the keyword memo and your keyword list table. This "joins" the two, and would then give you a list.
You could then use a subform with a dropdown list to populate each row of the join table.
If you like presenting the keywords on reports as a comma-separated list (as you're currently storing them), you can write a simple function to do the concatenation for you at the presentation layer of your reports (concatenation functions for that purpose are a frequent Access question here on Stackoverflow).
Why not use a "Combo Box" and set its Row Source Type to Table/Query, and then make the Row Source a query on the second table. Just make sure you don't turn on Limit to List.
CodeSlave mentions a way that will work. But it will only work for one value. There is no way to do the multi-words-separated-by-commas thing. Only one word at a time.
As for the Adding new values. The combobox control support an OnNotInList event which can do what you say.
Seth