Add unbound combo box to form that can trigger a BeforeUpdate() event? - vba

I have a datasheet form ItemsForm based on table Items. Items is one-to-many related to table StatusHistory, between Items.ID and StatusHistory.ItemID. There is also a Status table, with the relationship between Status.ID and StatusHistory.StatusID.
I want to add a StatusBox combo box to ItemsForm so that when the user selects a Status value from the box and then moves out of the record, which should trigger the Form_BeforeUpdate() event, a new entry is added to StatusHistory with the Items.ID of the currently selected entry.
I've successfully added the StatusBox field to the form and populated its list by setting its RowSource with a query of Status. But there are two big problems:
I can scroll through the values in the box's list, but after I
select one, it doesn't show up in the field; the field stays blank.
When I select a value in StatusBox, and then click onto another
record, the Form_BeforeUpdate() isn't triggered. It seems that
Form_BeforeUpdate() is only triggered if I modify data in the
fields from Items that the form is based on. Is there a different event that I should be using here?

Solved it as follows:
The ID field for Status is actually named StatusID instead of
ID. Fixing this allowed me to enter values into the field.
I put the code into the BeforeUpdate() event for StatusBox, viz:
Private Sub StatusBox_BeforeUpdate(Cancel As Integer)
End Sub
This means it gets triggered whenever I select an item in the list, rather than when I move to a new record, but for now that's all I need.

Related

How do I validate a Form input field with a Table row value in microsoft access?

I am having issues with setting a Validation rule in Access.
I have a database with the tables Clients, TypeClient, Sales, SalesList, Items.
I have a form for Sales, with a sub-form SalesList inside which has a relationship with Items in order for me to put several stock items in Sales instead of only one item.
Inside Sales table is ID, Date Sold, ID Client.
Inside SalesList is ID_List(referenced to ID in Sales), ID_Item(referenced to ID in Items), Quantity.
Inside Items is ID, Name, Stock(how much we have in stock), Price
The issue is that I am trying to validate the data I enter in the sub-form Quantity field to be higher than 0, but no higher than the available stock.
The issue is that I have tried using the expression builder to get the value from a calculated query that has 2 fields - the ID and the value for that id, with criteria that is for the ID to get it from the main form, the sub-form, the combo box input and the query works.
But when trying to get it like this:
It shows an error "The expression [Query bla] you entered in the form control's ValidationRule property contains the error The object doesn't contain the Automation object 'Query bla'".
I tried using directly the table Value(but it won't work anyway as it doesn't know for which field to get the stock value from), still the same error. I guess it can't reference to anything else? Normal validation rules work, but I want to validate it not to exceed the value of the available stock for the item I am selling now.
Nowhere on the internet there is a tutorial how to do it with expression builder. How do people validate their fields then?
It doesn't stop me in this case to sell 200 items when I currently have stock of only 2 of them, for example.
Note: I have tried DlookUp in expression builder, straight up tells me No.
Sample wrong validation rule expression builder code:
<=[Query bla]![Stock]
<=[Items]![Stock]
I am currently using VBA and fetch the record I need(the current stock) with one of the following and my unbound text is changing on every subform to the same, it shouldn't happen like that. What can I use to populate a field for each record uniquely:
Private Sub ID_Product_IZBOR_Click()
'Me.Stock_ValueField = DLookup("[Nalichnost]", "Stoka", "[ID]=" & Me.ID_Product_IZBOR)
Me.Stock_ValueField = Me.ID_Product_IZBOR.Column(2)
End Sub
Partial solution: I created a new Dim as Integer and fetched the records based on the ID provided by the field in the form and used BeforeUpdate to validate the current stock. Unfortunately the only way to see the current stock level is to click on the combo box where you choose your product and check the column for that one, it doesn't show anywhere else :(
Don't use the expression builder (I NEVER do) - just type the needed expression in property.
>0 AND <=DLookup("Stock", "Items", "ID=" & [ID_Item])
Another approach is to return Stock in textbox ControlSource then ValidationRule references that textbox. Also, user can then see the quantity limit. Methods of pulling the Stock value from Items table:
include Stock field in Items combobox RowSource - textbox then references column by its index (index begins with 0): =[cbxItems].Column(2); VBA may be needed to Requery combobox after record entry/edit is committed to table.
include Items table in form RecordSource - bind textbox to Stock field (Locked yes and TabStop no)
DLookup() expression in textbox ControlSource
Use ValidationText property to give users a custom message.
However, ValidationRule will not prevent user not entering any value if they skip the control. If you want to make sure a value is entered, either set field as required in table or use form BeforeUpdate event to validate record data.

When the user clicks a text box on my form, I need to assign an ID to the current record if there isn't one already

I have a form, frmEvent, for editing and creating records. Each record represents an Event. I have a pop-up form that displays the many-to-many relationships that associate one or more Persons to the current Event. This pop-up form is opened when the user clicks a text box on frmEvent.
The pop-up form displays all of the records in tblEventPersons where EventID = the ID of the Event record that is currently open. This normally works great. However, when my form is used to create a new Event record, Access does not assign an ID for the new Event record until at least one field has been changed. If a user creates a new Event record and tries to immediately open the frmEventPersons form, they get an error because the new Event record does not yet have an ID assigned.
I'm sure there's a very simple solution to this, but my searches have not yielded anything useful.
Well it is assumed that the main form has a record, and has some data and has a "ID" as you well asked.
However, if the form is moved to a new record, and you want to launch that next form that requires and needs the current forms ID that as you WELL note has not yet been generated?
Well, keep in mind that you current form WILL IN FACT generate the ID (assuming a auto number PK id column) if the current record has been "dirtied". We thus assume that the current record had SOME data editing. If it has NO EDITING done, then it actauly turns out is a bit of a trick to get Access force feed and generate that ID.
About the MOST easy way?
Dirty some field/column in the current form.
eg:
if isnull(me!ID) then
' this record does not yet have the PK id
' dirty some bound control.
me.MyEditDate = date()
end if
me.Dirty = false ' this will force a recrod save - gereate the "ID" you want.
docmd.Open "frmDetails",,,"FKColumn = " & me!id

Control Source of a text boxes set to DCount function - Refresh issue

I'm setting the control source of text fields to return the value of a function (multiple fields with different filtering conditions). The form has a combo box with a list of years: when the user selects a specific year, the on change event triggers a refresh of all the fields.
My problem is the fields don't show any values unless after combo box's On Change events. I have to click on the form/fields before the values start showing up.
I tried to do form refresh & field's requery but doesn't work.
The text field's Control Source is set to:
=SummaryReport("Projects","G","1",[Forms]![frmSUMMARY_REPORT]![cmbYEARS])
What I'm trying to do is when the user selects a year from a drop down, the fields values are updated & displayed by the On Change event - currently they seem to be updated but are not showing unless I click on the screen and that's when values start showing up in each field.
The method to update calculated fields is Me.Recalc (or myForm.Recalc):
https://learn.microsoft.com/en-us/office/vba/api/access.form.recalc
Try this instead of .Refresh.
Also I think the better event to use is After Update instead of On Change for a combo box.

How to make a total column that updates automatically in Access.

In access I am trying to get my total value to be equal to the sum of the all of the different values where the order number is the same.
My current code is as follows;
= SUM( Forms![OrderLine]![Total] ) Where( Forms![OrderLine]![OrderNo] = [OrderNo] )
This however gives me an error. How else would this be done?
Thanks
It sounds like you have an Order form and an OrderLine subform. Add a Form header/footer to your OrderLine form and put a text box in the footer. Put a SUM function in the Control Source of the footer text box to generate the aggregated value you need from the order line item rows.
On your main form, set the Control Source of the text box you want to display the order total equal to the name of the invisible text box in the subform. The control source on the main form text box will resemble SubformControlName.Form.AggregateTextBoxName.
You may need to play with the visibility settings of the header/footer, text box, form view mode, etc. to get the presentation you want, but this works even with the subform in datasheet view. The key is to get a text box somewhere on the subform to calculate the value you need on the parent form and then reference it inside the subform control from the parent form.

How we can grab value from list box and fills automatically related text box in new form

I have a list box and its row source is "tblitems" with bellow fields.
Now I like when right click on this list box and select one option for example "new task" it opens new task form and automatically Grab the item number from a list box and fills related text box "item number" in "new task" form that is bounded to table "tbltask"
Now when I press "Apply" button it insert new record in "tbltask".
tblItems
item number (pk)
item name (text)
tbltask
task number (auto number,pk)
item number
enter image description here
Getting a value from a list box in a form is:
Me.List_Box_Name.Value
Or if you have unbound values then get it based on the column:
Me.List_Box_Name.Column(2)
or whichever column you need.
You can then populate fields with DLookup or a recordset. Then if you want this to happen when you open a new form, you may want to look into this:
Private Sub Form_Load()
'Stuff you want to happen when that form loads
End Sub
Updated
The following will print out the value each time you click it. You can use this method to trigger a new form to open, or you can have a user click a submit button afterwards.
Private Sub Test_List_Click()
Debug.Print Me.Test_List.Value
DoCmd.OpenForm "Form_Name"
End Sub
Now I'm not exactly sure the best way to add your variable to the opened form. If it were me with my limited knowledge, I would add a global or public string and have the Form_Load() check to see if that string length is greater than 0. If yes then it will populate the field.
Hope that helps
Update 2
Actually this link will help you populate a field from previous form:
MS Access - open a form taking a field value from a previous form