Get user input from optiongroup before proceeding - ms-access

I have a database that generates test questions in a random order. When I get the answer form (frmAnswers) to open, all I can do is have it scroll through all the questions using either the Enter or esc keys. I have a MsgBox that pops up just to let me know some of the variables are set properly, but the code will not pause to accept input from the OptionGroup in the form.
Here is what I assume is the relevant code:
Set rsCourse = CurrentDb.OpenRecordset(strCourse)
DoCmd.OpenForm ("frmAnswers")
rcdCnt = 1
While Not rsCourse.EOF
With rsCourse
Screen.ActiveForm.ctlQ_No = rcdCnt
Screen.ActiveForm.ctlQuestion = .Fields("Question")
Screen.ActiveForm.ctlAns_A = .Fields("Ans A")
Screen.ActiveForm.ctlAns_B = .Fields("Ans B")
Screen.ActiveForm.ctlAns_C = .Fields("Ans C")
Screen.ActiveForm.ctlAns_D = .Fields("Ans D")
Forms!frmAnswers!optAnswer.SetFocus
Select Case Forms.frmAnswers.optAnswer
Case Is = 1: strAns = "A"
Case Is = 2: strAns = "B"
Case Is = 3: strAns = "C"
Case Is = 4: strAns = "D"
Case Is = Null: srtAns = "Nothing"
End Select
If strAns = .Fields("Correct Answer") Then
Exit Sub
Else
MsgBox "The correct answer is " & .Fields("Correct Answer") _
& Chr(13) & Chr(10) & "You answered " & strAns
End If
End With
rcdCnt = rcdCnt + 1
If rcdCnt > 100 Then
Exit Sub
End If
rsCourse.MoveNext
Wend
I have searched many sites, to include Microsoft, pcreview, accessmvp, etc., and have yet to find anything that helps. I have tried;
Select Case
Case 1
Case 2
Etc.
End Select
as well as the code in my example. Nothing seems to pause the code except the MsgBox.
I have also tried putting this code as a Function:
Call TestClick(strCourse)
With the function:
Function TestClick(strCourse)
with the above code in the function. It returns a compile error: "Object required" at the Set rsCourse line.
I have also tried this as a subroutine with the same error.
For clairification, here is the code I have for the form that calls the frmAnswers Form:
DoCmd.OpenForm ("frmIntroduction_VBA")
If IsNull(Me.cboTrainee_Name) Then ' No Name
MsgBox "You must enter your name to continue!", vbOKOnly ' Tell user
Me.cboTrainee_Name.SetFocus ' Focus the control
Exit Sub ' Exit the method
End If ' End the IsNull test
Trainee_Name = Forms!frmIntroduction_VBA!cboTrainee_Name
If IsNull(Me.cboCourse) Then ' Check if a course is selected
If IsNull(Me.cboVol) Then
MsgBox "You must select either a Course or Volume Review to continue!" ' Tell user
Me.cboCourse.SetFocus
Exit Sub
End If
End If
If IsNull(Me.cboCourse) Then
strCourse = Me.cboVol.Value
Else
strCourse = Me.cboCourse.Value
End If
I would like this to actually call another Sub for the frmAnswers form, but do not know how to pass the rsCourse variable to the Sub.
I am sure this is a fairly easy issue to resolve, but I am no expert by any means. Once I get this problem solved, I will continue on and try to have VBA create a recordset with test results to be appended to an existing table.
Thank you all for any assistance you can provide.

This is just one of a million different ways of doing this. My feelings aren't hurt if other people chime in with other ways. But this solution may be most in-line with the road you're already headed down:
You need a way to pass your strCourse to the form.
-One way would be to declare a String variable strCourse in the frmAnswers class module and set it from the frmIntroduction_VBA after you open frmAnswers.
-Another way would be to create an invisible field on frmAsnwers called strCourse and set it after you open the form with form!frmAnswers!strCourse=strCourse.
-The easiest way I think for you would just be to refer to the frmIntroduction_VBA form from the frmAnswers form. That's what we'll do here.
First things first: Open frmAnswers.
DoCmd.OpenForm("frmAnswers")
Now let's move all the rest of your code into the frmAnswers form itself. Here's the frmAnswers class module:
Option Explicit
'The following will be variables that will persist as long as the form is open
dim rsCourse as Recordset
dim strCourse as String
dim rcdCnt as Long
dim strCorrectAnswer as String
Private Sub Form_Load() 'This basically initializes the variables and loads the first question
If IsNull(Forms!frmIntroduction_VBA!cboCourse) Then
strCourse = Forms!frmIntroduction_VBA!cboVol
Else
strCourse = Forms!frmIntroduction_VBA!cboCourse
End If
Set rsCourse = CurrentDb.OpenRecordset(strCourse)
rcdCnt = 0
LoadNextQuestion
End Sub
Private Sub LoadNextQuestion() 'reusable code to load questions
rcdCnt=rcdCnt+1
If (rcdCnt>100) OR rsCourse.EOF Then
rs.Close
DoCmd.Close acForm, "frmAnswers"
Exit Sub
End If
With rsCourse
ctlQ_No = rcdCnt
ctlQuestion = !Question
ctlAns_A = ![Ans A]
ctlAns_B = ![Ans B]
ctlAns_C = ![Ans C]
ctlAns_D = ![Ans D]
strCorrectAnswer = ![Correct Answer]
optAnswer = Null 'clears previous answer
optAnswer.SetFocus
.MoveNext
End With
End Sub
Private Sub btnSubmit_Click()
Dim strAnswer As String
strAnswer = "Nothing"
Select Case optAnswer
Case 1:
strAnswer = "A"
Case 2:
strAnswer = "B"
Case 3:
strAnswer = "C"
Case 4:
strAnswer = "D"
End Select
If strAns = strCorrectAnswer Then
MsgBox "Correct!"
Else
MsgBox "The correct answer is " & strCorrectAnswer & "." _
& Chr(13) & Chr(10) & "You answered " & strAns &"."
End If
LoadNextQuestion
End Sub
Start with that and play around with it. If you're not sure why I did something a certain or if I missed some fundamental aspect of what you're doing, leave it in a comment and we'll keep refining it.

Related

MS Access Choosing Filter with ComboBox

I have returned with yet another Question regarding MS Access and its VBA environment.
I'm currently constructing a database in MS Access 2016.
The main View headview has a combobox viewcombo and a subform listview.
What I need: I want the combobox to filter the listview depending on the chosen entry of it.
What I did:
Private Sub ViewCombo_AfterUpdate()
On Error GoTo Proc_Error
If IsNull(Me.ViewCombo) Then
Me.ListView.Form.Filter = ""
Me.ListView.Form.FilterOn = False
Else
Dim selectedOption As AccessObject
selectedOption = Me.ViewCombo
Select Case selectedOption
Case selectedOption = "open"
Me.ListView.Form.Filter = "Column1='" & "'"
End Select
End If
Proc_Exit:
Exit Sub
Proc_Error:
MsgBox "Error " & Err.Number & " Setting Filter:" & vbCrLf & Err.Description
Resume Proc_Exit
End Sub
Note: The Me.ListView.form.Filter = "Column1='" & "'" is supposed to be empty if the chosen entry of viewCombo is open, the available entries are Open, Closed, ovedue, cancel and "as seleced
However, it seems that Access doesnt work this way. How do I properly write the select case statements?
Edit 1:
The Values of the ComboBox ViewCombo are manualy written in it. Depending on the selection of a value, different Filters are to be set on the ListView
Example:
The selected value is open
The Listview is filtered with the statement: Column1 is empty
The selected value is closed
The Listview is filtered with the statement Column 1 is not empty, Column 2 contains the value 10 (10 is an ID for a status, these are given to me by the employees I work with, those are internal and have no meaning for the database)
Hope that helps to clarify the situation.
You will use the value of the combobox, not the combobox as an object, similar to:
If IsNull(Me.ViewCombo.Value) Then
Me.ListView.Form.Filter = ""
Me.ListView.Form.FilterOn = False
Else
Select Case Me.ViewCombo.Value
Case Is "open"
Me.ListView.Form.Filter = "[SomeFieldName] = 'open'" ' or other filter value.
End Select
Me.ListView.Form.FilterOn = True
End If
I solved it with the Input you guys gave me:
Private Sub AuswahlFilter_AfterUpdate()
On Error GoTo Proc_Error
If Me.ViewCombo.Value = "All" Then
Me.ListView.Form.Filter = ""
Me.ListView.Form.FilterOn = False
Else
Select Case Me.ViewCombo.Value
Case Is = "Open"
Me.ListView.Form.Filter = "FlagOpenClosed='1'"
Me.ListView.Form.FilterOn = True
End Select
End If
Proc_Exit:
Exit Sub
Proc_Error:
MsgBox "Error " & Err.Number & " when creating Filter:" & vbCrLf & Err.Description
Resume Proc_Exit
End Sub
I created some additional Columns on the ListView. The Table listviewis based on now has additional columns filled with values from statements like When(IsNull(Column1);1;0). Then I set the filter for those values.
I guess there is a better way to do it, however, I am a noob in VBA, so that is the best solution I came up with. If there is a better way to do it, please dont hesitate to write it as an answer here, I am glad to learn new things, and love to hear from you guys.
-Ninsa

Access Input Form with Custom Error Messages

The Solution
The solution was to not try and capture the errors but do the error handling myself as part of the Add New Record command button:
Private Sub buttonNewRecord_Click()
Dim ErrorInt As Integer
Dim TeleCheck As Variant
Name.SetFocus
If Name.Text = "" Then
MsgBox "Name is missing!"
ErrorInt = ErrorInt + 1
End If
TeleCheck = DLookup("[Telephone]", "tblColdCallLog", "[Telephone] = '" & Me.Telephone & "'")
If Not IsNull(TeleCheck) Then
MsgBox "Telephone number already exists in the table!"
ErrorInt = ErrorInt + 1
End If
If ErrorInt < 1 Then
DoCmd.GoToRecord , , acNewRec
MsgBox "Record Added!"
End If
End Sub
Original Post:
What I Have:
I have created a simple Access 2013 Form used to input data into a table. On the Form, the user enters data into the fields and clicks on a button made using the Command Button Wizard to Add New Record.
The form has one required field, [Name], and one field set to 'Index: Yes (No Duplicates)', [Telephone Number]. In the Form, this correctly produces error messages if the [Name] field is empty or there is a duplicate number detected in the [Telephone] field that is also in the table.
What I Am Trying To Do:
The error messages that appear are not user friendly. I would like to replace them with custom error messages and if there are no errors, maybe a message that says all went well.
What I Have Tried:
On the Form properties, Events tab, in 'On Error', [Event Procedure]:
Private Sub Error_Sub(DataErr As Integer, Response As Integer)
If DataErr = 3022 Then
MsgBox "Duplicate telephone number found in table!"
Response = acDataErrContinue
End If
If DataErr = 3314 Then
MsgBox "Name is missing!"
Response = acDataErrContinue
End If
End Sub
This works but only when you close the Form... When you click the 'Add New Record' Command Button, it simply shows the default error messages when appropriate.
Maybe I should use the Event 'Before Update'? I can't seem to use the same VBA script. I'm not allowed to define DataErr or Response. So, I'll use an Expression instead:
=IIf(Error(3022),MsgBox("Duplicate telephone number found in table"))
=IIf(Error(3314),MsgBox("Name is missing"))
This works... but when there is no error. Even if there is a name in the [Name] field, the error shows but at least it replaces the default error message.
Let's put it in the button itself? I'll have to use the Macro Builder to edit it. It's a bit hard to copy and paste this one so I'll simplify:
OnError GoTo Error_Handling
GoToRecord New
If [MacroError]<>0 Then
MsgBox = "[MacroError].[Description]"
End If
Error_Handling:
If Error(3022) Then
MsgBox = "Duplicate telephone number found in table!"
End If
If Error(3314) Then
MsgBox = "Name is missing!"
End If
This does the same as the 'Before Update' event; replaces the default error message but regardless of whether or not the error message should be triggered in the first place.
What am I doing wrong? I get the feeling it's something really simple. I've tried a variety of other combinations and endless Googling but I feel stumped.
Private Sub buttonNewRecord_Click()
Dim ErrorInt As Integer
Dim TeleCheck As Variant
Name.SetFocus
If Name.Text = "" Then
MsgBox "Name is missing!"
ErrorInt = ErrorInt + 1
End If
TeleCheck = DLookup("[Telephone]", "tblColdCallLog", "[Telephone] = '" & Me.Telephone & "'")
If Not IsNull(TeleCheck) Then
MsgBox "Telephone number already exists in the table!"
ErrorInt = ErrorInt + 1
End If
If ErrorInt < 1 Then
DoCmd.GoToRecord , , acNewRec
MsgBox "Record Added!"
End If
End Sub

Find next record based on certain criteria

I am trying to use the .FindNext (and .FindPrevious) function on an update form "next button" to find the record that meets certain criteria.
Private Sub NextRecord_Click()
Dim foundmatch As Boolean
For x = 0 To 3 Step 1
With Me.RecordsetClone
.FindNext "[Sensitivity] = " & [TempVars]![AccessLevel] + x
If .NoMatch Then
foundmatch = False
Else
Me.Bookmark = .Bookmark
foundmatch = True
Exit For
End If
End With
Next
If foundmatch = False Then
MsgBox "No More Records"
End If
End Sub
Upon a user entering the database the users accesslevel is assigned to a temp variable (1 to 4), and each project has a sensitivity rating of 1 to 4. The code below was used and worked for both next and previous only in finding records when the sensitivity and accesslevel were equal but not for sensitivities below the users access level which they are qualified to see.
Private Sub PrevRecord_Click()
Dim Stringy As String
Stringy = "[Sensitivity] = " & [txtaccess]
With Me.RecordsetClone
.FindPrevious Stringy
If .NoMatch Then
MsgBox "No More Records"
Else
Me.Bookmark = .Bookmark
End If
End With
End Sub
Note: The form is pulled from a query with Sensitivity one of the fields, and [txtaccess] is a text box on the field with the default value set at [TempVars]![AccessLevel]. I've also tried changing it to:
Stringy = "[Sensitivity] >= " & [txtaccess]
but that doesn't work either
I was able to fix the problem by setting applying a filter for sensitivity on the actual forms On_Load event rather than the command button. It now works using a next record command button added with the default code/settings!

Why do I get run-time error '2759' when saving the record? access 2010

Using Access 2010, I have a form for Purchase_Orders where the status changes depending on the whether the Items in the sub form have been delivered or not, and, it is influenced by the date as well.
Private Sub Form_AfterUpdate()
Dim rs As Recordset
Dim db As Database
Dim var_Delivered As String
var_Delivered = "SELECT Count(*) AS d_Count" & _
" FROM Items" & _
" WHERE PO_ID =" & Me.PO_ID.Value & _
" AND Supplier_Dnote_ID IS Null" & _
" AND Delivered_Without_Dnote =0;"
Set db = CurrentDb
Set rs = db.OpenRecordset(var_Delivered, dbOpenDynaset)
'MsgBox rs!d_Count
If rs!d_Count > 0 Then
If Me.Supply_date < Date Then
Me.Status = "Overdue"
Else
Me.Status = "Submitted"
End If
Else
Me.Status = "Delivered"
End If
db.Close
Set db = Nothing
Set rs = Nothing
End Sub
This runs after_update of the Purchase_Orders. I have a save_close button that uses the following code and doesn't return an error:
If Me.Dirty = True Then
DoCmd.Close acForm, "Purchase_Orders", acSaveYes
Else
DoCmd.Close acForm, "Purchase_Orders", acSaveNo
End If
However, I also have a Save button that doesn't close the form. This is where I get run-time error 2759 : The method you tried to invoke on an object failed. Debug Highlights the saverecord line.
Private Sub SaveOnlyBtn_Click()
If Me.Dirty = True Then
docmd.RunCommand acCmdSaveRecord
End If
End Sub
If I comment the status code out and use the save button, the record saves fine without any errors. Why do I get this error? I'm completely stumped and searching the error online hasn't helped me either.
So I found that the error did not occur when I put the code in the "on dirty" event, which then made me realise that I don't need necessarily have to run the code after the form updates, only when specific fields change. So I changed my code to a public code and called it when supply date, delivered_without_dnote, or supplier_Invoice_ID changed.
the public code is :
Public Sub delivered_status()
On Error GoTo errTrap1
If Forms!Purchase_Orders_Ex.Form!Status = "Cancelled" Then
Exit Sub
Else
DoCmd.RunCommand acCmdSaveRecord
Dim rs As Recordset
Dim db As Database
Dim var_Delivered As String
var_Delivered = "SELECT Count(*) AS d_Count" & _
" FROM Items" & _
" WHERE PO_ID =" & Forms!Purchase_Orders_Ex.Form!PO_ID.Value & _
" AND Supplier_Dnote_ID IS Null" & _
" AND Delivered_Without_Dnote =0;"
Set db = CurrentDb
Set rs = db.OpenRecordset(var_Delivered, dbOpenDynaset)
'MsgBox "Outstanding Items: " & rs!d_Count
If rs!d_Count > 0 Then
If Forms!Purchase_Orders_Ex.Form!Supply_date < Date Then
Forms!Purchase_Orders_Ex.Form!Status = "Overdue"
Else
Forms!Purchase_Orders_Ex.Form!Status = "Submitted"
End If
Else
Forms!Purchase_Orders_Ex.Form!Status = "Delivered"
End If
rs.Close
Set db = Nothing
Set rs = Nothing
End If
errTrap1:
Select Case Err.Number
Case 3314 'form not complete and other required fields are empty
Exit Sub
Case Else
If Err.Number > 0 Then
MsgBox Err.Number & ": " & Err.Description
End If
End Select
End Sub
Now, when I use either the save_close or Save_Only I do not get error 2759. I do not completely understand which part of my original method caused the error but it no longer occurs with this approach.
I've just encountered this issue and moving code out of Form_AfterUpdate fixed it for me too.
What's (vaguely) interesting is that the code in question worked fine locally, but did not work when deployed to the client. I tried importing just the amended form instead of replacing the whole access app, but I still got the same issue. I also copied the back-end database back from the server to my development machine, but still didn't get the issue locally. On top of that I did endless compact/repair and decompile/compile.
My conclusion at the end of all of that was that this was yet another weird issue emanating from the Access black-box, rather than an issue with the particular code.

Access VBA - All checkboxes on form have been checked

I am relatively new to Access VBA and have a form that has around 30 checkboxes on it. When saving the form I want to ensure that all checkboxes have been ticked (set to true). The tickboxes have all got names SC1, SC2....SCN Is there a way to loop through each control and see if it has been set to true?
This is what I have tried but it doesnt seem to read the tickbox -
Private Sub Validate_Data(rstTop)
Dim n As Integer
Dim count As Integer
count = 0
For n = 1 To rstTop
If Form.Controls("SC" & n).Value = False Then
count = count + 1
End If
Next
If count <> 0 Then
MsgBox "Not all Questions have been ticked, please tick and add comments", vbInformation, _
"More information Required"
Else
End If
End Sub
Give this a try, it worked for me.
Option Compare Database
Option Explicit
Private Function Validate_Data() As Boolean
Dim ctl As Control
Validate_Data = True 'initialize
For Each ctl In Me.Form.Controls
If ctl.ControlType = acCheckBox Then
If (ctl.Name Like "SC*") And (ctl.Value = False) Then
MsgBox "Not all Questions have been ticked, please tick and add comments", vbInformation, _
"More information Required"
Validate_Data = False 'something isnt checked
Exit Function
End If
End If
Next ctl
End Function
Private Sub cmdGo_Click()
Validate_Data
End Sub