initialize ms access form fields - forms

Is there a generic VBA code for initializing all fields on an MS Access form? I am very weak in the VBA coding department but i would like to have the form initialized in the following 2 conditions:
1) When someone double clicks the form to open it.
2) After someone clicks the "save" button to save the newly created record.
Any help would be greatly appreciated.
edit
i have tried using the me.refresh code in the "on click" event and it does not seem to initialize all fields. The only code in the form is the following:
Private Sub Form_BeforeUpdate(Cancel As Integer)
Dim ctl As Control
On Error GoTo Err_BeforeUpdate
If Me.Dirty Then
If MsgBox("Do you want to save?", vbYesNo + vbQuestion, _
"Save Record") = vbNo Then
Me.Undo
End If
End If
Exit_BeforeUpdate:
Exit Sub
Err_BeforeUpdate:
MsgBox Err.Number & " " & Err.Description
Resume Exit_BeforeUpdate
End Sub

The only differences between #'s 1 and 2 are the event handlers.
1
Private Sub Form_Load()
DoCmd.GoToRecord , , acNewRec
End Sub
2
Private Sub SomeButton_Click()
'Your code to save the record the user entered
DoCmd.GoToRecord , , acNewRec
End Sub
Both of these Subs should go to the next (new) record.
On Me.Refresh :
Me.Refresh only updates the records in the current form, but will not show new or deleted records.

Related

Microsoft access end of records error '2105'

I have a Microsoft access form that allows users to navigate through records via two buttons "Back" and "Next". The problem is that if a user is on the first record and clicks "Back" a really tacky error message appears. How can I prevent this from happening?
So pretty much, If the record selected is =1 and Back button is pressed then do nothing.
Try this:
Previous record:
If CurrentRecord <> 1 Then DoCmd.GoToRecord , , acPrevious
Next record:
If CurrentRecord <> Recordset.RecordCount Then DoCmd.GoToRecord , , acNext
Consider adjusting your error handler accordingly:
Private Sub Back_Click()
On Error GoTo ErrHandle
'...
ExitHandle:
' UNINITIALIZE SET OBJECTS
Exit Sub
ErrHandle:
If Err.Number = 2105 Then
DoCmd.GoToRecord , , acFirst
Else
MsgBox Err.Number & Err.Description, vbCritical, "RUNTIME ERROR"
End if
Resume ExitHandle
End Sub

How to check if form view is filterbyform

I am using two forms. The form this code is from shows a weekly summary of booked appointments: it contains text boxes that display a count of appointments for each team on each day, and daily and weekly totals. I have replaced the double click events for all the text boxes with a function. When a text box is double clicked another form is used to display records that are counted in that text box. It all works great unless the user already has the details form open and has selected the filter by form option but has not yet applied the filter.
I check to see if the details form is open, if not then I open it with an SQL sting to show the records for the counted appointments. If the details form is already open then I check to see if a filter is applied, remove it, then filter to show the records for the counted appointments.
If CurrentProject.AllForms("MyForm").IsLoaded = False Then
DoCmd.OpenForm "MyForm", , mysql
Else
If Forms("MyForm").FilterOn = True Then Forms("MyForm").FilterOn = False
Forms("MyForm").Filter = myfil
Forms("MyForm").FilterOn = True
End If
How can I check if the details form is in the filter by form view/state? and if it is, close it. So I can apply the filter to show the records of the counted appointments.
Ah, good find with the Filter event!
I would use a public variable in the module of MyForm that saves the FilterByForm state and can be accessed from the outside:
Option Compare Database
Option Explicit
Public bFilterByForm As Boolean
It is set and cleared in the Filter and ApplyFilter events:
Private Sub Form_ApplyFilter(Cancel As Integer, ApplyType As Integer)
' acShowAllRecords = 0
' acApplyFilter = 1
' acCloseFilterWindow = 2
Debug.Print "Form_ApplyFilter: " & ApplyType
' I don't think checking for ApplyType is necessary -
' in each case the filter windows is closed.
' FilterByForm is finished!
bFilterByForm = False
End Sub
Private Sub Form_Filter(Cancel As Integer, FilterType As Integer)
' acFilterByForm = 0
' acFilterAdvanced = 1
Debug.Print "Form_Filter: " & FilterType
If FilterType = acFilterByForm Then
' FilterByForm is active!
bFilterByForm = True
End If
End Sub
and using this variable your calling sub can check the FilterByForm state:
If Form_MyForm.bFilterByForm Then
' FilterByForm is active: close the form!
DoCmd.Close acForm, "MyForm"
DoCmd.OpenForm "MyForm", , mysql
End If
Massive thank you to Andre for all his help, my final solution is mostly his work with a slight edit to allow the form to stay open. I added this function to details form AKA MyForm
Public Sub RunApplyFilter()
Forms("MyForm").SetFocus
DoCmd.RunCommand acCmdApplyFilterSort
End Sub
And the final checks use Andre method to identify if MyForm is in FilterByForm view.
If CurrentProject.AllForms("MyForm").IsLoaded = False Then
DoCmd.OpenForm "MyForm", , mysql
Else
If [Form_MyForm].bFilterByForm = True Then Forms("MyForm").RunApplyFilter
If Forms("MyForm").FilterOn = True Then Forms("MyForm").FilterOn = False
Forms("MyForm").Filter = myfil
Forms("MyForm").FilterOn = True
End If
Thanks again to Andre.

List an MS Access form's controls with their events

I have a humongous Access form with hundreds of controls, all with some events.
One of them is throwing an error crying about "Validation or After Update event". No control name, nothing more to go by.
So I figured I'd list all the forms with all their validation rules and all their events (not all of them are "[Event procedure]", some are custom function calls).
Is there any way to get a list of a control's events?
My code so far:
Sub ListAllControlsAndTheirEvents(FormToCheck As Form)
Dim ctrlCurrent As Control
For Each ctrlCurrent In FormToCheck.Controls
Debug.Print "Name: " & ctrlCurrent.Name
On Error Resume Next
Debug.Print "Validation: " & ctrlCurrent.ValidationRule 'Not all controls have a ValidationRule property.
On Error GoTo 0
For Each eventCurrent In ctrlCurrent.events 'this thing doesn't exist :(
Debug.Print "Event: " & eventCurrent.Name & "; value: " & eventCurrent.whatever
Next
Next
End Sub
So, is there a way to implement this part?
For Each eventCurrent In ctrlCurrent.events 'this thing doesn't exist :(
Debug.Print "Event: " & eventCurrent.Name & "; value: " & eventCurrent.whatever
Next
Digging through the code module won't give me the custom function event calls, just the [Event Procedure] codes.
You could use typename to determine the type of control, then set so something like if typename(x) ="CommanButton" then set cb=x, then loop the properties, for property names beginning with On, then if there is an [Event Procedure] you know there's an event, also you can then narrow down your search to x_Click
The code below should identify and list all events (whether blank, [Event Procedure], or a custom function) for each control on the form. I tested it on Access 2010 by creating a blank form and adding several controls. I made sure to assign some standard events and custom functions to a few controls in order to validate.
Public Sub ListAllControlsAndTheirEvents(FormToCheck As Access.Form)
Dim ctrlProp As Object
Dim ctrlCurrent As Access.Control
For Each ctrlCurrent In FormToCheck.Controls
Debug.Print "Name: " & ctrlCurrent.Name
If PropertyExists(ctrlCurrent, ctrlProp, "ValidationRule") Then
Debug.Print "Validation: " & ctrlProp.Value
End If
For Each ctrlProp In ctrlCurrent.Properties
' Category 4 type 8 identifies an event property
If ctrlProp.Category = 4 And ctrlProp.Type = 8 Then
Debug.Print _
"Event: " & ctrlProp.Name & "; " & _
"Value: " & ctrlProp.Value
End If
Next
Next
End Sub
Private Function PropertyExists( _
ByRef ctrlCurrent As Access.Control, _
ByRef ctrlProp As Object, _
ByRef PropName As String _
) As Boolean
On Error Resume Next
Set ctrlProp = ctrlCurrent.Properties(PropName)
PropertyExists = Err.Number = 0
End Function
I know that this question has been marked as answered like 4 years ago.
I have been to this question in my search for the same thing in Excel.
This question was the source behind my search for an answer to a similar question.
I have found an answer to this question using TLI.
The answer I provided here is meant to help other people reach for a solution quickly and painlessly.
There is NO intention of gaining merits/points/reputation but just to help others get an answer I've only reached after spending so much time and energy.
I am no expert in Access VBA nor am I in Excel VBA but I think TypeLib Info can be used in Access too.
Requirement: Reference to TypeLib Information library at C:\Windows\SysWow64\TLBINF32.DLL
Sub printControlEventNames(ByVal o As Object)
Dim t As TLI.TLIApplication
Set t = New TLI.TLIApplication
Dim ti As TLI.TypeInfo
Set ti = t.ClassInfoFromObject(o)
Dim mi As TLI.MemberInfo
For Each mi In ti.DefaultEventInterface.Members
Debug.Print mi.Name
Next
End Sub
My question and my own solution can be found here.

Error 2427 "You entered an expression that has no value." in Access form (VBA)

I am using Access VBA, and I have two forms (form1 and form2), in form 1 I have a listbox control (form1.modifiable49). I choose a list item and with a button control click I open the second form (form2),
In the second form I have some table columns, and I have a textbox where I store my variable, I would like to open form2 with the element that equals the value of modifiable49
I have:
Private Sub Form_Load()
Me.Texte = [Forms]![Form1]![Modifiable49]
Me.Filter = "[id_parcelle]=" & Texte
Me.FilterOn = True
End Sub
but when I choose the value in the listbox and I excute I get error 2427:
You entered an expression that has no value.
The expression may refer to an object that has no value, such as a form, a report, or a label control.
This will not fail and will list the value of Texte for you to investigate:
Private Sub Form_Load()
Me!Texte.Value = [Forms]![Form1]![Modifiable49].Value
Debug.Print "Texte:", Me!Texte.Value
Me.Filter = "[id_parcelle]=" & Me!Texte.Value & ""
' or, if Texte is a string:
' Me.Filter = "[id_parcelle]='" & Me!Texte.Value & "'"
Me.FilterOn = Not IsNull(Me!Texte.Value)
End Sub

Displaying a recordset on a form in Access 2010 using VBA

I'm developing a data retrieval application in Access 2010 in which the user chooses which table, columns, and rows to view by selecting listbox entries. The VBA code generates a SQL statement from these choices and then creates an ADBDB.Recordset object from this.
How can I display the recordset records in Access? None of the grid controls work in Access 2010 and the subform just isn't designed for this purpose. Can someone recommend another strategy?
You could save the SELECT statement as a named query, then open the query as a datasheet. It's not really a form, but somewhat form-like.
Call DatasheetFromSql(strSql)
Public Sub DatasheetFromSql(ByVal pSql As String)
Const cstrQuery As String = "qryDiscardMe"
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim strMsg As String
On Error GoTo ErrorHandler
Set db = CurrentDb
db.QueryDefs.Delete cstrQuery
Set qdf = db.CreateQueryDef(cstrQuery, pSql)
DoCmd.OpenQuery cstrQuery, , acReadOnly
ExitHere:
On Error GoTo 0
Set qdf = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 3265 ' Item not found in this collection. '
Resume Next
Case Else
strMsg = "Error " & Err.Number & " (" & Err.description _
& ") in procedure DatasheetFromSql"
MsgBox strMsg
GoTo ExitHere
End Select
End Sub
I opened the query read-only. If you want to allow users to edit the data returned by their custom queries, I would not recommend this approach. Instead I would invest the effort in the approach HK1 offered because it can support better control of the user data changes.
With the query opened as a datasheet, you can use Screen.ActiveDatasheet to inspect its properties. At least some of the methods are also available to you. For example you could resize/reposition the datasheet like this:
Screen.ActiveDatasheet.Move Left:=0, Top:=0, Width:=(4 * 1440), Height:=(3 * 1440)
The units are twips (1440 twips / inch), so that would make the width 4 in., height 3 in., and move it to the upper left corner of the Access window.
Here's what I think you'll have to do to get this kind of functionality.
You'll first need to create enough of the correct controls on a form to handle every possible scenario. You'll then need to set the form to be a datasheet form so that it appears as a grid.
Now set the controlsource on your controls to correspond with one of the fields in the recordset. On every control that is not in use needs to have it's ColumnHidden property set to true. You'll also have to change the caption of the associated label to show the appropriate column name for each control that will be visible.
Now, bind that form to your ADO recordset object.
Me.Recordset = rst
'or
Me.Subform1.Form.Recordset = rst
Is this a perfect solution? Most certainly not. Access doesn't have anything that compares to the DataGridView in .Net or even to the Grid controls that are used in VB6. In my opinion, you're really pushing the limits of Access to try to get this sort of functionality. It's like swimming upstream. You'll find that everything you do is going to be fairly difficult and some things just aren't going to be possible.
for an ADP Project where you can't have local MS Access query definitions, you can create a datasheet form with multiple textboxs named txt1, txt2,.... txt30 and labels name lbl1 ... lb30 and this code will set the form.recordsource and set the textbox.controlsource and the label.caption to the appropriate fields from an ADO recordset object. This form will allow you to view your ADO Recordset similar to the Docmd.OpenQuery method.
You must pass the ADO recordset's SQL statement to the form using the OpenArgs property of the form. the code below shows the VBA code to call\open the form (which shows the ADO Recordset like a query) and pass your sql string. The vba code on the form's load event will set all the control properties, resize the columns that have data and hide the columns that do not have a corresponding field from the ado recordset:
'stevekirchner 09/29/2012 Replace Access parameterized query with SQL Server in-line function
'DoCmd.OpenQuery "qry_SearchMaster_CaseTitles", , acReadOnly
strsql = "Select * from dbo.UDF__qry_SearchMaster_CaseTitles ('%" & Me.tbxSearchTerm.Value & "%') "
Call Display_ADO_Recordset_from_Datasheet_Form(strsql, "frm_Display_ADO_Recordset_Result1")
'create a non-form module and put the code for the sub Display_ADO_Recordset_from_Datasheet_Form
'and function fIsLoaded in it (this will allow you make several forms to view ADO recordset and
'call the code from one place\module):
Sub Display_ADO_Recordset_from_Datasheet_Form(sSQL As String, sFormName As String)
On Error GoTo Error_Handler
If fIsLoaded(sFormName) Then
DoCmd.Close acForm, sFormName
End If
DoCmd.OpenForm sFormName, acFormDS, , , acFormReadOnly, , OpenArgs:=sSQL
Exit_Sub:
Exit Sub
Error_Handler:
MsgBox Err.Description & " Error No: " & CStr(Err.Number)
Resume Exit_Sub
End Sub
Function fIsLoaded(ByVal strFormname As String) As Boolean
On Error GoTo Error_Handler
'Returns False if form is not open or True if Open
If SysCmd(acSysCmdGetObjectState, acForm, strFormname) <> 0 Then
If Forms(strFormname).CurrentView <> 0 Then
fIsLoaded = True
End If
End If
Exit_Function:
Exit Function
Error_Handler:
MsgBox Err.Description & " Error No: " & CStr(Err.Number)
fIsLoaded = False
Resume Exit_Function
End Function
'Create a datasheet view form (named frm_Display_ADO_Recordset_Result1) with 30 textboxes and 30
'30 labels named txt1 - txt30 and lbl1 - lbl30 and put this code in the form's module:
Option Compare Database
Private Sub Form_Load()
On Error GoTo Error_Handler
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim rsClone As ADODB.Recordset
Dim strsql As String
Set conn = CurrentProject.Connection
Set rs = New ADODB.Recordset
strsql = Me.OpenArgs
rs.Open strsql, conn, adOpenStatic, adLockOptimistic
Set rsClone = rs.Clone
Call Update_Form_Controls("your text goes here", strsql, rsClone)
Exit_Sub:
rs.Close
conn.Close
Set rs = Nothing
Set conn = Nothing
Exit Sub
Error_Handler:
MsgBox Err.Description & "; Error Number : " & Err.Number, vbOKOnly
Resume Exit_Sub
End Sub
Sub Update_Form_Controls(Header_Label As String, SQL As String, CloneRS As Recordset)
Dim rsCount As Integer
Dim i As Integer
On Error GoTo Error_Handler
Me.Form.Caption = Replace(SQL, "Select * From ", "Display: ")
rsCount = CloneRS.RecordCount
If rsCount <= 0 Then
MsgBox "The Query did not return any data to view", vbOKOnly
DoCmd.Close
Else
Me.Form.SetFocus
Me.RecordSource = SQL
i = 1
Do Until i = 31
Me("lbl" & i).Caption = ""
Me("txt" & i).ControlSource = ""
Me("txt" & i).ColumnHidden = True
i = i + 1
Loop
i = 1
With CloneRS
For Each Field In .Fields
On Error Resume Next
Me("lbl" & i).Caption = .Fields(i - 1).Name
Me("txt" & i).ControlSource = .Fields(i - 1).Name
Me("lbl" & i).Visible = True
Me("txt" & i).ColumnHidden = False
Me("txt" & i).SizeToFit
i = i + 1
'Debug.Print Field.Name
On Error GoTo 0
Next Field
End With
End If
Exit_Sub:
Me.Requery
Exit Sub
Error_Handler:
MsgBox Err.Description & "; Error Number : " & Err.Number, vbOKOnly
Resume Exit_Sub
End Sub
I don't use ADO but simply VBA, in which case above approach is wrong: one doesn't need any means for displaying an existing recordset in a form, but should on the contrary define an adequate recordset within the form !
Instead of creating MyDataBase.OpenRecordset ("SELECT … [SQL query] ;"), just set the form's RecordSource to the very same query definition:
Forms![MyDisplayForm].RecordSource = "SELECT … [SQL query] ;"
Forms![MyDisplayForm].Requery
For me this works perfectly (Windows 7 pro ×64 / MS Office pro ×64)