In one database form code generates a new record:
Me.Section(0).Visible = True
DoCmd.GoToRecord , , acNewRec
Me!ExhibitName.SetFocus
The focus is not set on the data textbox ExhibitName. The focus is nowhere to be seen.
In another database, the same code (except the text box is DistributorName) does set the focus on the proper data entry box.
In the one that fails, if I enter Forms!ExhibitForm!ExhibitName.setfocus<Enter> in the Immediate window the focus goes to the proper data entry text box.
If I trap on the instruction after the Me!Exhibit.SetFocus and execute the Me!ExhibitName.setfocus<Enter> command in the immediate window, then continue execution, the focus is correct.
It feels like some indeterminate delay is needed between the 2nd and 3rd command in the above sequence. Either that or I failed to set some control somewhere.
A workaround is moving the focus to another control and then back to the first control. Like this:
DoStuff
Me.Section(0).Visible = True
DoCmd.GoToRecord , , acNewRec
Me.anotherControl.SetFocus
Me.ExhibitName.SetFocus
This did not work:
Me!anotherControl.SetFocus
Me!ExhibitName.SetFocus
This did work:
DoEvents
Me!ExhibitName.SetFocus
Thanks!
Related
My Access REPORT has a text box with the Record ID that looks like a button with an on click event to go to a form for that specific record. This works great, but when I return to the report I cannot see which record was clicked. I want to temporarily change ONLY the record that was clicked until another record is selected.
The reason I want this on a report and not a form is because I want the user to have a quick way to proof read in the format needed to print, and make a change or check a detail if necessary, then update the report AFTER all proof reading and updates are completed and before final print. But with many records on the screen it is easy to lose track of which record you were checking when returning from the form.
I tried:
Private Sub btn_txt_GoToTransaction_Click()
Dim vColor
vColor = RGB(51, 204, 51) 'green
Me.btn_txt_GoToTransaction.BackColor = vColor
DoCmd.OpenForm "Account_frm", acNormal, , "[TransactionID]=" & Me.TransactionID
End Sub
But this does not work because every button turns color not just the selected record.
Any suggestions? Thanks.
This is a great question because there are many benefits to highlighting a row or item in an Access Report. You are not able to just change the button color in one row only, but you can highlight the whole row so the user knows where they were.
Here are two methods to accomplish this:
Method 1 - Click on a Label
This works great in newer versions of MS Access when using Report View. Use a Label Control instead of a Button. You could make the label look like a button if you format it that way. I prefer to stretch an invisible Label across the whole row on top of all the other controls in that row. Then if you click anywhere in the row, it automatically selects that row and then runs whatever code you have in the OnClick Event. This works best if the Label is not linked to a Text Box.
This picture shows an example of how this method looks. You can click anywhere in the row and it highlights that row with the red outline and grey background.
This is very simple and works well but there are a couple disadvantages:
1- You can not change the color of the highlight.
2- If any of the text boxes CanGrow, the row height may be higher then the Label and create areas where the invisible label doesn't capture your click.
3- Clicking on a Text box does not work for this method.
Method 2 - Change Color of a Text Box
In order to just highlight one row or one piece of data in a report, we can use the "FormatConditions" property. This is the same as Conditional Formating from the MS Access design interface but we are going to change it programmatically on the fly. You can't do this with a button or label - it needs to be a Text Box with unique data, such as your TransactionID.
This picture shows an example of how this method looks. You can set the color of the highlight if you follow the steps below.
STEP 1) I recommend that you add a text box to your report that stretches from the left to the right, set the Back Color and Fore Color to White, set the Control Source to TransactionID, and set the Name to TransactionID. Then right click on this text box and select Position > Send To Back. This works best if the other text boxes and labels on the report have a transparent background.
STEP 2) Add this code:
Private Sub HightlightRow(intRowID As Integer)
With Me.TransactionID.FormatConditions
.Delete
With .Add(acFieldValue, acEqual, intRowID)
.BackColor = vbGreen
.ForeColor = vbGreen
End With
End With
End Sub
STEP 3) Also change your button code to call this subroutine like this:
Private Sub btn_txt_GoToTransaction_Click()
HightlightRow Me.TransactionID.Value
DoCmd.OpenForm "Account_frm", acNormal, , "[TransactionID]=" & Me.TransactionID
End Sub
STEP 4) I like to set it up so if the user clicks anywhere in the row, it will pop up with a modal with more detail regarding that row. Also, the user can't make any changes to the data in the Report View, so I use the pop up modal to allow changes. To accomplish this, I do a couple more things:
First, we need to add the code to the OnClick event for every control in that row. Ofcourse, each OnClick event will simply can that subroutine HightlightRow Me.TransactionID.Value
Second, if the user clicks on a Text Box, the Text Box gets the focus and hides the highlight. Therefore, I like to set the focus to something else. In your case, you could set the focus to the button by adding this line to the end of the HighlightRow subroutine: btn_txt_GoToTransaction.SetFocus
In my case, I am not using a button, so I set up a tiny Text Box with = " " (just an equal sign a space in quotation marks) as the Control Source. Then I position this tiny Text Box to the far right. And in the HighlightRow subroutine, I set the focus to this textbox.
STEP 5) You may also want a button or method of removing the highlight. To do that simply have the code run this line:
Me.TransactionID.FormatConditions.Delete
I'm working in VB.NET, Visual Studio 2017. I have a combobox with DropdownStyle = Dropdown. If the user types something invalid in the text field of the combobox (invalid means it doesn't match a value in the combobox) then we display a message and then return focus to the text field with the text highlighted, so they can see what they typed. The message is displayed from the Validating event.
This works fine if they don't open the dropdown. If they do open the dropdown and, while it is open, they type in an invalid entry, the message displays but the entry they typed clears.
I have put in debug statements to see what events are firing. Before the message displays, I get a DropDownClosed (text is still there), then a TextChanged (text is still there), then a second TextChanged (text is now empty). I think something about losing focus to display the message may be triggering something, but I can't figure out what.
I can save off the text and then replace it after the message displays, but while the message is up, the text field is blank.
Any ideas?
While I still don't understand the series of events that causes the problem, I found a solution. Just before the message is displayed from within the Validating event of the combobox, I set focus to the combobox. I'm guessing that tabbing away from the invalid entry loses focus, and because the dropdown is open, it then closes which somehow clears the entry. Go figure.
Here is the code from the validating event:
If testInList Then
ResultTextBox.Enabled = True
Else
TestComboBox.Focus
'If test is not in combobox, display message.
MyUtility.MicroUtilities.DisplayMessage(
My.Resources.RES_MSG_INVALID_TEST, MessageBoxIcon.Information, , , True)
e.Cancel = True
End If
The "TestComboBox.Focus" line has fixed the issue of the text disappearing. However, if the user's invalid entry is a partial match for an item in the dropdown, then the text in the text field of the combobox is updated to that item, so now it looks like they typed a valid entry but are getting an message that it's invalid. For example, if there is an entry in the dropdown of "NAMC" and they type "NA" (with the dropdown open) and tab away, the entry changes to "NAMC".
Any ideas on how to prevent that?
p.s. The AutocompleteMode is set to None.
So again, I don't understand the sequence of Events that causes the issue, but I've found something that works. If I move the new "TestCombobox.Focus" line outside of the If condition, the text remains in the text field before, during and after the message displays:
TestComboBox.Focus()
testInList = TestEntryValid()
If testInList Then
EnableResultFields(True)
Else
'If test is not in combobox, display message.
MyUtility.MicroUtilities.DisplayMessage(
My.Resources.RES_MSG_INVALID_TEST, MessageBoxIcon.Information, , , True)
e.Cancel = True
End If
This moves the .Focus before TestEntryValid, but I don't see anything in there that would trigger any events:
Private Function TestEntryValid() As Boolean
Dim item As String = TestComboBox.Text
Dim validTest As Boolean = False
If item.Length > 0 Then
Dim index As Integer = TestComboBox.FindStringExact(item)
If index > -1 Then
validTest = True
End If
End If
Return validTest
End Function
If anyone can explain why this works, I'd love to know. If not, thanks to everyone who responded!
Recently I am messing ( a lot) around with setting focus to my subform. For some reason I can't set the focus to my subform and it keeps giving me the error: can not find the field '|1' referred to in your expression I tried multiple ways to set the focus but all of them won't work.
What I tried so far:
Forms("frmArtikelSubInkoopHistorie").SetFocus (Set focus directly to the subform)
[Forms]![frmArtikelen].[frmArtikelSubInkoopHistorie].SetFocus (Set focus to the subform with reference to it's main form)
[Forms]![frmArtikelen].[frmArtikelSubInkoopHistorie].SetFocus
[Forms]![frmArtikelen].[frmArtikelSubInkoopHistorie].[Form].[Tekst33].SetFocus (First set focus to the subform itself and then setting focus to the subforms control)
First I tried to set the focus on the Load event of the main form but this caused the error as well.
Then I tried to set the focus in the load event of the subform itself but this event never gets fired.
Lastly I tried (and this is where I left off) to set the focus in the change event of my tab control (the subform resides in one of the tabs):
Private Sub TabbestEl91_Change()
On Error GoTo eri
Select Case TabbestEl91
Case 3 'Inkoop Historie
'Forms("frmArtikelSubInkoopHistorie").SetFocus
[Forms]![frmArtikelen].[frmArtikelSubInkoopHistorie].SetFocus
[Forms]![frmArtikelen].[frmArtikelSubInkoopHistorie].[Form].[Tekst33].SetFocus
End Select
eri:
MsgBox (Err.Number)
MsgBox (Err.description)
End Sub
I guess the focusing failing because the subform isn't loaded yet on the moment it sets the focus, this is just an assumption though and I thought this would be fixed if I would set the focus in the tab change (the subform should be loaded by then).
P.s. found multiple posts on this subject but non of them fixed my problem or were totally different than mine.
Any ideas to get this fixed? Thanks in advance!
I would try the following syntax:
Forms![frmArtikelen]![frmArtikelSubInkoopHistorie].Form![Tekst33].SetFocus
Note the exclamation marks that have been added. Also, it may sound counter intuitive but I believe that when a form loads, the subform loads before the mainform.
I don't understand at what point you actually want to apply the setfocus, in order to understand where the event should go.
Are you aware that you don't need VBA to select the tab index of the subform to 0? and then set the tab index within the subform so that tekst33 is 0?
I tried to set focus on my subform date after a new record is created.
Sequential code to set focus on the subform then the subform field might work for you:
from parent form setfocus on the subform first
Me.SF_DRL_Scheduling.SetFocus
then point to last record of the subform (even if filter is active)
DoCmd.GoToRecord , , acLast '
finally refer to the field in subform
Me.SF_DRL_Scheduling.Form.DrScDte.SetFocus
On Error Resume Next
'For second time doesn't run code below and raises error, so we need On Error Resume Next above. but with one more time else again run it code, there is ok runing all codes and process below
Me.frmArtikelSubInkoopHistorie.SetFocus
Forms![frmArtikelen]![frmArtikelSubInkoopHistorie].Form![Tekst33].SetFocus
Hopefully I can explain what I want to do well enough...here it goes...
I have a data entry form...the user will be entering employeeIDs. Once in normal operation, most people will be entering only their own EmpID, and they should know it, so this won't be a big problem 99% of the time once this DB goes live.
However, I need some temps to enter historical data from paper sheets into the DB. These people will not know anyone else's EmpID. I'd like to set the Student field's OnDblClick event in the subform's datasheet to open a small form with a combo box. The combo box has a list of all Employee Names, and is bound to the EmpID. Once this user enters the name, and selects the person, I have a button they can click to return to the datasheet.
I can use a function to launch the form, no problem there. But how do I return the EmpID to the field in the datasheet that was double clicked?
When user double clicks in the Student field...I want the next form to appear, and then once they type in the name and select the correct person...and then click Found Them!...I need that bound value to return.
I'd love to say I have code to share right now...but the only code I have is to launch the look up form. I'm brain farting on how to pull the value back down.
The way to do this to launch your little dialog form as “acDialog”. This will cause the calling code to WAIT.
And then the “magic” part is when they click on “Found Them” you do NOT close the popup form, but simply set the form’s visible = false. This has the effect of the calling code that popped up this form that halted to continue (the form is kicked out of dialog mode when you do this). So now your calling code continues.
So your code will look like this:
Dim strF As String ' name of popup form
strF = "frmPopUp"
' open form, wait for user selection
DoCmd.OpenForm strF, , , , , acDialog
' if for is NOT open, then assume user hit cancel buttion
' (you should likly have a cancel button on the form - that cancel buttion will
' execute a docmd.close
If CurrentProject.AllForms(strF).IsLoaded = True Then
' grab the value of thee combbo box
strComboBoxValue = Forms(strF)!NameOfComboBox
DoCmd.Close acForm, strF
End If
As noted, the code behind the Found Them button DOES NOT do a close form, but sets forms visible = false (me.Visible = false), and this trick allows the calling code to continue at which point you can examine any value on the form. Remember to then close the form after you grab the value.
It looks like your data table is in a subform so there is a little more work but it does not have to be as complex as the above solution if you don't want it to be. #Andre451 was close but you need the extra step of identifying the form and subform. For the purpose of demonstration let's call the form Attendance and subform Entry then I'll call the second form LookUp. So the code for your double click in the subform field will of course look something like this :
Private Sub Student_DblClick(Cancel As Integer)
DoCmd.OpenForm "LookUp"
End Sub
You really don't need anything else fancy there. For the button on "LookUp" you will put this:
Private Sub Command2_Click()
Forms![Attendance]![Entry].Form![Student] = Forms!Lookup!Student
DoCmd.Close acForm, "LookUp"
End Sub
And that should get you what you want without any overhead or having to leave any ghosts open.
I have created a UserForm where the user is required to fill-in three fields. The macro attempts to auto-detect these fields' values in the UserForm_Initialize() event, then displays the found values in the three fields, but the user can change them. The auto-detection takes a few seconds, though, and delays the appearance of the UserForm. I'd like the UserForm to appear with its fields blank before the auto-detection procedure, then have the auto-detection procedure fill the fields automatically. What would be the best way to do this? Making the UserForm non-modal makes the macro run without waiting for the user's input, which is problematic. I don't want to have an "auto-detect" button: this has to be done automatically.
Use the Activate() event instead of Initialize() :)
Private Sub UserForm_Activate()
End Sub
FOLLOWUP
Thanks! It works, but there seems to be a bug: the dialog is drawn all white until the macro completes. screenshot (the dialog should be gray)
No. It is not a bug :) Try This. Add Doevents as shown below.
Private Sub UserForm_Activate()
UserForm1.ProgressBar1.Value = 0
starttime = Timer
While Timer - starttime < 1
UserForm1.ProgressBar1.Value = (Timer - starttime) * 100
DoEvents
Wend
End Sub
HTH
Sid
There is a simpler way to do this...
1) On your userform create a new 'CommandButton' that will execute the macro you wish to trigger.
2) Set the height and the width of the button to 0
3) Make sure the 'TabIndex' parameter for the button is 0... This will create an 'invisible' CommandButton that will receive the focus as soon as the form opens.
4) In the calling routine, immediately before the command that 'shows' the userform enter the line - 'Application.SendKeys "~"'
How it works...
The commandbutton created in (1) is a valid control just like any other wxcept that you can't see it or click it with the mousebutton. The 'SendKeys' command replicates a left mouse key click which is stored in the keyboard buffer until the form displays when it will be read. This has exactly the same effect as a mouse click and will run the required macro.
Incidentally, if you are calling the macro from more than one location and wish to have different actions dependant on the source of the call, you can add more than one 'invisible' button and add "{Tab}" before the "~" character to tab the focus through the available controls. e.g. 'Application.SendKeys "{Tab}~"' will activate the button with the 'TabIndex' parameter set as 1. 'Application.SendKeys "{Tab}{Tab}{Tab}{Tab}~" ' will activate the button with the 'TabIndex' parameter set as 4 etc.
RF
I'd suggest using a timer. Open the form with the input fields disabled and empty, and set the timer to fire within a couple of hundred milliseconds. This should allow the form to be displayed immediately. Do your auto-detection within the timer's tick event (disable the timer first), then enable the fields and fill in the detected values.