How to create a public variable in a private module - ms-access

Basically It's a login form and i'm trying to save the ID which is the Me.CBOUsername.Column(0) but I get an error when i try to call it in another form.
Option Compare Database
Option Explicit
Public ID_ As String
Private Sub Command4_Click()
Dim strCBOPass As String
Dim strPassword As String
strCBOPass = Me.CBOUsername.Column(1)
strPassword = Me.txtpassword
If strCBOPass = strPassword Then
MsgBox "Login Successful!"
DoCmd.OpenForm "Form1"
DoCmd.Close acForm, Me.Name
ID_ = Me.CBOUsername.Column(0)
Else
MsgBox "login Unsuccessful!"
End If
End Sub

It may be a little easier to explain this way.
As an example of a global variable:
Public Global_Variable1 as String
Public Sub Procedure1()
Global_Variable1 = "Test"
End Sub
Public Sub Procedure2()
Call Procedure1
MsgBox (Global_Variable1) 'return Test
End Sub
Add the module by right-clicking, and using Insert > Module

Related

Make custom Wait Popup wait Until activity is done MS Access 2010 - 2016

I have a custom Popup that I call whenever an activity takes more than a second. Example:
PopupMsg("Getting records")
It makes a nice box that just shows the user something is happening, then it quietly disappears when the activity is done.
It works great for anything that only takes about 3 seconds, but beyond that, it disappears and then the user is left with the impression that the activity is finished. I'd like to make it stay up exactly as long as whatever activity is happening, but I've never been successful in determining this. I'd like to make sure all screen calculations are done before the popup disappears.
Here's how I implement my PopupMsg routine
Public Function PopUpMsg(strMsg As String, Optional strTitle As String)
Dim frmWait As New Form_Wait
If strTitle <> "" Then
frmWait.OpenForm strMsg & "...", strTitle
Else
frmWait.OpenForm strMsg & "..."
End If
End Function
Wait (A form called 'Wait' contains the following code)
Option Compare Database
Option Explicit
Public Property Let Message(ByVal MessageText As String)
Me.MessageLabel.Caption = MessageText
Me.Repaint
End Property
Public Property Get Message() As String
Message = Me.MessageLabel.Caption
End Property
Public Property Let Title(ByVal TitleText As String)
Me.Caption = TitleText
End Property
Public Property Get Title() As String
Title = Me.Caption
End Property
Public Function OpenForm(Optional MessageText As Variant, _
Optional TitleText As Variant) As Boolean
If Not IsMissing(MessageText) Then Me.MessageLabel.Caption = MessageText
If Not IsMissing(TitleText) Then Me.Caption = TitleText
Me.Visible = True
Me.Repaint
OpenForm = True
End Function
As you're opening a form through a class instantiation, it doesn't actually persist, and gets removed as soon as Access decides to do garbage collection and sees there's no reference to the form. If you want a form that persists until code execution is done, the best way is to pass back that form:
Public Function PopUpMsg(strMsg As String, Optional strTitle As String) As Object
Set PopUpMsg = New Form_Wait
If strTitle <> "" Then
PopUpMsg.OpenForm strMsg & "...", strTitle
Else
PopUpMsg.OpenForm strMsg & "..."
End If
End Sub
The rest of your code is still valid
You can call it like this:
Dim WaitForm As Object
Set WaitForm = PopupMsg("Getting records")
That way, you're still depending on garbage collection to remove the form, but it will close as soon as the function calling it is done.
You could also just open the form through DoCmd.OpenForm "Wait", reference it through the Forms collection, and close it using DoCmd.Close acForm, "Wait" at the end of your function, but then you'll have to close it actively. Full code for that approach:
Public Function PopUpMsg(strMsg As String, Optional strTitle As String)
DoCmd.OpenForm "Wait"
Dim frmWait As Form
Set frmWait = Forms!Wait
If strTitle <> "" Then
frmWait.OpenForm strMsg & "...", strTitle
Else
frmWait.OpenForm strMsg & "..."
End If
End Sub
Call it: PopupMsg("Getting records")
Close it at the end of execution: DoCmd.Close acForm, "Wait"
If you're not calling DoEvents in your code, there's another alternative:
Open the form using DoCmd.OpenForm "Wait", set it's TimerInterval to 1, and add DoCmd.Close acForm, Me.Name to it's Form_Close event

MS Access application return value

I need to make automatic application called from windows command line. This app start, make some DB operations and automatically exit.
Next I need to handle return values from Access. I tried everything what I find on Google but Access returns 0 every time. I need to return 1 or something else to tell cmd that there is error in database.
here is some code in VBA (access call Form when application starts):
Private Sub Form_Load()
Dim xSQL As String
Dim xRS As DAO.Recordset
xSQL = "select * from table1"
Set xRS = CurrentDb.OpenRecordset(xSQL, dbOpenDynaset)
xRS.MoveLast: xRS.MoveFirst
DoEvents
If xRS!field1 = "" Or IsNull(xRS!field1) Then
' HERE I WANT TO RETURN 1 OR ANY TRUE VALUE = ERROR
Application.Quit acQuitSaveAll
End If
' HERE I RETURN 0 = SUCCESS
Application.Quit acQuitSaveAll
End Sub
Some ideas how to do it?
I think your best solution can be setting an environment variable with the desired return value.
From your VBA code:
Private Declare Function SetEnvironmentVariable Lib "kernel32" _
Alias "SetEnvironmentVariableA" _
(ByVal lpName As String, _
ByVal lpValue As String) As Long
Private Sub Form_Load()
Dim xSQL As String
Dim xRS As DAO.Recordset
xSQL = "select * from table1"
Set xRS = CurrentDb.OpenRecordset(xSQL, dbOpenDynaset)
xRS.MoveLast: xRS.MoveFirst
DoEvents
If xRS!field1 = "" Or IsNull(xRS!field1) Then
SetEnvironmentVariable "ACCESSEXITCODE", "1"
Application.Quit acQuitSaveAll
End If
SetEnvironmentVariable "ACCESSEXITCODE", "0"
Application.Quit acQuitSaveAll
End Sub
From de command line:
IF %ACCESSEXITCODE%==1 GOTO HandleError

How to Pass Additional Method signature dynamically

Ok so i have this situation where i need to dynamically open a form, see code below, and, if possible, execute a known method for that form.
Open Form Method:
Public Sub ShowForm(par As Form, nm As String)
DoCmd.OpenForm nm
While IsOpen(nm)
DoEvents
Wend
End Sub
Caveat:
Not all forms will have the same method. So if possible add an additional optional parameter to pass through the method call, probably as a string value.
Some examples:
Form1:
public sub InitItem(id as string)
....
end sub
Form2:
public sub InitCategory(id as string)
....
end sub
How about going mad?
Private Sub Form_Open(Cancel As Integer)
Cancel = Not BuildForm(Me.Name, True)
End Sub
Function BuildForm(strFormName, blnRS, Optional strParent = "None", _
Optional strSubname = "", Optional strParentS = "", _
Optional NameMod = "", _
Optional strFormReport = "Form") As Boolean
OpenArgs, some notes
If Me.OpenArgs & "" = "" Then
Cancel = True
Exit Sub
End If
astrOpenArgs = Split(Me.OpenArgs, ",")

Compile time: Syntax error

I am able to add controls to a form when it is loaded. I need these controls to be to be catagorized so the user only can see a few at a time. My first thought was to attached the controls to particular tabs. Not sure why the syntax is off in the following code. Thanks for the help!
Private Sub Enter_Records_Click()
Dim stDocName As String
Dim tabPage As String
Dim tabNum As Integer
Dim i As Integer
Dim passedTabName As String
stDocName = "CLForm"
tabPage = "tabControl.tabPage"
stTabName = stDocName & tabPage
tabNum = 8 'the number of tabs on the "CLForm"
DoCmd.OpenForm stDocName, acDesign
For i = 0 To tabNum - 1
passedTabName = stTabName & i
CreateKeywords (stDocName, passedTabName)
Next i
DoCmd.Close acForm, stDocName, acSaveYes
DoCmd.OpenForm stDocName, acNormal
End Sub
Public Sub CreateKeywords(frmName As String, tabName As String)
Another idea that might be better, simply having buttons that show one category of controls at a time. Would this be easier?
You need to use the Call keyword when calling a method with more than one parameter and using parentheses.
For example, these would work:
Call CreateKeywords(stDocName, passedTabName)
CreateKeywords stDocName, passedTabName
//Example of using parentheses with one parameter
Msgbox (stDocName)
Welcome to the wonderful world of VBA. ;)
It is best be careful with calling arguments and parentheses:
Public Sub CallingSub()
CallingArg = "ABCDEF"
CalledFunc CallingArg
Debug.Print CallingArg ''Result: 987654
CallingArg = "ABCDEF"
CalledFunc (CallingArg) ''Result: ABCDEF
Debug.Print CallingArg
CallingArg = "ABCDEF"
Call CalledFunc(CallingArg)
Debug.Print CallingArg ''Result: 987654
End Sub
Public Function CalledFunc(CalledFuncArg)
CalledFuncArg = "987654"
CalledFunc = "Return"
End Function

Can I wrap an Access form with a transaction?

I want to make a form the essentially creates an invoice, but using some other related data as inputs or limits; In the process of adding items to the invoice, I need to reduce the items in another table. Since the user will enter several items at a time, I'd like to issue a "START TRANSACTION" when the form loads, and then do a "COMMIT" when the form updates. Thus, if they cancel the form, the other related tables (shown via subforms) would roll back to the previous values.
Can't be done using bound forms. You could use temporary tables to store the data and then update the main tables. A bit of a kludge but I've done that in the past.
See the TempTables.MDB page at my website which illustrates how to use a temporary MDB in your app.
Yes it can be done, to take control over the transaction in the form you need use this code:
Private Sub Form_Open(Cancel As Integer)
Set Me.Recordset = CurrentDb.OpenRecordset("NAME_OF_YOUR_TABLE_OR_QUERY")
End Sub
After that, you can use DBEngine to control the transaction.
It work for me (Im using Access 2007)
Note: If you insert a new record using the form interface it is visible when the Form_AfterInsert event is raised, therefore you can use DbEngine.Rollback in that event to undo the changes.
I have figured it out its possible to have it on bound forms. Everything you need to assign variable that contain an ID number on change event of any of the parent control. Than you need to transmit that ID value into the subform connected field and perform transaction on both forms the primary and the subform. Here is the example of how I did it.
Primary Form VBA
Option Compare Database
Option Explicit
Private boolFrmDirty As Boolean
Private boolFrmSaved As Boolean
Private Sub EmpolyeesID_Change()
Dim ordID As Integer
Dim subFormOrdID As Object
Set subFormOrdID = Forms!Order.OrderInstallation.Form!OrderID
ordID = Me.Form!OrderID
subFormOrdID.DefaultValue = ordID
End Sub
Private Sub Form_AfterDelConfirm(Status As Integer)
If Me.Saved = False Then Me.Saved = (Status = acDeleteOK)
End Sub
Private Sub Form_AfterUpdate()
Me.Saved = True
End Sub
Private Sub Form_Delete(Cancel As Integer)
If Me.Dirtied = False Then DBEngine.BeginTrans
Me.Dirtied = True
End Sub
'Check if form has got new values in it
Private Sub Form_Dirty(Cancel As Integer)
If Me.Dirtied = False Then DBEngine.BeginTrans
Me.Dirtied = True
End Sub
'Open Form as a Record Set and set the variables for it
Private Sub Form_Open(Cancel As Integer)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT * FROM Orders", dbOpenDynaset, dbAppendOnly)
Set Me.Recordset = rs
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim msg As Integer
If Me.Saved Then
msg = MsgBox("Do you want to commit all changes?", vbYesNoCancel)
Select Case msg
Case vbYes
DBEngine.CommitTrans
Case vbNo
DBEngine.Rollback
Case vbCancel
Cancel = True
End Select
Else
If Me.Dirtied Then DBEngine.Rollback
End If
End Sub
Public Property Get Dirtied() As Boolean
Dirtied = boolFrmDirty
End Property
Public Property Let Dirtied(boolFrmDirtyIn As Boolean)
boolFrmDirty = boolFrmDirtyIn
End Property
Public Property Get Saved() As Boolean
Saved = boolFrmSaved
End Property
Public Property Let Saved(boolFrmSavedIn As Boolean)
boolFrmSaved = boolFrmSavedIn
End Property
Private Sub ProductID_AfterUpdate()
'Calculations of VAT and Floor Price
Dim clcVAT As Integer
Dim sqlQry As String
Dim instID As Integer
instID = Me.Form!ProductID.Value
sqlQry = "SELECT Products.Price FROM Products WHERE Products.ProductID =" & instID & ""
Me.flPrice.RowSource = sqlQry
End Sub
Sub Form VBA
Option Compare Database
Option Explicit
'Transaction for sub-form
Private Sub Form_Open(Cancel As Integer)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT * FROM OrderInstallation")
Set Me.Recordset = rs
End Sub
Private Sub Form_AfterUpdate()
Dim emplID As Object
Dim cstmID As Object
Dim prdcID As Object
Dim DataArray As Variant
Dim RqrdFieldErorr As String
Dim qry As String
Set emplID = Me.Parent!EmpolyeesID
Set cstmID = Me.Parent!CustomerID
Set prdcID = Me.Parent!ProductID
If IsNull(emplID.Value) Or IsNull(cstmID.Value) Or IsNull(prdcID.Value) Then
MsgBox ("Please enter select required fields first")
Else
End If
End Sub
'Restrict updates of Installation subform if Employee, Customer and Product is not selected
Private Sub InstallationID_AfterUpdate()
Dim instID As Integer
Dim instPrice As Integer
Dim strQry As String
' Create query based on InstallationID value
instID = InstallationID.Value
strQry = "SELECT Installation.Price, Installation.InstallationID FROM Installation WHERE Installation.InstallationID =" & instID & ""
Me.Price.RowSource = strQry
End Sub