How to load code before on form load - vba

I have some code I need to load in before I want the code to run (I want to create a table), I tried 'Onload' but this is not soon enough, basically I'm looking for something just like OnInit() where I can load all I need before anything actually occurs. My problem is that it's checking for the table way to early (Because it hasn't been created yet)
http://gyazo.com/c731783b9b2a01dcaf93f92a170f61ba
So really I just need some help with calling code before the actual onLoad event is called.
THanks

Is OnOpen event suitable?
And you can have empty RecordSource in form and set it after you have created table.
1. open form in design view
2. copy RecordSource
3. in you event(onOped or onLoad) put after table creation code
Me.RecordSource = "COPY'ed recordsource"

Related

Subform showing up blank after code executed

My goal is to change the SourceObject of a subform. I can do this manually by going into design view selecting the subform object and changing SourceObject and removing the master and child links. I save changes and reload into form view and all works well.
When I try doing this via VBA it does not seem to work and gives me a blank subform.
Here is the code that I am currently running:
Private Sub ondacapBtn_Click()
Me!DACAPRosterQ_subform.SourceObject = "ondacap_subform"
Me!DACAPRosterQ_subform.LinkMasterFields = ""
Me!DACAPRosterQ_subform.LinkChildFields = ""
Me!DACAPRosterQ_subform.Requery
I find this even crazier because this is code I've used before except the Me!subform is a different name, and it works perfectly elsewhere! I am complete baffled at how this works in the other subform but not this one.
I've tried changing the name, the tab order, made sure the subform I am changing to works, made sure the code matches the other subform shown below, I am out of ideas and I made this account just so I can ask this question. It's really upsetting me.
Private Sub FilterBtn_Click()
Me!Retrain_subform.SourceObject = "UpcomingRetrain_subform"
Me!Retrain_subform.LinkMasterFields = ""
Me!Retrain_subform.LinkChildFields = ""
Me!Retrain_subform.Requery
EDIT - 26SEP22
I found out that one of the fields in my RecordSource is causing this issue.
My subform has a RecordSource called DACAPRosterQ and in that query I've input a field that is called "SearchTerms:" [with] & [other fields] & [listed] & [to use as search bar criteria]. The table PersonnelT that the query DACAPRosterQ pulls from does not have the "SearchTerms:" field naturally. Only the query.
When I remove this field from the query the subform can be switched with no issue via VBA.
Something I noticed when trying to open Ondacap_subform individually without the parent form is it asks for input "Forms!DACAPRosterF!DummySearchTextbox" which is a control on the parent form DACAPRosterF alongside the subform.
I have a feeling I must input some code to reinitialize that field as it is not done so via VBA. I'm just not sure what it is.
I think this would also explain why I am able to switch SourceObject manually via design view because it it already being reinitialized when reopening the form in form view.
Anyone have any ideas?
I figured it out... I couldn't tell you why it works or why it didn't work without this solution.
All I had to do was enter into the subforms OrderBy property, I ordered it by [Field1], [Field2]. Works like a charm now. Search bar still works and everything functions as normal.
If anyone could provide insight as to why this occurred, that would be amazing. Otherwise, problem is fixed.

How can I make a form instance open a specific record on creation?

I'm trying to optimize the performance of my access frontend. One of the problems I'm stumbling on is how to set a multi-window form to open immediately to a specific record, because at the moment it queries everything twice.
Essentially, I allow my users to open multiple instances of a form. That way, a user can compare multiple records by placing the windows of those forms side by side.
At the moment, my code looks like this:
Set frm = New Form_Name
frm.RecordSource = "select * from Table where id = " & ID 'ID is a variable passed to the method
I'm pretty sure back then this question was one of the building blocks I relied on.
The problem is that on the first line, access already entirely opens the form and does everything the form does when opening, such as Form_Open, Form_Current, and loading subforms. Then, when I set the recordsource, it does all (or most) of that again, which significantly slows down the process of opening the form.
Here are some of the things I've tried:
Changing the Form_Current to recognize that it's being "used" twice and only actually run the code once. The problem is that the code is already very optimized and doesn't seem to be the bottleneck, so this doesn't seem to do much. Actually opening the form seems to be the bottleneck.
Trying to change the properties of the original form so that it opens the specific record I need, but I can't seem to change the properties without it opening the form.
Looking for a way to supply arguments to the form. That doesn't seem to be supported in VBA.
One other idea that popped into my mind was creating a variable in vba with the ID of the record, setting recordsource in the form properties to fetch that variable, but then, when I would open another form and change that ID, the form
I realize that I can do this with DoCmd.OpenForm, but that doesn't give me the option to open multiple instances of the same form.
How can I achieve this? This would mean a significant performance improvement.
OK, so I actually wanted to ask this question. But just before I hit the submit button, I had an idea...
Here's the idea: you set a global variable in VBA, which you then access in the form filter command. In my case I just added Public OpeningID As Long at the top of my VBA module. Then I create a function to get that value:
Public Function getFormID() As Long
getFormID = OpeningID
End Function
Then, in the form, you can set the filter criteria as ID = getFormID(). And then when you open the form instance, you do it like this:
OpeningID = ID
Set frm = New Form_Name
OpenindID = 0 'reset this to make sure that if it's being accessed when it shouldn't, it generates a clear error
The only problem is what happens when you refresh the form, as that will call the method again. When you refresh the form via VBA, you can set the OpeningID beforehand, and to avoid users refreshing the form, you can add this to your form (don't forget to turn on Key Previews in the form settings):
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyF5 Then KeyCode = 0
End Sub
Bang. Forms open almost twice as fast. Awesome.

Refreshing form from timer in another form

I have a problem with the snippet of the code I have got to extend and improve. It is not my original code and I cannot change the logic that much of it, just to be clear.
I have one main form called MDIServer, which has a timer set for every second. In Timer.Tick I have some other code which works fine (timer is running okay). Newly, I had to check there, if one form is Active and if so, change some stuff (labels text and tags) in that form and refresh it.
I add there this code:
If IsActiveForm("frmName") Then
frmName.ChangeSomething()
End If
The Sub ChangeSomething is, how you can see, located in the form I want to refresh and do the changes. In that function I simply change the label text and tags of few controls.
My question is: Form is not refreshing => labels are not visible changed, why?
I think I tried already almost anything with Refresh() function in the ChangeSomething() function or in the timer after I called this function. Also I tried to add there new timer (in frmName) and do the changes there, which works perfectly with
Label.Text = "something new"
Label.Refresh()
So I guess problem is somewhere with the refreshing form from Timer in different form. I also tried to do it with my own InvokeReguired() function etc...
P.S. When I am debugging the code, labels and tags are changing and every single function which has to be called, is called, but it is just not visible on the form itself.
EDIT Info
formName is not declared in MDIServer explicitely and in this case and many other cases, forms are used as default instances. Timer is from System.Windows.Forms.Timer. Also MDIServer is not a MDIParent of the formName and I cannot use Me.ActiveMdiChild Is. Lets just say, these two forms are not dependent on each other in any way.. and everything is done through name of the form (default instance, so nothing like Dim frm As Form and frm = frmName).
I would be really glad for any tip or anything :D
Thanks guys,
Vojta
So, I fixed my problem after some research and the problem was (expected) that I am not calling the subroutine ChangeSOmething() for one specific instance of the form frmName. So I had to change my code, that I will call it exactly for the instance which is active and visible.
New code looks like this:
Dim frmCollection = Windows.Forms.Application.OpenForms
Dim listfrmname = frmCollection.OfType(Of frmName).ToList()
If listfrmName.Count > 0 Then
Dim tmpFrm As frmName = listVZT15.Last()
tmpFrm.ChangeSomething()
End If
I also could not use combination of frmCollection.OfType(Of frmName).Any and frmCollection.Item("frmName"), because when I was closing the form and opening again, it created new and new instances (I dont know, why it is not closing the old one, but like I said, it is not my code). So the logic is, to list all open forms of the needed type, and then take the last instance from that list and for that instance call the subroutine. Also Me.Refresh() is placed in the subroutine ChangeSomething() itself.
Thanks everyone for help, it surely helped me to understand, how the instances works here.

VB.Net ComboBox (as Dropdown) not translating text to DisplayMember with Databinding

I inherited a fairly large project at work that is undocumented and written in VB (originally started pre .NET, ended around .NET 2). I'm in the process of updating / refreshing a lot of the code, but have run into an annoying issue that I haven't found the solution for yet. This system utilizes a UI, a Web Service, and a SQL DB.
Problem: I have a Databound Combobox (originally set to DropDownList - I'm changing it to DropDown, which is what started this mess - going back isn't an option) that is tied to a DataSet that comes from a Web Service. When a user types in the item they want manually, the data from the text field doesn't seem to associate itself with the DisplayMember, which forces the WS/SQL query to fail (it is sent a blank value when it's expecting a ValueMember). If the user types in a partial selection and then chooses the value they want from the DisplayMember list using the arrow keys or tab, the query goes off without a problem.
My Question: How do I get the text field to translate to the DisplayMember which will then properly tie itself to the ValueMember which will then allow the query to execute correctly? Sorry for making this sound complicated or convoluted; I'm sure the answer is easy and I'm just glazing over it.
The relevant bit of code is:
With cmbDID
If dtsLU.Tables.Contains(reqTable) = True Then
.DataSource = dtsLU.Tables(reqTable)
.DisplayMember = "zip"
.ValueMember = "gridID"
End If
End With
cmbDID.DataBindings.Clear()
cmbDID.DataBindings.Add("SelectedValue", dtsData, strDT & ".gridID")
I've tried changing "SelectedValue" to "Text", which almost works - but it directly translates to gridID and skips zip which ends up with an incorrect Web Service response since the zip and gridID field values are not synced (zip (DisplayMember) may be 5123 while gridID (ValueMember) may be 6047). I've tried changing "SelectedValue" to "SelectedIndex", and that got me no where.
Any help is greatly appreciated.
EDIT
To add some clarification to the process, the below pseudo code / description is roughly what happens. I could post the whole module, but I feel that would just muddy the whole question even more.
Private Sub A
FormAlpha is created with 1 ComboBox in the form of a DropDown
This DropDown is populated with a DataSet
DataBinding with a blank DataSet is added to the control to keep track of the users input
End Sub
lblSubmit_Click event is triggered on FormAlpha by the user after they have populated the DropDown with their data. lblSubmit_Click calls Private Sub Submit
Private Sub Submit
BindingContext(DropDown DataSet, tableName).EndCurrentEdit() is called
DataSet.HasChanges() is processed
If changes are present, changes are processed
HERE lies the problem
If the user has manually typed in the DropDown field, but not hit an arrow key or tab, then the DataSet registers a change, but returns a null value in all fields - it knows something was entered, but that data apparently didn't pass through the DataSet for the ComboBox (ListItems or SelectedIndex didn't change / fire I'm guessing). If the user selects the item with the arrow keys, the DataSet has the proper input (I'm assuming the Data was validated by the control at this point).
If the processed data is good, a value is entered into the database
If the processed data is bad (empty), an error is returned
End Sub
If the above can't be solved with what I've provided, but someone still knows a better way to handle this type of situation, I'm all ears. Rewriting the module isn't ideal, but fixing this problem is a necessity.
Alright, while this fix may not be ideal, it is a fix none the less.
The bare bones problem was that the text value of the DropDown wasn't causing the data to actually affect the SelectedIndex / SelectedValue of the control unless you interacted with it using the arrow keys or a mouse click. So, while the DropDown would read "1234", in reality the control saw "".
The fix I have in place for this is simply calling comboBox.text = comboBox.text whenever the user hits the submit button.

How to assign an output to a label in a second form through the first form?

I wanna show the output of the calculations in a second form but I am writing the code in the first form. How can I do it?
Use the parent form name in front of the control that you are trying to work with. You may need to set the modifier to Friend.
Say that the label exists in form2 and you have code in form1 that is needing to change it. So you would do it like this: form2.label.text = "the string value here"
However, keep in mind that if the control was created or is owned by a different thread then the one that is trying to edit the control, you will receive a runtime exception.
To resolve that you will need to create a delegate for the calling sub or function.