Hiding columns in a datasheet - vba

I am trying to hide specific columns in an Access 2007 split form through code. I need the form to check certain conditions to see whether it needs to display a column or not. I have code in the form's 'Activate' event to hide the column like this:
txtControl.ColumnHidden = True
This code works in the "Open" event, but if I hide the column on Activate, it won't display these changes until I close the form and open it again. I have tried calling the form's refresh, repaint, and requery methods, but this doesn't work. Please help!
Edit: Ideally, I need this event to occur whenever the focus switches to this form.That's why I'm using the Activate event rather than the Open event.

Try setting it in either the form's Current or Load events. You will also probably need to requery the control after setting that property: Me.TextControl.Requery Current is called every time a form's record is changed, the form is repainted or requeried. Load, as its name suggests, is called once, after the form has opened when the form loads its records. These have always been more reliable for me than using Activate, which really has to do with more the focus of the form, not really what you want.

I've had a problem like this before working in Access 2002. I was able to solve the problem with a subform by setting the subform source object equal to itself and then running the requery.
Me.SubForm.SourceObject = Me.SubForm.SourceObject
Me.SubForm.Requery
See if this technique works for your particular situation.

Related

in Access, Bound Combo Boxes do not update unless the form is already Dirty

I'm working on a fairly complex Access Database, trying to build forms with custom buttons for working with records. I'm using list boxes to display and navigate through records and all fields for existing records are disabled unless the user presses an edit button. The problem I'm having is that if I press the Edit or Add New button, enabling all of the fields, and then try to change the selection in a combo box, it does not update on the first try.
If I edit a text box first then the combo boxes work fine.
I've determined that the control's beforeUpdate and afterUpdate events are not firing on the first try but the action triggers the form_Dirty event and then it works as expected. I tried setting Me.Dirty = True with the Edit button and that solved the problem but it causes problems with some of my other code and it seems like an unnecessary workaround if only I understood the actual cause of the problem. It also works as expected if I leave the Combo Box unbound, but I am trying to build a template that doesn't require too much work to build new forms off of and I would rather not go that route.
It must have something to do with some bit of code I'm using because I can start a basic form and the combo boxes work fine.
I've started a basic test form and am adding code from my template form bit by bit until the problem arises, but it's a tedious process. Any help would be appreciated.
What am I missing? Is there some way of getting the Combo Box events to fire before the form is dirty?
UPDATE:
I have templates for a basic form, a form with a single subform, and a form with multiple subs in a tab control.
After some more testing I discovered that this problem does not apply to the basic form which has no subforms. This template uses similar code to the others for new, edit, cancel, save and delete buttons and for preventing accidental changes, preventing Form_unload during an edit and so on. The main difference I can think of off the top of my head is that the templates with subforms use class modules and collections to hold various data and pass it between the main form and subforms. Not sure if or how this might relate to combo box functionality.
I built most of this last winter then got too busy over the summer to work on it. Just now picking it up again and I'm having to re-learn a lot of the details of how my code works.
you can try to use Me.CboName.Requery in your After Update event.
I figured it out. I was calling a procedure with a form refresh in it from the Form_Dirty event and for whatever reason the refresh at exactly the wrong time was causing the combo box Before_Update and After_Update events to be skipped and the combo box value to not change. It was also causing text entered into a textbox to overwrite existing text on the first keystroke.

How do I get to a control in a subform

I want to go to a control in a subform in order to be able to enter data.
I can make a DoCmd.OpenForm but then I get an extra copy of the subform on top of the main form. I would rather go directly to the subform. I have tried a lot of options and the following I thought was the most promising
Me.Subform.SetFocus
Me.Subform.Form.mycotrol.SetFocus
DoCmd.GoToControl "mycontrol"
This piece of code does not stop at the Subform to let me enter data. I have also tried Me!Subform with the same result. I have thought of adding a Stop statement, but then I don't know how to resume execution when data has been entered to the subform.
I think there is something I have not understood. Can someone help me out?
Biørn Veirø
VBA is single threaded. It can't work with Access forms this way. You could do it with a modal popup that returns a value, like an InputBox. Access forms don't return a value this way.
If you really want to have a step by step using Access forms then you need to hook in to form events. For this specific case I think the event you want is TextBox.AfterUpdate
https://learn.microsoft.com/en-us/office/vba/api/access.textbox.afterupdate-event
You can have different events on each control object, allowing you to have code that runs after each input.
First set focus to the subform control, then the control in the form:
Me!YourSubformControlName.SetFocus
Me!YourSubformControlName.Form!YourControl.SetFocus

Opposite of SetFocus

MSAccess VBA:
Assume, in an arbitrary form, the focus is set to MyControl on that form.
How to "unset" the focus without giving the focus to another control?
I'm lokking for a code like
MyControl.UnsetFocus
In your circumstance, you probably want to just set focus back to the parent form. This meets the conditions of unsetting focus without giving another control focus, and tabbing or clicking will activate the focus / tab-navigation again from that form.
Here's an example:
Forms![MyForm].SetFocus
Note that per the documentation for SetFocus, if you attempt to SetFocus to a Form with child controls that have Enabled set, this will cause focus to automatically bounce to the first eligible child control per the documentation.
Form.SetFocus method (Access) # Microsoft Docs
The option to give focus to the parent form does work as proposed by meklarian
Alternatively, I recently had to do something similar but I wanted to update a textbox value and simply go back to whatever had focus before. This is another case where something like an "unsetfocus" would be awesome, but unfortunately doesn't exist.
Should you need to do something like this, the following works well
Screen.PreviousControl.SetFocus

Subform validation (datasheet view)

I have a subform where the user can create rows. A new row is created by clicking a button on the main form, after which the user can set the other values. Two fields are required, and the user must not be allowed to leave them empty, even by closing the form. Instead, a MessageBox should alert the user and he should stay on the offending row, allowing him to set the required values.
This must work even if the user has not made any change to the fields.
I'm trying different events with message boxes to see if any of them fire, but none of them fire when I try to leave the fields empty, for example by changing row or closing the main form. I'm looking for some equivalent to "OnBlur" in Javascript.
I've tried BeforeUpdate and On Dirty, but both of them require a change. I've solved the one for when closing the form, using On Unload with the Cancel parameter.
If I understood it correctly you are trying to validate user's entry before inserting a new row. Did you try the event 'Before Insert' of the subform? Use Cancel = -1 to disallow inserting. That should work even if the user tries to close the main form.

TabControl.SelectedIndex being changed, but SelectedIndexChanged even not firing

All,
I have a TabControl in an application that started behaving strangely. Some background...
This program was converted from VB6 to VB .NET 2008, and used to refer to forms using their class names. In other words, I might have a form class called frmFoo. In the code for the program you might see:
frmFoo.Show()
or
frmFoo.UserDefinedProperty = True
During some recent changes, I created variables to represent instances of my forms much like these:
Public MyForm as frmFoo
MyForm = New frmFoo
MyForm.Show()
In doing so, I also removed code from the form's Load event handler and put it in the form's constructor.
When the form loads, or when a document is loaded and should influence the TabControl's selected index, something like the following will not necessarily fire the SelectedIndexChanged event.
MyForm.tbsForm.SelectedIndex = ValueReadFromFile
...or...
MyForm.tbsForm.Tabs(ValueReadFromFile).Select
Sorry to be so wordy, but there's more. If I open the form and look at the TabControl to verify that it's been set properly, everything works like it's supposed to. The misbehaving TabControl is contained within another TabControl, so I have to click the parent TabControl to see it. If I can see it, and run a test, the test always works. If I can't see it, and run a test, the first test I run will not fire the event. ...paging Dr. Heisenberg...
It's almost as if the control has to be initialized first by changing the value or making it visible onscreen...I'm totally lost on this one. It's the most unusual behavior I've ever seen. And everything worked perfectly before I began using variables to represent forms and placed the Load event code into the form constructors.
Can anyone help, or at least put me out of my misery?
SH
-------------------------------------------------------------- Edit #2
I just performed a test after having attempted to eliminate some of the variability in the behavior. But I wanted to confirm the previously-stated behavior.
I opened the program and read a file. This file contained a value that should have triggered the event handler. Without making the control visible, I can change the SelectedIndex property of the tab control without the event firing.
I closed the program down again, and reopened it. This time, selected the parent tab that allowed the child tab (the one whose event I'm concerned with) to become visible. I then selected a different tab in the parent control, meaning that the child control was no longer visible. When I opened the same file as before, it fired the event.
I'm tempted to implement a flag that confirms that the control has been repainted or whether the parent tab has been displayed. I may have to fire the event in code if the flag isn't set.
I want to reiterate that everything worked when the program referred to the forms by their class names and much of the arrangement of controls on the forms was done in the load event. Now the program creates variables and the arrangement of the controls is done in the form's constructor. I'm sure this has something to do with the problem I'm having, but I can't understand how. Any wisdom to share?
MyForm.tbsForm.SelectedIndexChanged = ValueReadFromFile
doesn't make a lot of sense. Is tha trying to assign a handler to the SelectedIndexChanged event? or is ValueReadFromFile the name of the tab?
What you're saying is that you have two tab controls, say, A and B. Tab control B is contained within a tab of A, and unless A has the tab page selected that contains the tab control B, the SelectedIndexChanged event of B will not fire if you change its tab programatically?
In which different ways have you tried to select a tab within the child tab control, and when is this code being executed?