I have a database with the following
Mainfrm Form (Main Form - it has popup messages on load event)
kikThemOut Form (Loads hidden with Main Form and every 5 sec it checks for field value on table if it is 1 then call the Function fGetOut())
GetOutMod Module (has fGetOut() Function)
it works all fine, except when application closing it loads the popup alerts from Mainfrm again! which should not load.
Mainfrm Form Code
Private Sub Form_Load()
'to check for T&I notifications
Dim trs As Recordset
Set trs = CurrentDb.OpenRecordset("Y22_CurrMonth")
If trs.EOF = False Then
Dim tMsg, tStyle, tTitle, tHelp, tCtxt, tResponse, tMyString
tMsg = "There are Notifications Due, Do you want to view them?"
tStyle = vbYesNo + vbExclamation + vbDefaultButton2
tTitle = "Notifications Alert"
tHelp = "DEMO.HLP"
tCtxt = 1000
tResponse = MsgBox(tMsg, tStyle, tTitle, tHelp, tCtxt)
If tResponse = vbYes Then ' User chose Yes.
DoCmd.OpenReport "Notifications Current Month", acViewReport, acWindowNormal
Else
tMyString = "No"
End If
End If
'to load the checker form
DoCmd.OpenForm "kikThemOut", , , , , acHidden
End Sub
and this is the GetOutMod Module to force users to exit the db
GetOutMod Module
Option Compare Database
Option Explicit
Function fGetOut() As Integer
Dim RetVal As Integer
Dim db As DAO.Database
Dim rst As Recordset
On Error GoTo Err_fGGO
Set db = DBEngine.Workspaces(0).Databases(0)
Set rst = db.OpenRecordset("KickEmOff", dbOpenSnapshot)
If rst.EOF And rst.BOF Then
RetVal = True
GoTo Exit_fGGO
Else
If DSum("GetOut", "KickEmOff") = "1" Then
Application.Quit
Else
RetVal = True
End If
End If
Exit_fGGO:
fGetOut = RetVal
Exit Function
Err_fGGO:
'Note lack of message box on error
Resume Next
End Function
And this code in the load event of kikThemOut form to check for the same condition, if it is 1 then load this popup message (I could not add popup message to my GetOutMod Module with the function fGetOut)
kikThemOut form Code
Private Sub Form_Timer()
If DSum("GetOut", "KickEmOff") = "1" Then
Set TaskDialogAC = New cTaskDialog
With TaskDialogAC
.Init
.MainInstruction = "Dashboard Maintenance"
.Flags = TDF_CALLBACK_TIMER
.Content = "The Dashboard will be closed after 20 seconds for maintenance"
.CommonButtons = TDCBF_CLOSE_BUTTON
.IconMain = IDI_WINLOGO
.Footer = "Closing in 20 seconds..."
.Title = "Dashboard Maintenance"
.AutocloseTime = 20 'seconds
.ParenthWnd = Me.hwnd
.ShowDialog
End With
Call fGetOut
Else
If DSum("GetOut", "KickEmOff") = "0" Then
DoCmd.Requery
End If
End If
End Sub
Really hard to read your code and figure out where your function is being called from.
But I'm assuming this should work for you as described
Add this before your fGetOut function
Public blClosing as Boolean
And then add this inside your function at the top (after On Error GoTo Err_fGGO)
if blClosing then
blClosing = False
Exit function
Else
blClosing = True
End if
Related
Instead of using msgBox, I want to create My msgBox by form, "frmMsg".
"frmMsg" form has tow bottom, (Ok and No), and a label(lblMsg) for show message.
"frmMsg" property: Pop Up = Yes , Modal = Yes.
My Function for Open form is MsgInfo:
Public Function MsgInfo(Optional msg As String = "Are You Ok?", _
Optional msgCaption As String = "Warning" ) As Boolean
MsgInfo = False
DoCmd.OpenForm "frmMsg"
Form_frmMsg.Caption = msgCaption ' Set Caption of Form
Form_frmMsg.lblMsg.Caption = msg ' Set Message of Form
MsgInfo = MsgInfoResult ' MsgInfoResult is Public Variable to store MsgInfo Result (Ok Bottom(True) or No Bottom(False) )
End Function
I used this in other Form, Example For delete Customer in Customer List ( Delete Bottom ):
Private Sub btnDelete_Click()
DoCmd.SetWarnings False
If MsgInfo("Are You Sure Delete Customer?", , "Delete Customer!") = True Then
' Run SQL for Delete Customer
Dim sqlDelete As String
sqlDelete = "DELETE tblCustomer.*, tblCustomer.RowId " & _
"FROM tblCustomer " & _
"WHERE tblCustomer.RowId=[Forms]![frmCustomerList]![frmCustomerListSub]![RowId]"
DoCmd.RunSQL sqlDelete
Form_frmCustomerList.frmCustomerListSub.Requery
End If
DoCmd.SetWarnings True
End Sub
My Problem is After Open MsgInfo Form Before the user answers this, the Next commands (Sql) are executed.
To solve the problem, I changed AcWindowsMode in Function MsgInfo:
DoCmd.OpenForm "frmMsg"
to
DoCmd.OpenForm "frmMsg", , , , , acDialog
problem solved but There was another problem. The following commands are not executed:
Form_frmMsg.Caption = msgCaption ' Set Caption of Form
Form_frmMsg.lblMsg.Caption = msg ' Set Message of Form
MsgInfo = MsgInfoResult ' MsgInfoResult is Public Variable
please help me.
I am no Expert in VBA or Any Programming Language neither am I a programmer by Profession. But , I've had my fair share in dealing with programming languages as a hobby.
In VBA, Any Code after the ,,,,,acDialog can't be run until the Form is closed so , What you need to do is find a way to Pass the Messages somewhere and have the form Retrieve it.
Create a Module to Pass the Message from the Function to the Form
'a Module named Module_gVar
Public MessageHeader as String 'Optional A Separate Text Box For a Header
Public MessageBody as String 'Main Body
Public MessageTitle as String 'Caption of the Form
Public MessageReturn as Boolean
This is the function to Call the Message box and Get a simple True or False Return
'Function To Call the MessageBox
Public Function CallMessageBox ( _
Optional msgHeader as string , _
Optional msgBody as string , _
Optional msgTitle as string)
Module_gVar.MessageTitle = msgTitle
Module_gVar.MessageHeader = msgHeader
Module_gVar.MessageBody = msgBody
DoCmd.OpenForm "frmMessage",,,,,acDialog
CallMessageBox = Module_gVar.MessageReturn
'You can have the CleanUp on a Separate Function
'Since it's not a Procedure Variable it Isn't cleaned when it goes out of scope
Module_gVar.MessageTitle = ""
Module_gVar.MessageBody = ""
Module_gVar.MessageHeader = ""
Module_gVar.Return = False
End Function
Now for the Form itself.
'Retrieve the Strings
Private Sub Form_Current()
Me.[YourHeaderTextBox] = Module_gVar.MessageHeader
Me.[YourBodyTextBox] = Module_gVar.MessageBody
Me.Caption = Module_gVar.MessageTitle
End Sub
'A Button to Return a Value
Private Sub cmdYes_Click() ' Yes button
Module_gVar.MessageReturn = True
DoCmd.Close acForm,"frmMessage",acSaveNo
End Sub
Private Sub cmdNo_Click() ' No Button
Module_gVar.MessageReturn = False
Docmd.Close acForm,"frmMessage",acSaveNo
End Sub
You can Optimize the code from here on but it's the basic structure. I Recommend creating a Class Module in which you can retrieve strings , input strings , and call Forms.
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 have some VBA code that checks a person's job title before allowing someone to edit the document. After adding this code in I occasionally get an "Automation Error Catastrophic Failure" message only when opening the spreadsheet. As far as I can tell it does not damage any part of the workbook, and you just have to exit the command debugger twice before it opens. Obviously others at work see this message and overreact to it. Please see my functions that activate when opening the workbook.
Private Sub Workbook_Open()
Sheets("Start Here").Select
Range("A3").Select
End Sub
Private Sub Worksheet_Activate()
If Usercheck() = True Then
ProtectionOff
Else
ProtectionOff
Range("A1:V260").Locked = True
ProtectionOn
End If
End Sub
Function Usercheck() As Boolean
Dim user As String
Dim title As String
On Error GoTo ErrorHandler
user = UserName()
title = WorksheetFunction.VLookup(user,
Sheets("BaseTables").Range("tblStaff[[#All],[Username]:[Title1]]"), 2, False)
If Left(title, 20) = "Technical Specialist" Then
Usercheck = True
ElseIf Left(title, 19) = "Engineering Manager" Then
Usercheck = True
ElseIf Left(title, 9) = "Team Lead" Then
Usercheck = True
Else
Usercheck = False
End If
Exit Function
ErrorHandler:
Usercheck = False
End Function
Public Function UserName()
UserName = Environ$("UserName")
End Function
I have a Problem with my Userform. It should automatically Switch to another TextBox when an selection in the catpart made. I get the Automation Error: It is illegal to call out while inside message filter.
Run-time error '-2147418107 (80010005)
Sub Auswahl_Click()
Dim sel As Object, Objekt As Object, ObjektTyp(0)
Dim b, Auswahl, i As Integer
ObjektTyp(0) = "Body"
Set sel = CATIA.ActiveDocument.Selection
For i = 1 To 6
sel.Clear
UserFormNow.Controls("Textbox" & i).SetFocus
Auswahl = sel.SelectElement2(ObjektTyp, "Wähle ein Body aus...", False)
Set b = CATIA.ActiveDocument.Selection.Item(i)
If Auswahl = "Normal" Then
Set Objekt = sel.Item(i)
UserFormNow.ActiveControl = Objekt.Value.Name
sel.Clear
End If
i = i + 1
Next
sel.Clear
End Sub
' EXCEL DATEI ÖFFNEN____________________________________
Sub Durchsuchen1_Click()
Dim FPath As String
FPath = CATIA.FileSelectionBox("Select the Excel file you wish to put the value in", "*.xlsx", CatFileSelectionModeOpen)
If FPath = "" Then
Else
DurchsuchenFeld.AddItem FPath
ListBox1.Clear
ListBox1.AddItem "Bitte wählen Sie das Panel"
TextBox1.SetFocus
End If
End Sub
' FORMULAR SCHLIEßEN____________________________________
Sub ButtonEnd_Click()
ButtonEnd = True
Unload UserFormNow
End Sub
First you have to know that when you use an UI and still want to interact with CATIA, you have to choices:
Launch the UI in NoModal: mode UserFormNow.Show 0
Hide the UI each time you want to interact with CATIA: Me.Hide or UserFormNow.Hide
Then, I strongly recommend you to avoid looking for items with names:
UserFormNow.Controls("Textbox" & i).SetFocus
If you want to group controls and loop through them, use a Frame and then use a For Each loop.
For Each currentTextBox In MyFrame.Controls
MsgBox currentTextBox.Text
Next
Regarding your code, many simplifications can be done:
Private Sub Auswahl_Click()
Dim sel As Object
Dim currentTextBox As TextBox
Dim Filter As Variant
ReDim Filter(0)
Filter(0) = "Body"
Set sel = CATIA.ActiveDocument.Selection
'Loop through each textbox
For Each currentTextBox In MyFrame.Controls
sel.Clear
'Ask for the selection and test the result at the same time
If sel.SelectElement2(Filter, "Wahle ein Body aus...", False) = "Normal" Then
'Get the name without saving the object
currentTextBox.Text = sel.Item2(1).Value.Name
Else
'allow the user to exit all the process if press Escape
Exit Sub
End If
Next
sel.Clear
End Sub
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