Remembering Boolean information - vba

I have a question regarding VBA and remember a boolean true/false value. It does not need to be remember after closing or saving, just when its open. But it does not seem to be remember this result.
I have the two checkboxes, one switches to the other when clicking one, but because one is loading a lot of data (checkbox 15) I dont want it to do it if the user accidently clicks on Checkbox 16.
Public Sub CheckBox1_Click()
Dim ACTUALLOADED As Boolean
If Worksheets("Sheet1").Shapes("Check Box 15").OLEFormat.Object.Value = 1 Then
Worksheets("Sheet1").Shapes("Check Box 16").OLEFormat.Object.Value = 0
If ACTUALLOADED = False Then
Sheet32.ListBox2_Empty
Sheet32.ListBox1_Fill
**DO SOME CODE**
Sheet3.UpdateSOP
ACTUALLOADED = True
End If
Else
Worksheets("Sheet1").Shapes("Check Box 16").OLEFormat.Object.Value = 1
Sheet32.ListBox1_Empty
Sheet32.ListBox2_Fill
End If
End Sub
When the checkbox is clicked for the first time, ACTUALLOADED = False, so it runs the code.
However at the end the code makes ACTUALLOADED = TRUE, but it forgets it when I click the same checkbox again.
It's like it does not remember the Booleans TRUE/FALSE. How can I make this happen?

Using Public would solve your problem I think.
Take ACTUALLOADED out of the sub and declare it as public:
Public ACTUALLOADED As Boolean

You can use the Static option when defining your variable so instead of
Dim ACTUALLOADED As Boolean
you would use
Static ACTUALLOADED as Boolean
This will keep ACTUALLOADED value between calls.
but like #JLILI Amen said you could use a public deceleration at the module level not Sub/Function level.

Related

Set a Property Value From Database of Properties

My database has the formname, control, and control property type value stored.
I would like to have a line of code like this.
Forms(i%).Controls(ControlName$)).controlpropertytype$ = NewValue
I am currently using a select case structure to handle the various property types. It would be much simpler to have a single statement take care of it.
Using a helper function, you can achieve this with one line of code. Here's an example of setting a TextBox on Form1 to the value 'aaa':
Option Explicit
Private Sub Test()
CallByName FindForm("Form1").Controls("Text1"), "Text", VbLet, "aaa"
End Sub
Public Function FindForm(ByVal Name As String) As Form
Dim f As Form
For Each f In Forms
If UCase(f.Name) = UCase(Name) Then
Set FindForm = f
Exit Function
End If
Next
End Function
While this is an interesting exercise, I would not recommend this approach. It assumes the form and the control can both be found, but if they can't be found this one-liner will crash your app.
Here's documentation for CallByName.

How to check for when a checkbox is checked in a Userform?

I have a Userform that has a Checkbox. I am able to check the value of it, but it is always False whether it is checked or not.
Update
This is how the UserForm is being called (This is in another UserForm ):
Private Sub AddOutgoingbtn_Click()
With New AddIncomingForm
.TopBottom.Value = False
.Show
.Repaint
End With
End Sub
End Update
I created a sub to look for a change in the value like:
Sub TopBottom2_Change()
With AddOutgoingForm
If .TopBottom2.Value = True Then TopBottom = True
If .TopBottom2.Value = False Then TopBottom = False
End With
End Sub
But no matter what I do the .TopBottom2.Value is always False.
I've put a breakpoint on the With line so that I know it is hitting this Sub, then I step through it each time. I open the UserForm and check the box, step through and the value is False, then I uncheck the box and step through. The value is still False.
I am not setting the value in any other way with VBA. I am checking the value in the UserForms code, not in any other place.
I have an If in a Calculation Module that is looking at this value for when it is true or falses, but it is always false.
Here are all the Properties of the Checkbox:
With AddOutgoingForm
That's referring to the form's default instance, which may or may not be the instance that's currently being displayed.
You have two options:
At the call site, instead of doing this (or something similar):
With New AddOutgoingForm
.Show
'...
End With
Do this:
AddOutgoingForm.Show
'...
That way you'll be working with the default instance and the checkbox value-check should work.
...but IMO that's a very very bad idea, because then your form contains code that will only ever work when you're showing the default instance.
Leave the call site alone, and NEVER refer to the default instance of a UserForm inside that form's code-behind. In other words change With AddOutgoingForm for With Me.
The Me keyword refers to the current instance - and that is what you want. Doing this will make the form work regardless of what the call site does.
Alternatively, just drop the With block altogether: With Me wouldn't be doing anything useful here.
I will assume the checkbox is indeed on your user form so just use me or you could use
AddOutgoingForm.TopBottom2.Value
But let me ask you, where is TopBottom and what is it a Boolean variable or another Checkbox? Also on the same form? The Subs are also all in the form? You have to be calling the form from somewhere so be careful between the worksheet, workbook, module variables. Is TopBottom a Global variable to the whole project (in a module called Global_Variables with Public in front of it perhaps?) You may not have access to TopBottom from inside of your form if you are not passing anything in or out.
Private Sub TopBottom2_Change()
If (Me.TopBottom2.Value) = True Then
Me.TopBottom.Value = True
Else
Me.TopBottom.Value = False
End If
End Sub
Cheers,
-WWC

VBA - Passing variable between modules

I'm new to VB6, and trying to write some macro in use for CorelDraw.
I have a variable that need to be passed from Class module to Standard module, in my Class Module "SaveOptClass" I have a public variable called IsSaved and it's set on the class module:
Public IsSaved As Boolean
Public Sub SaveFile()
If <some triggers> Then
IsSaved = True
End If
In Standard module:
Sub DoSave()
Dim SaveClass As SaveOptClass
Set SaveClass = New SaveOptClass
If SaveClass.IsSaved = True Then
ActiveDocument.Save
Else
Form1.Show
End If
End Sub
Basically I'm trying to pass "IsSaved" boolean value from class module to standard. (If IsSaved is true, save the document or else display a form.)
I have tested that the boolean is True when I executed the code, but I can't get the state to pass to the other module.
Is there something I miss here? Thanks in advance.
As already answered by #shahkalpesh the problem is that you're not using a meaningful instance of SaveOptClass.
In my opinion the best way to design this kind of dependency is by mean of a parameter in the routine is using it and avoid as much as possible the use of global variables.
In your case this brings to this rewriting:
' in someOtherModule
Public Sub DoSave(saveOptObj as SaveOptClass)
If saveOptObj.IsSaved Then ' = True is unnecessary
ActiveDocument.Save
Else
Form1.Show
End If
End Sub
The client code could be:
private saveOptObj as SaveOptClass
Public Sub SaveFile()
If <some triggers> Then
saveOptObj.IsSaved = True
End If
' ....
someOtherModule.DoSave(saveOptObj)
' ...
Consider also, at this point, a renaming of DoSave, given that the actions taken suggest different semantics. In similar cases is preferable moving the If Else logic in the caller. Anyway, if you prefer to group actions with different semantics in the same routine you'd better use namings like DoSaveOr<SomethingElse>.

Stopping "TextBox_Change" event from executing if called by code

I have a userform which contains a TextBox object named myTextBox.
The text inside the object can be changed either by the user or by the code. There's a "onChange" procedures attached to the textbox:
Private Sub myTextBox_Change()
'do some stuffs
End Sub
I would like the event to be processed only when is the user changing the text, but not the code. I had thought about adding an Optional parameter like the following:
Private Sub myTextBox_Change(Optional isCode As Boolean)
If isCode = False Then
'do some stuffs
End If
End Sub
but this is not really helpful because I cannot pass the isCode = True when changing the name programmatically, like this:
myForm.myTextBox = "new text"
Does anyone have an idea on how I can fix this?
One way (perhaps not the right way?) would be to declare a global variable to use in the same way as your IsCode Boolean. Set it to true during your code block so the textbox_change event knows code is processing in the background, and then set back to false when that code has finished.
Put this at the top of a normal module (won't work in a form module)
Option Compare Database
Option Explicit
Global IsCode As Boolean
and then in the code you're running just set IsCode=true as required.

SetFocus inside a GotFocus procedure initiated by another SetFocus

Objective: Redirect focus from one command button to another using the first's GotFocus procedure.
Context: I have a form-independent procedure in a generic module that, on most forms, sets focus to the NewRecord button after saving the previous record. But on one form, I would like to redirect (based on certain conditions) focus back to the SignRecord button so the user can "sign" a second part of the same record (I may need this for other uses in the future). The target control is enabled and visible and can otherwise be focused and the original control can be focused when the redirect doesn't occur. Reference [2] below implies that this should be possible, though I'm not changing visibility of my controls.
Issue: When the conditions are met to redirect focus in the GotFocus procedure, it redirects as desired but the original (test) SetFocus call throws a "Run-time error '2110', Can't move focus to the control CommandNew".
What I've tried:
Exit Sub after my downstream SetFocus calls.
Call CommandSign.SetFocus in the hopes that it would make it happen outside the previous SetFocus process.
In a module,
Public Sub test()
Forms("TargetForm").CommandNew.SetFocus 'This gets the error '2110'
End Sub
In the 'TargetForm',
Private Sub CommandNew_GotFocus()
If IsNull(textDateTime) Then Exit Sub 'Works as expected
'I can see these two parts work. The framSign value changes
'and CommandSign gets focus
If checPPC And IsNull(textSigID_PPC) And framSign = 2 Then
framSign = 1
CommandSign.SetFocus
ElseIf checDAS And IsNull(textSigID_DAS) And framSign = 1 Then
framSign = 2
CommandSign.SetFocus
End If
End Sub
References:
[1]: SelectNextControl() a bad idea in a GotFocus event?
[2]: http://www.access-programmers.co.uk/forums/showthread.php?t=100071
I think your problem is that the call to Forms("TargetForm").CommandNew.SetFocus doesn't quite seem to, in fact, finish setting the focus to CommandNew until after Private Sub CommandNew_GotFocus() has finished executing. Because you've called another SetFocus before the first SetFocus could finish, there is a conflict that Access seems to be unable to cope with.
Whether or not that is the case, one thing is clear: the way you have your execution plan set up right now is unfortunately not going to work. You might try adding either a global variable or a public variable to each form that determines whether or not you should set your focus to CommandSign after you set the focus to CommandNew.
Ex. TargetForm:
Public boolSetCommandSignFocusInstead As Boolean
Private Sub CommandNew_GotFocus()
If IsNull(textDateTime) Then Exit Sub 'Works as expected
'I can see these two parts work. The framSign value changes
'and CommandSign gets focus
If checPPC And IsNull(textSigID_PPC) And framSign = 2 Then
framSign = 1
boolSetCommandSignFocusInstead = True
ElseIf checDAS And IsNull(textSigID_DAS) And framSign = 1 Then
framSign = 2
boolSetCommandSignFocusInstead = True
Else
boolSetCommandSignFocusInstead = False
End If
End Sub
Module:
Public Sub test()
Forms("TargetForm").CommandNew.SetFocus
If Forms("TargetForm").boolSetCommandSignFocusInstead Then
Forms("TargetForm").CommandSign.SetFocus
End If
End Sub