I have an access table that stores information about the steps completed on a product. When entering information, I have a form pop up asking which product they want to enter data for. Each record in the table gets its own checkbox (dynamically created). If information has already been recorded for that product, for that step then the checkbox is disabled. When all checkboxes are disabled I have a message box pop up saying all products for that step have been completed.
The issue: Say for whatever reason (operator choice, production reason, etc), work is done on product 4 for an order but not complete on 1, 2, 3. The code that I have says that all products have info entered just because that is the last record checked.
Dim Args As Variant
Dim i As Integer
Dim ctl As Control
Dim bCheck As Boolean
bCheck = False
If Not IsNull(Me.OpenArgs) Then
Args = Split(Me.OpenArgs, ";")
Me.txtForm = Args(0)
Me.lblChoices.Caption = Args(1)
End If
For Each ctl In Forms(Me.Name).Controls
If ctl.ControlType = acCheckBox Then
ctl.Value = False
If ctl.Enabled = True Then
bCheck = False
Else
bCheck = True
End If
End If
Next
If bCheck = True Then
fncMsgBox "Labor has been entered for all bundles on this step."
DoCmd.Close acForm, Me.Name
End If
This IF statement is the problem and its obvious to me why it doesn't work. I'm curious as to how I can get around this?
If ctl.Enabled = True Then
bCheck = False
Else
bCheck = True
End If
Exit the loop as soon as you find an enabled checkbox:
Dim Args As Variant
Dim i As Integer
Dim ctl As Control
Dim bCheck As Boolean
bCheck = False
If Not IsNull(Me.OpenArgs) Then
Args = Split(Me.OpenArgs, ";")
Me.txtForm = Args(0)
Me.lblChoices.Caption = Args(1)
End If
For Each ctl In Forms(Me.Name).Controls
If ctl.ControlType = acCheckBox Then
ctl.Value = False
If ctl.Enabled Then
bCheck = True
Exit For 'stop checking
End If
End If
Next
If bCheck Then
fncMsgBox "Labor has been entered for all bundles on this step."
DoCmd.Close acForm, Me.Name
End If
Note: you don't need = True in your If when the value you're checking already represents a boolean.
Related
I have a VBA form in Corel. Behaving exactly like a similar one in Excel...
Initially, when the form initialize event used to contain only some lines of code, the simple ending line me.txtCsv.Setfocus used to send the focus on it. I mean, it appeared being in edit mode with the cursor blinking inside.
After a period of time, after the application became complex, I am not able to send the focus to the text box in discussion.
I know that Activate event goes last and I also have in it the line me.txtCsv.Setfocus. But without expected result. Inside the Initialization event code I inserted that line Debug.Print Me.ActiveControl.Name & " - 1", changing 1 in 2, 3 up to 6 in many places, including the last line and all the time the name of the text box in discussion (txtCsv) appears in Immediate Window.
So, the control in discussion is the activate one, but the cursor is not inside it when the form is loaded.
TabStop is set to True. I set the TabIndex to 0.
The control is enabled and not blocked. I have created a new simple form with three text boxes and it works well.
I mean the text box which I want to send the focus, has the focus when the form is loaded, keeping a similar code in its Initialize or Activate events.
I compared all properties of the two forms and all text box controls and they are the same...
When I send the focus from another control on the form, the text box in discussion receives it.
It does not receive the focus (anymore) only when the form is shown, the focus being sent by Initialize or Activate evens.
Events code:
Private Sub UserForm_Activate()
Me.txtCsv.SetFocus
End Sub
Private Sub UserForm_Initialize()
Dim P As Printer, i As Long, NrImp As Long, prDefault As String, strJustEngr As String
Dim Printers() As String, n As Long, s As String, boolFound As Boolean
Dim strEng As String, MEngr As Variant, m As Variant, el As Variant, defSize As String
Dim strDropbox As String
boolOpt = True: boolFound = False
Me.cbPrinters.Clear
If Me.chkNewStyle.Value = True Then boolNewStyle = True
prDefault = Application.Printers.Default.Name
strEng = GetSetting(ECA_K, ECA_set, ECA_Engr, "No settings...")
If strEng <> "No settings..." Then
boolSelectedEngravers = True ' only adding engraver is possible...
MEngr = Split(strEng, "|")
'Incarcare in combo:
Me.cbPrinters.Clear
For Each el In MEngr
m = Split(el, ":")
Me.cbPrinters.AddItem m(0)
If m(0) = prDefault Then
boolFound = True
defSize = m(1)
End If
Next
Me.cbPrinters.Value = Me.cbPrinters.List(0)
With Me.btChoosePrinters
.Caption = "Add an Engraver"
.ControlTipText = "Add another Engraver(must be installed)"
End With
Me.btEliminatePrinters.Enabled = True
Me.lblPrinters.Caption = "Engravers: "
Me.cbPrinters.ControlTipText = "Select Engraver to be used!"
Else
Printers = GetPrinterFullNames()
For n = LBound(Printers) To UBound(Printers)
Me.cbPrinters.AddItem Printers(n)
If Printers(n) = prDefault Then boolFound = True
Next n
boolSelectedEngravers = False
End If
Debug.Print Me.ActiveControl.Name & " - 1"
If boolFound Then
Me.cbPrinters.Value = prDefault
Else
Me.lblStatus.Caption = "The default printer (""" & prDefault & """) is not a laser Engraver..."
End If
If GetSetting(ECA_K, ECA_set, "LowRAM", "No settings...") <> "No settings..." Then
boolLowRAM = CBool(GetSetting(ECA_K, ECA_set, "LowRAM", "No settings..."))
End If
If boolLowRAM = True Then
Me.chkLowRAM.Value = True
Else
Me.chkLowRAM.Value = False
End If
Debug.Print Me.ActiveControl.Name & " - 2"
'Direct engrave setting:
Dim strDirectEngrave As String
strDirectEngrave = GetSetting(ECA_K, ECA_set, ECA_Direct_Engrave, "Nothing")
If strDirectEngrave <> "Nothing" Then
Me.chkDirectEngrave.Value = CBool(strDirectEngrave)
If CBool(strDirectEngrave) = True Then
boolDirectEngrave = True
Else
boolDirectEngrave = False
End If
End If
'_______________________________________
strJustEngr = GetSetting(ECA_K, ECA_set, ECA_Just_Engrave, "Nothing")
If strJustEngr <> "Nothing" Then
'Application.EventsEnabled = False
boolChangeEngr = True
Me.chkJustEngrave.Value = CBool(strJustEngr)
boolChangeEngr = False
'Application.EventsEnabled = True
If CBool(strJustEngr) = True Then
Me.chkDirectEngrave.Enabled = True
boolJustEngrave = True
Me.frLocFoldPath.Enabled = True
Else
Me.frLocFoldPath.Enabled = False
Me.chkDirectEngrave.Enabled = False
End If
End If
Debug.Print Me.ActiveControl.Name & " - 3"
If boolSelectedEngravers Then
Application.EventsEnabled = False
Me.btGo.ForeColor = RGB(45, 105, 7)
Me.txtCsv.BackColor = RGB(153, 255, 51)
Me.btGo.Enabled = False
Me.txtCsv.SetFocus
Application.EventsEnabled = True
End If
strDropbox = GetSetting(ECA_K, ECA_set, ECA_Dropbox, "No value")
If strDropbox <> "No value" Then
If CBool(strDropbox) = True Then
Me.chkDropbox.Value = True
End If
End If
AllRefresh
Me.chkCloseDoc.Value = True
Me.txtCsv.SetFocus
Debug.Print Me.ActiveControl.Name & " - 4"
End Sub
Private Sub AllRefresh()
Application.Optimization = False
Application.EventsEnabled = True
If Documents.Count > 0 Then
ActiveWindow.Refresh
ActiveDocument.PreserveSelection = True
End If
Application.Refresh
End Sub
Is there something else, crossing your mind, to be tested?
In the meantime I did some more tests, respectively:
I created a new project (.GMS file) and I imported the form in discussion.I started commenting all the Initialize event code, except the last two code lines.
It didn't set the focus! Commenting everything, letting only the Activate event code, it worked.
I started to un-comment lines in Initialize event code and I found a line not allowing the focus to be sent to that text box.
Setting the value of the combo: Me.cbPrinters.Value = Me.cbPrinters.List(0), moving it in the Activate event code, before the part pointing to txtCSV, worked well.
Now, I tried to do the same in the original form and it does not work...
The above question has been solved by Disabling followed by Enabling of the text box in discussion, but only doing that in Form Activate event. It did not work in Initialize event...
Private Sub UserForm_Activate()
Me.txtCsv.Disable: Me.txtCsv.Enable
Me.txtCsv.SetFocus
End Sub
I am using the following code as event handler for the button cmd_Edit on my main form:
Private Sub cmd_Edit_Click()
If intCanEdit = False Then
If MsgBox("Sollen vorhandene Prozeduren verändert werden ?", vbYesNo, "Frage") = vbNo Then Exit Sub
Me.AllowEdits = True
Me.AllowAdditions = True
Dim sbfrm As Control
For Each sbfrm In Me.Controls
With sbfrm
Select Case .ControlType
Case acSubform
.Form.AllowEdits = True
.Form.AllowAdditions = True
End Select
End With
Next sbfrm
intCanEdit = True
Else
Me.AllowEdits = False
Me.AllowAdditions = False
For Each sbfrm In Me.Controls
With sbfrm
Select Case .ControlType
Case acSubform
**.Form.AllowEdits = False**
.Form.AllowAdditions = False
End Select
End With
Next sbfrm
intCanEdit = False
End If
cmd_Edit.Caption = IIf(intCanEdit, "Click to Save", "Click to Edit")
cmd_Edit.BackColor = IIf(intCanEdit, vbRed, vbGreen)
End Sub
The form loads with intCanEdit set to False. When i click the button once (setting it to true) everything works as expected, when i click it again (setting it to false again) i get an error (Runtime error 2455) with the Debugger sending me to the line i marked with asterisks in the above code.
Does anybody have an idea why i can set the property to True with my code, but get an error when i try to set the same property back to False? :(
I'm trying to build in an error checking for two option boxes I have:
projectOptionbox
implementOptionbox
This is the current code I have right now for error checking a couple of other things, just unsure as to what kind of code is necessary for option boxes:
Function CheckInputs() As Boolean
If Not CheckControl(Me.nameTextbox, "Please enter your Name") Then Exit Function
If Not CheckControl(Me.projectTextbox, "Please enter a Project Name") Then Exit Function
If Not CheckControl(Me.initiativeCombobox, "Please select an Initiative") Then Exit Function
If Not CheckControl(Me.audienceCombobox, "Please select an Audience") Then Exit Function
If Not CheckControl(Me.impactCombobox, "Please select an Impact Type") Then Exit Function
If Not CheckControl(Me.hoursTextbox, "Please enter the amount of Monthly Hours") Then Exit Function
If Not CheckControl(Me.peopleTextbox, "Please enter the amount of People on the Project") Then Exit Function
If Not CheckControl(Me.lengthListbox, "") Then If Not CheckControl(Me.lengthListbox2, "Please select Project Length") Then Exit Function
CheckInputs = True
End Function
Private Function CountSelectedListBoxItems(lb As MSForms.ListBox) As Long
Dim i As Long
With lb
For i = 0 To .ListCount - 1
If .Selected(i) Then CountSelectedListBoxItems = CountSelectedListBoxItems + 1
Next i
End With
End Function
Function CheckControl(ctrl As MSForms.Control, errMsg As String) As Boolean
Select Case TypeName(ctrl)
Case "TextBox"
CheckControl = Trim(ctrl.Value) <> ""
Case "ComboBox"
CheckControl = ctrl.ListIndex <> -1
Case "ListBox"
CheckControl = CountSelectedListBoxItems(ctrl) > 0
' Case Else
End Select
If errMsg = "" Then Exit Function
If CheckControl Then Exit Function
ctrl.SetFocus
MsgBox errMsg
End Function
From what I gathered from the post, it sounds like you want to develop a method of confirming that an OptionButton within a group has been selected. (Not looking for an application error per se, but rather a violation of your business logic).
This is a bit more complicated than the checks on the other controls because the other controls are standalone. There are two options. (1) Since the OptionButton control doesn't actually support a null state, you can set a default option on the Form's Initialization. Then, irrespective of what the user does, one of the options will always be selected.
The other option is to use the GroupName property of the OptionButtons to put buttons into a group. (When optionbuttons are in a group, this ensures that one of them is selected). Next, you can loop through all of the controls looking for OptionButtons of the same GroupName, then check if at least one of them is selected. A helper function such as the one below should do the trick:
Private Function OptionBoxGroupHasASelection(inputControl As MSForms.Control) As Boolean
Dim ctrl As MSForms.Control
Dim sGroup As String
Dim bOutput As Boolean
If TypeName(inputControl) <> "OptionButton" Then
OptionBoxGroupHasASelection = False
Exit Function
End If
If inputControl.Value = True Then
OptionBoxGroupHasASelection = True
Exit Function
End If
sGroup = inputControl.GroupName
bOutput = False
For Each ctrl In Me.Controls
If TypeName(ctrl) = "OptionButton" Then
If ctrl.GroupName = sGroup Then
If ctrl.Value = True Then
bOutput = True
Exit For
End If
End If
End If
Next ctrl
OptionBoxGroupHasASelection = bOutput
End Function
I'm using VBA in Word to create a SmartForm where the user can tick a checkbox in order to display certain information which I have Bookmarked using the naming format "TEXT_BUTANE"
Because each product (BUTANE/ PROPANE/ ETHANE) will have multiple Bookmarks throughout the document I'm naming them "TEXT_BUTANE1" "TEXT_BUTANE2" etc
So I'd then like to loop through all Bookmarks and hide/show sections in the document depending on which group it belongs to i.e all Bookmarks starting with "TEXT_BUT" would be considered a group that would be collectively hidden (or shown if checked)
I'm getting a compile error "Next without For" but from what I can see the syntax is correct
It was working before creating the LoopThroughBookmarks Sub, but I need something like this so I can hide/show multiple sections of the document
Any help would be much appreciated
Private Sub CHECK_BUTANE_Click()
Dim vw As Word.View
Dim bChecked As Boolean
Dim bkm As Word.Bookmark
'turned on non-printing characters individually so that
'not displaying Hidden text does not affect these settings.
Set vw = Application.ActiveWindow.View
If vw.ShowAll = True Then 'if TRUE then SHOW following
vw.ShowParagraphs = True
vw.ShowObjectAnchors = True
vw.ShowTabs = True
vw.ShowHyphens = True
vw.ShowOptionalBreaks = True
vw.ShowSpaces = True
End If
vw.ShowAll = False 'if FALSE then HIDE following
vw.ShowHiddenText = False
bChecked = Me.CHECK_BUTANE.Value
'if CHECKED
If bChecked Then
Call LoopThroughBookmarks("BUT", True) 'then TRUE so loop through bookmarks passing PRODUCT
Else
Call LoopThroughBookmarks("BUT", False) 'then FALSE so loop through bookmarks passing PRODUCT
End If
End Sub
Public Sub LoopThroughBookmarks(product As String, bChecked As Boolean)
Dim bkm As Bookmark
Dim strMarks() As String
Dim intCount As Integer
Dim checkString As String
Dim bkmName As String
checkString = "CHECK_" + product 'CHECK_BUT or CHECK_PRO or CHECK_MET
If ActiveDocument.Bookmarks.Count > 0 Then
ReDim strMarks(ActiveDocument.Bookmarks.Count - 1)
intCount = 0
For Each bkm In ActiveDocument.Bookmarks 'Set bkm to be current Bookmark
bkmName = Left$(bkm.Name, 9) 'taking first 9 chars for bkm comparison
If bkmName = checkString Then 'if TRUE
bkm.Range.Font.Hidden = Not bChecked 'then hidden is false
Else 'is FALSE
bkm.Range.Font.Hidden = bChecked 'so stay visibility
Next bkm
End If
End Sub
You are probably getting that error because you are missing an End If immediately before the Next in this part of your code:
If bkmName = checkString Then 'if TRUE
bkm.Range.Font.Hidden = Not bChecked 'then hidden is false
Else 'is FALSE
bkm.Range.Font.Hidden = bChecked 'so stay visibility
Next bkm
As a further observation, you could probably simplify this part of your code
bChecked = Me.CHECK_BUTANE.Value
'if CHECKED
If bChecked Then
Call LoopThroughBookmarks("BUT", True) 'then TRUE so loop through bookmarks passing PRODUCT
Else
Call LoopThroughBookmarks("BUT", False) 'then FALSE so loop through bookmarks passing PRODUCT
to
Call LoopThroughBookmarks("BUT",Me.CHECK_BUTANE.Value)
What I'd like to accomplish:
Do While ctr < List and Break = False
code that works here...
DoEvents
If KeyDown = vbKeyQ
Break = True
End If
loop
Break out of a loop by holding down a key (eg, Q). I've read up on DoEvents during the loop in order to achieve the functionality that I want. The idea is to have a Do While loop run until either the end of the list is reached or when Q is held down. I'm having issues getting the code to work the way I want, so I'm reaching out to hopefully end the frustration. My experience with VBA is very limited.
UPDATE - More code to expose where the problem might be. This is all in the order I have it (in case order of subs makes a difference:
Private Sub Form_KeyPress(KeyAscii As Integer)
Dim strChar As String
strChar = UCase(Chr(KeyAscii))
If strChar = "Q" Then
blnQuit = True
Debug.Print "Q pressed"
End If
End Sub
Private Sub Master_Report_Click()
Dim i As Integer
Dim Deptarray
blnQuit= False
If IsNull(Me.Hospital) Then
MsgBox ("Please Choose a Hospital")
Else
DoCmd.OpenForm "Report Print/Update", acNormal, , , , acDialog
If Report_choice = "Current_List" Then
Debug.Print "Create master rec report"
DoCmd.OpenReport "Master Rec Report", acViewPreview
DoCmd.RunCommand acCmdZoom100
ElseIf Report_choice = "Update_All" Then
total = (DCM_Dept.ListCount - 1)
ctr = 1
Do While ctr < (DCM_Dept.ListCount) And LoopBreak = False
Debug.Print "LoopBreak: "; LoopBreak
Debug.Print "Counter: "; ctr
DCM_Dept.Value = DCM_Dept.Column(0, ctr)
Update_Site (Me.Hospital)
ctr = ctr + 1
'DoEvents
' If vbKeyQ = True Then
'LoopBreak = True
'End If
Loop
Debug.Print "Update loop exited"
Debug.Print "Create master rec report"
DoCmd.OpenReport "Master Rec Report", acViewPreview
DoCmd.RunCommand acCmdZoom100
Else
End If
End If
End Sub
Private Sub Update_Site(Site As String)
If IsNull(Me.Hospital) Then
MsgBox ("Please Choose a Hospital")
ElseIf IsNull(Me.DCM_Dept) Then
MsgBox ("Please Choose a Department")
ElseIf Site = "FORES" Then
Debug.Print "Run FORES update macro"
DoCmd.RunMacro "0 FORES Master Add/Update"
ElseIf Site = "SSIUH" Then
Debug.Print "Run SSIUH update macro"
DoCmd.RunMacro "0 SSIUH Master Add/Update"
End If
End Sub
Report_choice and LoopBreak are both Public variables. My original idea was to have a popup form floating over the main form to display a counter ("Processing department X of Y") and a button to break the loop on there. I realized that the form was unresponsive while the Update_Site() was running its macro so I decided to go with holding a key down instead.
So, where do I go from here to get OnKeyDown to work? Or, is there a better way to do it?
Try to set the Key Preview of the form to Yes and add a variable blnQuit and a key press event in your form like this:
Private blnQuit As Boolean
'form
Private Sub Form_KeyPress(KeyAscii As Integer)
Dim strChar As String
strChar = UCase(Chr(KeyAscii))
If strChar = "Q" Then
blnQuit = True
End If
End Sub
Then check the blnQuit in your Do While condition, like this:
blnQuit = False
Do While ctr < List And Not blnQuit
code that works here...
DoEvents
loop