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 - vba

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

Related

MS Access one form to select table values and use to populate multiple fields on other form?

I have a table called GL_Account and IM_Productline
The table IM_Productline has various fields that need to be populated with a value from the field GL_Account.AccountKey (i.e. IM_ProductLine.InventoryAcctkey and IM_ProductLine.CostOfGoodsSoldAcctKey)
To populate the IM_ProductLine table I made a form "Product Line Maintenance" with all the fields. To populate the field IM_ProductLine.InventoryAcctkey I put a (magnifying glass) button behind the field with the following code:
Private Sub CMD_Select_GL_Account_Click()
Me.Refresh
If IsNull(Select_ProductType) Then
'do nothing
Else
Forms![Product Line Maintenance].InventoryAcctkey = Me.SelectGLAccountKey.Column(0)
Forms![Product Line Maintenance].Refresh
End If
DoCmd.Close
End Sub
So the button opens a form Called "Select GL Account" with a combo box that enable to SELECT GL_Account.AccountKey, GL_Account.Account, GL_Account.AccountDesc
FROM GL_Account; and when the OK button is clicked it writes the value from GL_Account.AccountKey to IM_ProductLine.InventoryAcctkey, closes the form "Select GL Account" and then refreshes the form "Product Line Maintenance" so the account number and description become visible for the user.
This all work fine but here's my question:
Now rather than creating a new form for every account field I need to populate (i.e. "Select Inventory GL Account" select "Cost Of Goods Sold GL Account" etc) I'd prefer to use the form "Select GL Account" to select and populate the 11 different account fields. So behind each xxxAcctkeyfield on form "Product Line Maintenance" is a (magnifying glass) button that when clicked pulls up the form "Select GL Account" and when "OK" is clicked it writes the selected AccountKey to the correct field on form "Product Line Maintenance"?
I'd greatly appreciate anyone's efforts to understand what I am trying to explain and point me in the right direction.
Ok, there is the issue that all 11 fields should not require to be "copied" since you have a relational database (you would ONLY store the row PK ID of that selection in the current report. (a so called FK (foreign key) value). That way, say you want to change the choice? Well then you could pop up that form - search + select the one record with all that information, and then upon return ONLY store the one value.
So, I would give some thoughts to the above - you want to leverage the relational database features. And as a result, you don't need to "copy" all that data. This is not much different then say creating a invoice. I can create the new invoice, but all of the address information, and the customer that this ONE invoice belongs to? Well, that is one column with a FK value that points to the customer. Once I select that one customer, then display of the customer name + address can be say a sub form or some such - but no need exists to "copy" that information. It would also means with near zero code, you could move a invoice between customers!!! - (just change the one fk column with to the new/different customer ID (PK) value.
Now, back to the question at a hand?
You can certainly pop up a form, let the user select, enter, pick and do whatever. And THEN you can have the calling code grab + pick out the values from that form.
The way you do this? It involves a not too wide known trick.
The code that calls the form can simply open that form as a dialog form. This will HALT the calling code, the user does whatever, and when done the calling code will THEN continue. Not only does the calling code continue, but it can get/grab/pull/take any values from that pop up form WIHOUT having to use global vars.
The approach is thus thus:
dim strF as string
strF = "frmPopAskInfo"
docmd.OpenForm strF,,,,,,acDialog
' above code waits for user input
if application.AllForms(strF).IsLoaded = true then
' user did not cancel, get values from form
me!AccountNo = forms(strf)!AccountNumber
etc. etc. etc.
docmd.Close acForm,strF
end if
Now the only other issue? Well, the "ok" button on the popup for DOES NOT close the form, what it does is set visible = False. This will kick the form out of dialog mode.
me.Visible = False
So, if the user hits the cancel buttton (close form) or hits the X upprer right (close form), then the form will NOT be loaded when your calling code continues. But, if they hit OK button, then you don't close the form, but ONLY set visbile = false.
This allows the calling code to continue, you are free to get/grab/take values from that form, and then once done, you close the form.
So a form close in that popup = user canceled the form.
So, a popup form, and even a modal form? They do NOT halt the VBA calling code, but a acDialog form does!
You can thus place 2 or 5 little buttons that pops up this form, the user can pick/choose/select/enter values. When they hit ok, your calling code continues, and you are free to pull values from that form. So while all 3-4 buttons might pop up that form, each individual button launch of the form can have code that follows and updates the given control the pop button was placed beside.

MSAccess VBA: Pass values from a subform to a seperate form

I have a form frmDetail that contains several locked fields I want populated only when another form has been filled out, in the name of having some kind of standardization in my data. This other form frmSignOut is used to enter in a date and location that will populate the fields on frmDetail. frmSignOut also contains a subform subULookup that looks up users from a different table using an identifier number. The resulting last name, first name and phone # should also be passed to frmDetail. I also hope to combine first and last name somehow into a Last,First format.
My approach so far has been to open frmSignOut modally with acDialog and I inserted Visible=False into the On_Click event on frmSignOut. Then I try to reference my subform fields and set them to the desired fields on frmDetail. I finish by refreshing and then closing the dialog form.
Private Sub CmdSignOut_Click()
DoCmd.OpenForm("frmSignOut"),,,,,acDialog
If CurrentProject.AllForms("frmSignOut").isLoaded=True Then
Set Forms!frmSignOut!SubULookup.PhoneNbrTxt=Me.ContactNbrTxt
DoCmd.Close (acForm), ("frmSignOut")
Me.Refresh
End If
End Sub
I have only been able to get this far, trying to pull the first field PhoneNbrTxt. I can get frmSignOut to open, I put in data and when I click my 'close' command button I get run-time error 438: Object doesn't support this property or method.
The line highlighted is where I try to reference my subform field. I also have a 'Cancel' button added to frmSignOut that just closes the form, I have no errors there.
Again I'm completely new to Access without much prior experience in anything related, I'd appreciate any knowledge you guys can throw at me.
EDIT: I've been able to successfully pull the value to Me.ContactNbrTxt by adjusting my code to the below.
Me.ContactNbrTxt = Forms!FrmSignOut!SubULookup.Form!PhoneNbrTxt
It looks like the missing part was the Form! right before the control name, along with formatting this correctly and dropping Set.
Im still trying to work out how to combine first and last name before also pulling those to frmDetail, if anyone can help there.

Use command button to open selected record on a form without filtering?

I have a continuous form which displays a small amount of data from each record in my table ProjectT (i.e. project name, status) and a command button in the footer which I would like to open the selected record in its expanded single form (where all of the relevant info is displayed).
At first I set this button up using Access's wizard, but realized that Access opens a selected record by filtering the data on the form. The problem with this is that once the expanded form is opened, I want a user to be able to move to other records without having to select to unfilter the results. If I change the button on my continuous form to simply open the expanded single form, is there code I can run to make the form open to the selected record without putting a filter on?
Initially I thought to set the expanded form's (named ProjectF) default value to Forms!ProjectListF!ProjectID (where ProjectListF is the continuous form and ProjectID is the autonumber primary key for ProjectT), but this was not successful, I think because there is more than one ProjectID displayed on ProjectListF.
Another thing to consider is that I have another button on my Main Menu form which opens the ProjectF form in data entry mode to prevent the user inadvertently changing/deleting an existing record when they are trying to add a new one; I have no idea if this might be important when trying to find a solution to my issue.
I'm open to any suggestion--I have an okay handle on SQL, and have delved into a little VBA but am completely self taught. Any ideas? Thanks!
You can open the detailed form with this command:
DoCmd.OpenForm "ProjectF", , , "[ProjectID] = " & Me!ProjectID.Value & ""

Delete function first or last record

My main menu is where all records are displayed. The user can navigate between records by a list table which has all the records.
When i use the this code to delete a displayed record, allways the first record gets deleted.
BindingContext(JobsDBDataSet, "T_Jobs")
.RemoveAt(BindingContext(JobsDBDataSet, "T_Jobs").Position)
Ive added an extra line in which the position should match the ID of the record.
BindingContext(JobsDBDataSet, "T_Jobs").Position = Job_IDTextBox
BindingContext(JobsDBDataSet, "T_Jobs")
.RemoveAt(BindingContext(JobsDBDataSet, "T_Jobs").Position)
NOTE: Job_IDTextBox is directly connected to the column in the database (I dragged it from the datasource menu into the form in details form)
My goal is so that i can delete the job that has been selected (and displayed) from the list box (with all records in it)
Right so ive changed my code to
BindingContext(JobsDBDataSet, "T_Jobs").Position = Convert.ToInt32(Job_IDTextBox.Text)
BindingContext(JobsDBDataSet, "T_Jobs").RemoveAt(BindingContext(JobsDBDataSet, "T_Jobs").Position)
And the same thing still happens: last job is deleted and not the selected one (from the listbox). I have a feeling its a problem regard the listbox, and maybe I'd firstly have to tell the program to change its pointer to the job ive chosen from the list box but i have no idea how to do this - and this is just an assumption.

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

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.