@ kd2017 post# 29. In this example your approach would work. In reality the FormLoad procedure creates and builds dozens of variables, which couldn't be passed back via a function very well. Hence the questions in post #26.
@ kd2017 post# 29. In this example your approach would work. In reality the FormLoad procedure creates and builds dozens of variables, which couldn't be passed back via a function very well. Hence the questions in post #26.
Understood.
It sounds to me like you might be reaching a level complication with your user interface where I would personally look to different tools/languages other than VBA. For that reason I'll bow out of any discussion in regard to advising how *best* to accomplish your goal in VBA.
I'm sure the experts on this forum could easily set you on the correct path.
@kd2017, post #32 Thanks for the looking. I wish I had the option to consider another avenue.
Anyways, if anyone is looking for a little proof that form class local variables don't get stomped with multiple instances,
(or you just want a little template to test things with)
I broke out the old Closen.accdb, and added just 5 lines for testing. Open multiple instances of Form2_2 and move between the forms.
If module variable MyHwnd got corrupted, the detail background would turn blue on that form (if I didn't make any errors).
Minimizing and Restore Up will have some spastic results though, as well as the debugger if you use a breakpoint in:
CheersCode:If MyHwnd <> Me.Hwnd Then Me.Detail.BackColor = vbBlue 'module variable got tromped on by other instance
Sorry to bring the thread back, I edited my replies, twgonder.
I was driving home and minding my own business when I realized the error in my explanations out of nowhere, my bad.
The code above is the entire Module1. mWhat is private to that module, it can't be accessed outside of it, mWhat CAN NOT be accessed outside of Module1. fFrmLoad is public, since you are using it on the Form_Load of all your forms, every time a form Loads, it changes the private variable, THROUGH THE FUNCTION, not directly. Then, since fFrmCurrent is also public, your forms can check the current state of the private variable and return a string based on that state. And this state, again, can be changed by anything that calls fFrmLoad. So I would perhaps write the code like this:Code:Option Compare Database Option Explicit Dim mWhat As String Public Sub sFrmLoad(ByVal aW) mWhat = aW End Sub Public Function fFrmCurrent() As String If mWhat = "P" Then fFrmCurrent = "a parent" Else fFrmCurrent = "a child" End If End Function
To me, that is easier to read. It's not a solution, but a way to understand what is going on. I insist that what you did is the expected behavior within VBA. If what you want is to have different mWhat variables for each call, then you have to create a Class module so that you can effectively instantiate the Class, to have an mWhat variable available for each instance. I'm gonna use my own variable names to use intellisense more effectively:Code:Option Compare Database Option Explicit Dim currentFormType As String 'could be Private currentFormType As String Public Sub setFormType(ByVal FormType As String) 'Just to be explicit that it's string, not Variant currentFormType= FormType End Sub Public Function checkCurrentState() As String If currentFormType= "P" Then checkCurrentState= "a parent" Else checkCurrentState= "a child" End If End Function
And the implementation for Form1 is as follows:Code:Option Compare Database Option Explicit Private currentFormType As String Public Property Let FormType(ByVal value As String) currentFormType = value End Property Public Property Get FormType() As String FormType = currentFormType End Property Public Function CheckCurrentState() As String If currentFormType = "P" Then CheckCurrentState = "a parent" Else CheckCurrentState = "a child" End If End Function
Implement the rest for the other Forms. You will now have instances for every form. Check the attached.Code:'Form 1 'Test of incest in Access Option Compare Database Option Explicit Private thisFormType As String Dim myFormState As New FormState Private Sub Form_Load() ' as class myFormState.FormType = "P" ' as module Call sFrmLoad("P") thisFormType = fFrmCurrent Forms.Item("frmCurrentFormType").Controls.Item("lblCurrentFormType").Caption = fFrmCurrent End Sub Private Sub Form_Current() ' as class Debug.Print "Form1 (parent) = " & myFormState.CheckCurrentState() ' as module tbxIam = fFrmCurrent If tbxIam = "a parent" Then tbxIfeel = "okay as an adult" & " (" & thisFormType & ")" Else tbxIfeel = "a little confused" & " (" & thisFormType & ")" End If End Sub
Ohh, interesting.
There has to already be some accepted practices in regards to localization or translating forms like that. Off the top of my head if were do it from scratch I think I would keep a form object's translations in a db table and devise a vba routine that queries for object names, translations, etc. based on form name and whatever else your criteria, then loop over the controls and set appropriate property.
Just found this on a quick search. I haven't watched it but looks to be directly relevant https://www.youtube.com/watch?v=2mkwBSExnyk
[edit]
I did a quick skim through the video, at the 14 min 45 sec mark unfortunately it looks like he wants you to pay for the good stuff
@Edgar, post #36 Thanks for that. I'm curious about Access classes, and have got to get into that.
I'm curious, did you look at post# 8? Did you see a problem with that solution?
@kd2017 post# 37 I looked at the MS approach, it came up short, from what I could tell and what others said.
Then I looked at an old post, I don't think it was Allen Browne, downloaded the sample and went huh? That one used the tag property.
As usual I went back to some of my old designs, and did just what you said, create a couple of tables and VBA to do the translations for everything except data.
Sometime, way back, I watched Richard's video (I'm an avid watcher and member), but his approach was brute force.
At the same time, I added helps to be in the different languages.
Three lines of code that do all this in validation error of a form look something like this:
Besides doing the translate, it puts the result in the yellow Status Box you see at the top of the form.Code:pSp(1) = aFrm.Controls(aFldNm).Controls(0).Caption 'label caption for the associated entry field pSp(2) = aValdt(3, ValCol) 'some control of how to validate, like length of field sAddStatus aFrm, fTranltLang(TempVars!LangID, "3_Ie21", "H", pSp), , , aValAll
Now you know why my Form Support module (which does this for all forms) is so important, to not tromp on module variables,
Okay, it sounds like you're already past all this. But for what ever it's worth to you, for my own entertainment I whipped up another example db to demonstrate what I was talking about in post #37. This could be pretty powerful, it can dynamically change any number of control properties based on what ever criteria you want... Might want to think on how it could possibly be abused and/or cause problems?
example2.accdb
Form Code:
Module Code:
I don't see a problem, but rather a unorthodox way to use your variables. Typically, you would want to input XXX and output YYY. With the approach in that post, you first declare your variable, then you input some other value and return it in the argument of the function, then you use the returned argument to use it for another function. I don't know, I mean, it's good that you can do it, but I'd stay away from that approach.
Remember, this wasn't about variables per say and subroutines and functions. The purpose was to show that variables get corrupted when dimed as module variables in the Module1.
In reality, the FormOpen, FormLoad, FormCurrent, for a typical form (as shown above) has about 300 values for control and over 2,000 lines of code to cover form overhead, form colors, control colors, enabled and translation as well as helps, validations, etc. I'm not sure a class is going to bring much to this that a regular array can't handle. At the moment I'm moving everything into one large array, which is then easy to pass as a single argument to anything that might need it. And since it's by reference, there shouldn't be much overhead. Wish me luck, lots of variables to keep straight.
I remember when I made my first web application, I didn't have a clue about code organization, and ended up putting all 80+ server routes in one massive file. I mean, we're talking over 3,000 lines of code here. And that was just the start. I did the same with my first .NET app and several other things. Maintaining all of that code every few weeks was a nightmare. But nothing could prepare me for the day my client requested an urgent change. A breaking change. And boy did it break me, not the code. It caused me so much stress and anxiety that I went three whole days without sleep. And when I finally did manage to drift off, my brain would send lightning strikes down my spine every five minutes, jerking me awake once again. On the third day, I was at my wits' end. So, at 4 am, I ran outside as fast as I could, hoping to exhaust myself enough to finally get some rest. It worked, but couldn't fully recover over the span of 4 months.
Classes, you can split your code into classes. One class for language functions. One class for theme functions. One class for validation. One class for helps. And if you have repeating properties and methods, you can make a class for that too, and inherit it to the classes that require it. Don't make super powerful functions that do everything. Split things. Refactor. If...Then statements that go 3+ levels deep? don't do that. Seriously. Maintaining that will be too much. Better to learn some design patterns. But good luck.
No, but there is plenty of info on custom classes out there but not always easy to find.Got a link that shows how to take a regular module and turn it into something "class"?
Many of the classes I use are entirely self contained including using instances of forms.
I'm currently working on a custom class to handle one textbox. There are about 8 different things that need to be done when various changes are made to this one text box.
All the validation, data entry, deletion, naming, renaming, deleting and moving folders, etc. are easily handled by the class and all the variables persist while the class is in scope.
They take longer to write but give you a lot of control over various events.
If this helped, please click the star * at the bottom left and add to my reputation- Thanks
Cool & thanks, I'll look and learn.
In the meantime, I still wonder how Access has been useful for developers when, as how this post started, if a main & sub forms (and even two different forms running at the same time) can smash on each other's variables when they both call the same subroutine that has module or static variables that the forms use separately. Does everything have to be turned into a class to preserve simple variables? It seems ludicrous to me and what I've experienced in computing over the past 45 years.