Access VBA: write on selected record - ms-access

The form shows one record per time. I would like that, by clicking a button, the system puts a value on the table of the DB, in the row of the selected record. Something like:
DoCmd.RunCommand acCmdSelectRecord
DoCmd.RunCommand write "example" in the field <FieldName> of the selected record
Is it possible something like that?

The simplest method is bind the field to a textbox, then set property Visible of the textbox to False.
Now, call this code in your OnClick event:
Me!NameOfTextbox.Value = "example"
' Save the record.
Me.Dirty = False

Related

How to test if current record has changed when command button clicked on continuous form

In ms access, I have a mainform with 2 subforms. SubformA is a continuous form with record title and a transparent button overlay for each record. SubformB contains the detail of the selected record (this is on tabcontrol elsewhere within the mainform, mimicking a popup overlay).
What I want to happen is:
1. Clicking a record subformA displays subformB and filters it to that record.
2. Moving through records on subformA updates so that subformB always displays the corresponding record.
3. Clicking a record on subformA hides subformB again ONLY IF it is the record that is currently being displayed.
However I cannot work out how I can test for if the current record is the one that was clicked because as soon as I click the button, if it is not the current record, the current event fires first, making it the current record, and hence always hiding subformB.
I tried using a variable to check at the start and end of the current event if the id on subformB stays the same. However, the current event of course does not trigger in the situations where the record has not changed, which is when I need to test this variable.
Stripped down/pseudocode in subformA for what I have tried to do:
Sub Form_Current
If subformB.Visible Then set filter on subformB to ID = subfromA.ID
End Sub
Sub cmdButton_Click
If subformB.Visible Then
If subformB.ID = subformA.ID Then
Hide subformB
Else
'code never gets to here because the condition is always true
'do nothing - current event has already set the filter
End If
Else
Unhide subformB
Set filter to ID = subformA.ID
End If
End Sub
Is anybody able to help me here? Thanks.
EDIT: what I am asking is how can I test the current record ID against the record ID of the record where the command button was clicked - but the record ID when clicking the button is of course just taking the new current record ID. Therefore it is comparing old current record ID to new current record ID, the problem being how do I store the old ID but prevent it from being updated again before the condition is tested.
Set a module level private field and set its value to the value:
a) of the selected ID if new.
b) zero if same ID supplied (clicking the button twice).
Private mSelectedId as Long
Sub cmdButton_Click
If Me!ID = mSelectedId Then
mSelectedId = 0
Else
mSelectedId = Me!ID
End If
FilterSubFormB
End Sub
You could expand this to filter subformB:
Private Sub FilterSubFormB()
With Me.Parent.SubformB.Form
.Filter = "ID=" & mSelectedId
.FilterOn = True
End With
End Sub
An alternative to checking the ID that might work for what you're doing is to:
1. Add a hidden, unbound textbox to your form.
2. Use the click event to stash the ID in the textbox, after the check takes place.
3. Instead of checking the ID in the click event code, check the value saved in the textbox. Untested, but something like this.
Sub cmdButton_Click
If subformB.Visible Then
If subformA.ID = HiddenTextBox Then
Hide subformB
Else
End If
End If
Else
Unhide subformB
Set filter to ID = subformA.ID
End If
HiddenTextBox = subformA.ID
End Sub
You should not have to filter on the other subform, just make the record the current record.
This article will show you how - it may also be a bit more intuitive for the user:
Synchronizing Multiple Subforms in Access

BeforeUpdate event of a linked subform control firing multiple times

Good afternoon,
I have to maintain an Access form which contain a linked subform (using Master and Child fields).
Basically, in the main form, the user choose a value in a combobox and the subform is automatically updated.
My issue is that I have a BeforeUpdate event on one field of my subform which is preventing to update the field (Cancel=true) when it does not meet the criteria. The alert msgbox should appear once if there is any error in the field but the BeforeUpdate event is always fired 3 times for unknown reason.
I have created a simple accdb file which reproduce my issue. It is located here: https://www.hightail.com/download/bXBhU2V0Q1JxRTFsQXNUQw.
Open the Form1, choose a value in the combobox and then try to update one of the letters in the subform by X and you will get the msgbox appearing multiple times.
Thanks in advance for your help on this issue as it's driving me crazy.
Sylvain
This happens because you do not change the value of Text0 back to what it was.
Try this
Private Sub Text0_BeforeUpdate(Cancel As Integer)
If Me.Text0 = "X" Then
MsgBox "Wrong value"
Cancel = True
Me.Text0.Undo
End If
End Sub
OK finally found the solution.
It was related to the text box used for storing the Link master fields used by my subform. This control contains the value of my combobox in order to filter out my subform.
The control source definition of this link master field used to be:
=myCombobox.column(0)
By replacing the definition by just:
=myCombobox
The beforeUpdate event in my linked subform is only triggered once and behaves as expected;
Private Sub Text0_BeforeUpdate(Cancel As Integer)
If Me.Text0 = "X" Then
MsgBox "Wrong Value"
Cancel = True
End If
End Sub
I can not explained the magic of why it is behaving that way but this is how I made it worked.
Sylvain

Make fields visible in MS Access form as certain fields are completed

I am building a form In MS Access for users to input data but there are too many possible fields. Most of the time only about half the fields will be used.
I thus would like to have certain fields appear only depending on what the user inputted on a prior given field.
Ex: user enters project number, title, then he checks a "yes/no" engineering. since he checked it this means engineering is impacted so a dozen fields that the user will have to fill out appear.
Is this possible:
1)without VBA
2)with VBA
Probably not possible without VBA.
With VBA for example:
Ensure your form is in Design view
Right click on your Combo Box, Build Event, Code Builder
This opens the code behind your form. It drops you into the default code for the BeforeUpdate event. We want the Change event instead, so at the top right change the drop down from BeforeUpdate to Change. This will give you a bit of code like this:
Private Sub Field1_Change()
End Sub
Inside here, you want to check the value of the combo box and hide fields as required:
Assuming the name of your combo box is Field1 (yours of course will be different), you add some code so it looks like this to hide Field2:
Private Sub Field1_Change()
If Field1.Value = "Yes" Then
Me.Field2.Visible = False
End If
End Sub
Note you need to know the names of all your fields - this is in the Other tab, Name field in the properties box (F4). You should give all of your fields sensible names so you can understand what is going on in the code.
For a check box, follow exactly the same procedure, but you probably need to use the Click event. Just experiment.
Sample check box code:
Private Sub Check5_Click()
' Note: vbTrue = -1
If Me.Check5 = vbTrue Then
MsgBox ("Ticked")
Else
MsgBox ("Not Ticked")
End If
End Sub
I have a form that will show certain fields after a list box value is selected. I use the AfterUpdate function. It has worked so far. My code is below. ProjectName and ProjectNumber are fields you only want displayed if Engineering is selected. OtherName and OtherNumber are fields you only want to show if it is a "NotEngineering" project.
Insert this code by clicking on the Field that selects the project type, go to the Event tab on the property sheet, and click "After Update" and choose code builder and paste in VBA.
Private Sub ProjectType_AfterUpdate()
If ProjectType.Value = "Engineering" Then
Me.ProjectName.Visible = True
Me.ProjectNumber.Visible = True
Else
Me.ProjectName.Visible = False
Me.ProjectNumber.Visible = False
End If
If ProjectType.Value = "NotEngineering" Then
Me.OtherName.Visible = True
Me.OtherNumber.Visible = True
Else
Me.OtherName.Visible = False
Me.OtherNumber.Visible = False
End If
End Sub
There is a way to do not-quite-this without VBA. I'd definitely recommend VBA though, because you can do a lot more with it.
Rather than hiding, try disabling the unnecessary fields with conditional formatting by expression.
right-click on the control you want disabled.
go down and click on 'Conditional Formatting'
Add a new rule
Select 'Expression is'
example:
[fld1]="yes"
hit the disabled box
click ok
click ok
now the control you've selected will disable if field 1 has "yes" selected.
I have the same problem and I did the following:
Private Sub Field1_Click()
If Field1 = "Yes" Then
Me.Field2.Visible = True
Else: Me.Field2.Visible = False
End If
End Sub
but now I have other problem, when I change record, the field that I choosen to be visible in the last record is now visible on the current record, although I have not choosen any option.
Thank you,

How to keep Form_Current actions from triggering table validation errors?

I have a table T with a required text field item, and a text field userID that is meant to fill in the current user's login ID. I have a form mainForm with a subform TForm based on this table. To make sure that each record has the user's ID I have added the following event to TForm:
Sub form_current()
Me.userID = Environ("username")
End Sub
When I open mainForm, I get this error message immediately on opening:
You must enter a value in the 'T.item' field.
I think what is happening here is that the form_current() event makes Access think that I've attempted to complete entry of a new record while T.item is still blank, which violates a table constraint because that's a required field. Curiously, though, this only happens when I open mainForm; when I open TForm by itself, I don't get this error message on opening.
Should I be using a different event to fill in the user's login ID for each field? Or is there a better way to use form_current() for this?
First way.
Create a function in a module:
Public Function getUserName() As String
getUserName = Environ("Username")
End Function
Then open property window for your TForm, select "userId" field, select "Data" tab in property window, find row with "Default Value" and put next expression: =getUserName().
I don't know why but access don't see Environ() function.
Second way.
Implement OnLoad event like this:
Private Sub Form_Load()
Me.userID.DefaultValue = "=""" & Environ("username") & """"
End Sub

How to set the value of an unbound textbox with a default value to an empty string with Access VBA

I have a database with information about visitors to our department. Here is my setup: A user selects a visitor name from a listbox. Access assigns the values from that visitor's record to temporary variables and opens an unbound form where those variables are the default values in the text field. When a user changes a value in a textbox, an After_Update event uses SQL to update the corresponding field in that visitor's record and assigns the new value to the temporary variable.
After_Update example:
Dim strRUN As String
strRUN = updateVisitorOnDirty(Me.txtVisitorTravelMethod, "VisitorTravelMethod", 1)
HideWarnings (strRUN)
TempVars!strVisitorTravelMethod = Nz(Me.txtVisitorTravelMethod.Value, "")
"updateVisitorOnDirty" is a function that returns SQL to update a field (specified in second argument) in the table with visitor information with the first argument. (The number at the end is says it's a string.) "HideWarnings" turns warnings off, executes the SQL, and then turns warnings back on.
My problem:
When a user clears a textbox, the After_Update event makes the textbox revert to it's previous value.
I thought at first that maybe the unbound textbox was reverting to its default value when it was cleared, but I put a breakpoint in the sub that fires during After_Update:
If I change a value in mytextbox from a to b, debug.print shows the value of mytextbox as b. If I change a value in mytextbox from a to (blank, or empty string), debug.print shows the value of mytextbox to still equal a.
My workaround has been to include a little "x" near the textbox that the user can click to 1)clear the textbox, 2)update the temporary variable, and 3)update the table. It works fine, but it seems like there should be a better way. Help?
Please let me know if you need any other information or if I should otherwise re-word this. I come here all the time for answers, but this is the first time I've actually submitted my own question. Thank you!
(I edited this to make the code show up correctly...didn't leave a line before.)
I figured out that the unbound textboxes were reverting to their default value when a user tried to make them blank. To stop them from doing this, I put this in the AfterUpdate of the textboxes:
Call ResetDefault(Me.textbox1.Text, Me.textbox1)
And defined the function:
Public Sub ResetDefault(ByVal strChange As String, ByRef txtCurrent As TextBox)
If Nz(strChange, "") = "" Then txtCurrent.DefaultValue = ""
End Sub
That is, if a user cleared a textbox, the default value of that textbox was set to "", allowing the textbox to actually go blank.
I think the best approach is to scrap the after_update event on your text boxes and instead either put a save button on your unbound form so that all updates are written in one pass, or capture the forms closing event and update your table then.
This is the advantage of using unbound forms, you do not have to comit data until you are absolutely ready to, but with using an after_update event you are almost mimic-ing the behaviour of a bound form.