I'm trying to create a simple ignore list option for my program. When a sub runs, I want it to not execute some code if a user is on the list and a checkbox is checked.
I have tried this:
If Not My.Settings.IgnoredNames.Contains(PartnerDisplayName) AndAlso chkIgnore.Checked = False) Then
'Do something...
End If
This works, except even when the check box is checked by itself the if statement doesn't continue. I don't have a clue how to rewrite it.
This will not work either and I don't really know why. The sub triggers on an certain API event, and exiting it like so still lets the real code go through.
If My.Settings.IgnoredNames.Contains(ParterDisplayName) And chkIgnore.Checked = True Then Exit Sub
'Do something...
Instead of using Nots and creating messy logic, just invert your If statement and short circuit out if you hit the condition where you don't want to run the code:
If My.Settings.IgnoredNames.Contains(PartnerDisplayName) AndAlso chkIgnore.Checked = True Then
Return
End If
' Do your other logic here.
Related
I'm having a very strange problem in a VB application. I have a function written like this:
In the innermost condition, two statements are commented out here. These were found to have no effect on the strange behaviour. This is the minimal example I've found causing trouble.
(Note that the names of objects have been changed in this example.)
Private Sub MyForm_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles myDGV.CellValidating
Dim dgv As DataGridView = CType(sender, DataGridView)
Select Case dgv.Columns(e.ColumnIndex).Name
Case "uniqueColumn"
' Validate that the values in our unique column are unique.
For i As Integer = 0 To dgv.RowCount - 1
If i <> e.RowIndex Then
' Here i != j, so compare to the value...
If e.FormattedValue = dgv.Rows(i).Cells(e.ColumnIndex).FormattedValue Then
e.Cancel = True
'dgv.ShowRowErrors = True
'dgv.Rows(e.RowIndex).ErrorText = "Data in the unique column must be unique"
End If
End If
Next 'i
Case Else
' Perform no validation.
End Select
End Sub
What trouble, you ask? For some inexplicable reason, whenever the line
e.Cancel = True
is executed, afterwards, nearly all buttons and form widgets in the entire application, including even the close button in its window bar (what a user would use to exit the application) stop doing whatever they previously did and now call this event handler instead.
In other words, commenting out that line (and doing the validation manually when the form is submitted) fixes the problems. I'd like to know why this happens, though. Some pointers:
Here's a list of which things are not affected:
The minimize and maximize button in the top bar.
All objects in its menu bar.
This handler is private to its form class, it's not referenced anywhere else in the application.
I'm at a loss. Just how? What could possibly cause this?
e.Cancel is for stopping the validation when the input is deemed incorrect. This causes the cell to still have focus as the user is expected to correct whatever they did wrong. The CellValidating event will then be raised again whenever the cell is about to lose focus until your code deems the input to be correct.
You can use the Control.CausesValidation property to control whether a control (for instance a button) should raise validation events when it gains focus.
I am using VBA in Microsoft Access. I want the code to run before the user completes each entry of "downtime". I am trying to make sure that the value of a box is not a negative number. The box actually holds a formula. I don't know if that matters but, I thought I would mention that. I want to check the result of the calculation (the value that is showing in that box) and if it is less than 0, I want a MsgBox to pop up. My code is doing nothing. No error, no pop-up, no warnings.
Here is my code.
Private Sub Form_BeforeUpdate(Cancel As Integer)
If (Me.RunningTotal.Value < 0) Then
MsgBox (RunningTotal & "Please check your downtime.")
Cancel = True
End If
End Sub
I have tried using the "RunningTotal" in brackets as well with no luck. I have also tried beforeupdat as well as afterupdate.
I got it to work. I had to put the code in the user's data entry box AND as an "after update" since the calculation wouldn't happen until after the entry has been made. Thank you, Darren, for your help. :) Here is the code that works.
*Private Sub MinutesDown_AfterUpdate()
If (Me.RunningTotal < 0) Then
MsgBox (RunningTotal & "Please check your downtime.")
Cancel = True
End If
End Sub*
I know this might be a more of a general question, but I've looked at my code a 100 times and am not sure what's wrong. I set a global flag so that it can be used in different forms of my application.
Dim OverPopulated as Boolean
I have a function where I first set it to FALSE, and after it goes through some validating it gets set to TRUE.
Now i do a bunch of stuff, go through different forms, and the value stays correct the entire time. Basically I need this value for another form, so when I check
if OverPopulated = false then
MsgBox "You Can't do this and that"
exit sub
End if
Then all of the sudden it gets set to FALSE. I've went through every instance of OVERPOPULATED in my application and put a break point to it to make sure that nowhere do i set it to FALSE, except for the one time I set it to FALSE before my validation.
I only have it in 2 other forms in my applications. There is one place where the flag is being run twice through the same statement (just like the one above). The first time it goes through, the value is correct, then it goes through again and the value is set to FALSE.
Any ideas? if this is too vague, please let me know, I'll try to edit it.
EDIT: I deleted a lot of the code but here's how it looks.....
Dim OverPopulated as Boolean
' modular level
Private Sub ValidatePopulation()
Dim admDate as date
OverPopulated = False
admDate = Format(Now(), "mm/dd/yyyy")
Select Case revPURP
Case 0, 1, 2
'Check make sure these fields
'some if statements, checking, validation
Case Else ' no need to do a
End Select
OverPopulated = True 'I MAKE SURE IT GETS HERE and is set to TRUE!!!
End sub
Now, in other functions I used it like this...
If OverPopulated = False Then
If optStat (0).Value = True Or optStat (1).Value = True Then
MsgBox "You are not able to do this”, vbCritical, "Incorrect review status...."
TabPop.Tab = 6
End If
Exit sub
Else
'Proceed with SAVE
End If
So I have this. and I have another statement just like this somewhere else. This one gets hit twice. The first time I go through it line by line and it's FALSE, then the 2nd time around the value is TRUE.
It looks like for some reason the value was getting reset to FALSE. I took out the Dim OverPopulated as Boolean from my form code, and placed it in a GLOBAL module where all the other globals are stored. This seems to have fixed the issue of the value remaining the same while I'm manuevering in the application. Thank you for all your comments.
Global OverPopulated as Boolean
My project is vb.net 2010 windows desktop form.
So far, single threaded (default).
If a SUBroutine has a for...next loop in it that is running, what happens if a buttonclick event is fired and within that event a variable is changed? Like: does program execution leave the loop that was running? Or does it continue to run while that variable is changed by the buttonclick event?
What I'm aiming for:
If someone clicks the button, blnRequestStop is set to True.
Within that for...next loop, just before the "next" it checks blnRequestStop. If true then it will exit the "for" loop.
I'm guessing I need to use threads? Can anyone give me a simple example, please?
EDIT:
This code below seems to be working fine. But maybe you all see a problem?
If (btnProcess.Text = "Done!") Then
End
ElseIf (btnProcess.Text = "IMPORT") Then
bRequestStop = False
t1 = New Thread(AddressOf ProcessDo)
t1.Start()
Else
t2 = New Thread(AddressOf MyInterrupt)
t2.Start()
End If
Here is the short version of what ProcessDo and MyInterrupt do:
Private Sub ProcessDo()
For each X in blahblah
'do stuff (yes, includes interface)
if (blnInterrupt) then exit For
Next X
End
End Sub
Private Sub MyInterrupt()
blnInterrupt=true
End Sub
Yes, you probably want to do the long-running task on a background thread. Here's a code sample including how you'd get the results back to the UI thread when you're done (otherwise you'll get errors about Cross-thread operation not valid).
ThreadPool is a nice way to do some work on a background thread. You could set stopIt = True in the button click event for the stop button.
ThreadPool.QueueUserWorkItem(
Sub()
For Each thing In things
If stopIt Then Exit Sub
'Do the stuff!
Next
'We're done, update UI
Me.UpdateUI("All done!")
End Sub)
To safely update the UI, you'll need to make sure you get back to the UI thread.
Public Sub UpdateUI(result As String)
If Me.InvokeRequired() Then
'If we aren't on the UI thread, invoke this function on the UI thread
Me.BeginInvoke(Sub() UpdateUI(result))
Exit Sub
End If
'Update UI here
lblResult.Text = result
End Sub
Execution is 'stopped' (in a way) until the Loop finishes him job, so yes, you need to multi-thread.
It it is not a very long operation where you need to update UI controls during the Loop then you just can use Application.DoEvents inside the loop to be able to use other controls as normally in the application when FOR loop is working, but I advise you that this will have a negative impact on UI performance, but if it's not a long duration loop then you maybe would consider to use DoEvents instead introduce into multi-threading it's just an alternative, not recommended but, you can use it.
PS: Forgive my English
I have a VBA sub that makes a call to a sub that was written by someone else. occasionally, the other sub opens a MsgBox with an OK button. The other sub takes a long time to run, and I am calling it hundreds of times, so I want to be able to run this overnight. Unfortunately, I can't figure out a way to automatically click OK on the MsgBox.
I have tried
Application.DisplayAlerts = False
but this doesn't suppress message boxes.
Is there any way to do this?
Thanks
One way to do this is slightly modifying the code of the original sub. You will need to have the necessary permissions tough...
Modify the header of the original sub by throwing in an extra optinal parameter at the end setting the default value to True. This will result in something like Sub OriginalSubName(original set of parameters, Optional ShowMessages = True)
At the point where the msgbox is called, modify the code this way:
If showMessages = True Then 'The = True part is important here - see below.
showMessages is a Variant type
'The original statement that calls the msgBox
End If
Leave the rest of the code of the original sub unchanged
Modify the line where you call the original sub by throwing in False as an extra parameter. This results in OriginalSubNameyour set of parameters, False. This way you don't suppress the dialog box by default, but you do when you use it in your sub.
Wonder why I use an optional Variant type parameter?
The optional part: this prevents other existing subs from crashing when they call the modified sub
The Variant type part: optional parameters are always Variant type. That's also why you need to use If showMessages = True Then instead of just If showMessages Then.