I modified some code I saw which opens a word template and populates it by replacing bookmarks with the current record. Everything works fine until I try to write content from a linked (lookup) table, e.g.
Table A:
ID
Name
Description
JobType (lookup drop down list by JobTypeID in Table B)
Table B:
JobTypeID
JobType
Form C:
ID
Name
Description
JobType
This all works as planned in the form, and works for most when I click a button with:
'code for connecting to word and opening templates works fine *snip*
With WordApp.Selection
.Goto what:=wdGoToBookmark, Name:="bmName"
.TypeText [Name]
But when I use:
With WordApp.Selection
.Goto what:=wdGoToBookmark, Name:="bmJobType"
.TypeText [JobType]
it doesn't write the job type thats stored in the table or displayed in the drop down box on the form.... it writes the JobTypeID (1,2,3,4....) used in the link.
Ive also tried using
me.JobTypeComboBox.value
from the form, but this also displays the ID.
Can someone point me in the right direction please.
A lookup field stores one value but displays a different value. In your case, you seem to want the displayed value instead of the stored value. Two ways to deal with that ...
Use a query where you INNER JOIN Table B to Table A. Then including [Table B].JobType in the query SELECT list should give you what you want.
Use a DLookup expression to retrieve the [Table B].JobType value for the current [Table A].JobType
The situation is confusing because [Table A].JobType is actually a number which corresponds to [Table B].JobTypeID. And in [Table B], the field named JobType is something else ... perhaps a text field.
Hopefully those details are less confusing for you than they are for me. If this was my application, I would rename [Table A].JobType to [Table A].JobTypeID and leave it as a simple numeric field, not a lookup field. And probably also create a relationship between the 2 tables based on JobTypeID.
Related
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
I am trying to build a query which will look at the data in two fields in two different tables and check to see if the data is the same, if it is I want it to return the number of times it is matched, if it isn't I simply want it to return the text saying "No viewings".
I have constructed this query in my access database which has the field from the first table "Property" and the second field I want it to compare the data with, "Viewings". I have build the following expression using the build tool, however I am stuck to make it work since every time I get this error message when trying to run the query: "Your query does not include the specified expression 'Property Viewed' as part of an aggregate function."
totalViewings: IIf([Viewings]![Property Viewed]=[Property]![ID],Count([Viewings]![Property Viewed]=[Property]![ID]),"No Viewings")
Any help how to overcome this error would be very appreciated.
Thanks
I would suggest doing something like this:
1) Assuming this is something you are developing yourself, make sure your data structure is all in order first. Since I dislike relatively code-hostile identifiers, I'd have the tables as so -
Properties - PropertyID (AutoNumber, primary key), HouseNumberOrName, Street, etc.
Viewings - ViewingID (AutoNumber, primary key), PropertyID (Number/Long Integer), ViewingDate, etc.
In the Relationships view, Properties.PropertyID would then be set up to point to Viewings.PropertyID in a one-to-many relation.
2) Your actual query I would then break into two, the first to compile the data and the second to format it for display. The first would go like this, saved as ViewingCounts...
SELECT Properties.PropertyID, Count(Viewings.PropertyID) As ViewingCount
FROM Properties LEFT JOIN Viewings ON Properties.PropertyID = Viewings.PropertyID
GROUP BY Properties.PropertyID;
... and the second like this, saved as ViewingCountsForDisplay:
SELECT Properties.*, IIf(ViewingCount = 0, 'No viewings', ViewingCount) AS Viewings
FROM Properties INNER JOIN ViewingCounts ON Properties.PropertyID = ViewingCounts.PropertyID
ORDER BY Properties.PropertyID;
I have a lookup field in my table based on another table. I'm having trouble filtering those values based on another field that is entered prior to the field.
Is it possible to filter a lookup field based on another field?
EDIT
Let me try and clarify my original question, sorry about that. Ok, so I have a table1 that has the following fields: ID, Name, Logo.
If a user enters a specific name in the Name field, when they click on the Logo field, it'll only display those values associated that are similar to the name entered. Does that make any sense? If it does make sense, would there be an easier suggesion on accomplishing this task?
If you're talking about inside a table, the answer is "No". You can create cascading combo boxes on a form, but you can't base a lookup value in a field of a table off of a different field in that table (or the field in any other table).
Here is an example of how to handle filtering a combo box based on the value selected in another combo box:
I have the following form:
The combo boxes are named cboIntPN and cboManPN.
The Row Source for cboIntPN is set to: SELECT uniq_key, part_no, revision FROM inventor. The Row Source for cboManPN isn't set to anything.
When the user selects a value for Internal PN the following AfterUpdate Event is triggered:
Private Sub cboInternalPN_AfterUpdate()
[cboManPN].RowSourceType = "Table/Query"
[cboManPN].RowSource = "SELECT uniqmfgrhd, mfgr_pt_no FROM invtmfhd " & _
"WHERE uniq_key = '" & cboIntPN.value & "'"
End Sub
It sounds like he is having the same issue as me. I also wanted to filter a field in a table for data entry on another field's input and my conclusion is "it is time I stopped entering data manually in tables and begin to create Data entry forms. I was putting this task off until later, but if I don't do it now, I might make worse trouble for myself later.
Btw, what an old thread.
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.
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.