Required Fields Before Update in Conjunction with Close Button - vba

Novie VBA programmer here, looking for the ABC's direction.
I have 3 fields that I need to require in a form before the form is close.
I had previously require the fields within the Table; However, when I create a new contact to add to this Form I need to Requery the results of the added contact. When I Requery and the required fields are Required from the Table I reach a stuck, since I need to add the new contact but cannot Requery until the fields are filled (and I cannot do that until I have the right contact).
I know this is in the wrong place but this is the code I have thus far attached to my "Close" button.
Private Sub SaveCloseBtn_Click()
If Nz([PlaintiffName], "") = "" Then
MsgBox "Plaintiff Name is required.", vbExclamation, "Required Field"
Cancel = True
End If
If Nz([LawFirm], "") = "" Then
MsgBox "Law Firm is required.", vbExclamation, "Required Field"
Cancel = True
Me.[LawFirm].SetFocus
End If
If [PlaintiffName] = True Then
If [LawFirm] = True Then
If MsgBox("You are about to exit this case. Are you sure?", vbYesNo, "Warning!") = vbYes Then
DoCmd.Close
Else
DoCmd.CancelEvent
End If
End Sub
I tried creating Required fields in "BeforeUpdate" but for whatever reason, it does not work in conjunction with the docmd.close form function.

Related

Dealing with edited fields left in blank on subform

I am having a problem when an user decides to "clear/delete" a line entered on the form during the first update.
I have a form with a subform to give the user the possibility of multiple entries, however, after the user has first edited any field on the subform the respective record gets dirty and recorded, so if the user decides to not use anymore that record and deletes all the info for that line, that line which now is all blank still being recorded, and this is giving me blank lines in my data (The TransactionID and ID are not shown to the user on the form, I added it for the sake of this post).
This can also accidentally happen if on the "new" line, which is not dirty, the user hits any key by mistake, and even deleting it straight away, the record gets dirty for good, so it ends being recorded completely in blank.
I couldn't find a way to avoid recording this blank lines.
I would like to know if it is possible to have buttons to "add a new line" and "delete a line", just like, on the last line it would have a "+" to add new line (so the "new not dirty" line wouldn't appear automatically), and on the precedent lines would have a "-" to remove that specific record (this is just an idea, it can be in any kind of way).
Is that achievable? If it is not, is there a way to simply avoid blank lines to be saved? Like, saving jumping those blank lines, just like in a loop?
More information added for the sake of better explanation.
I didn't include the code before as there is no code behind this, this is just access natural recording set. I am not using DAO Record Set nor SQL to "save" the records (just to delete from table in a discard event), I am using normal bounded controls.
The modifications I did were on Parent form to always stay on the Current Record (Cycle) and On Load event it always goes to new record. Thus, the buttons Save and Cancel, are used to confirm or discard the new record created on the Parent form, because, as I have previously said, the subform is used to enter multiple records under the same record on the Parent Table, in other words, Relationship One-To-Many, therefore the button "Close" holds a simple code for deleting the last entry on the Parent Table (as it still on the current record) and as the tables have "Delete Cascade Relationship" all the information entered into the subform/Child Table get automatically deleted, so I just had to handle the data inserted into the Parent Table, whereas, the save button is used to get the confirmation of saving from the user, and make sure that the user will fill all the fields prior to save.
That is pretty much the code on this form, which is below.
But before the code, I would like to reinforce that, I have made use of the "BeforeUpdate" event, which works fine, it makes the user to add all the fields before opening a new record on the subform, but let's suppose that the user enters 10 records on the subform, then the user decides to "Delete" one of the records (which in this case is not the last one, so he cannot just press "ESC" and I cannot just run "Me.Undo"), so if the user clears the fields (just like in the images I have provided, as I don't know how to delete a record in this scenario yet), the before update event gets triggered and doesn't allow the user to do anything while he/she fills in the blank fields, not even to click in "Cancel". Therefore, in my "Save" button I check all the fields and if one of them is "dirty" them the user must fill all the subsequent fields, however, if all the fields are "empty", the user is still able to save.
In the beginning I thought that those "blank lines" wouldn't happen so often and I would have to clean them sporadically, but it is unbelievable, the amount of blank lines that have been created by the users. I have to clean them almost every week.
I really would like a way to create "+ add line" and "- delete line" buttons, because if the user wants to delete a line he just click on "-" button, the same for add new line.
Again, I appreciate the help. I am really struggling on this. Thanks all.
Private Sub btnSave_Click()
If IsNull(Me.TransactionDate) _
And IsNull(Me.SupplierPayee) _
And IsNull(Me.TotalReceipt) Then
MsgBox "Form in blank!", vbInformation + vbOKOnly, "Saving..."
Exit Sub
End If
If IsNull(Me.TransactionDate) _
Or IsNull(Me.SupplierPayee) _
Or IsNull(Me.TotalReceipt) Then
MsgBox "Please fill in all the fields", vbCritical + vbOKOnly, "Transaction not Saved"
Exit Sub
End If
Me![subfrmPCHeaderDetail].SetFocus
DoCmd.GoToRecord , , acFirst
If IsNull(Me.TransactionDate) _
Or IsNull(Me.SupplierPayee) _
Or IsNull(Me.TotalReceipt) _
Or IsNull(Form_frmPCHeaderDetail.Item) _
Or IsNull(Form_frmPCHeaderDetail.ItemAmount) _
Or IsNull(Form_frmPCHeaderDetail.VATRate) _
Or IsNull(Form_frmPCHeaderDetail.DescriptionPurpose) Then
MsgBox "Please fill in all the fields", vbCritical + vbOKOnly, "Transaction not Saved"
Exit Sub
ElseIf Form_frmPCHeaderDetail.ItemAmount = "0" Then
MsgBox "Amount cannot be €0.00", vbCritical + vbOKOnly, "Transaction not Saved"
Form_frmPCHeaderDetail.ItemAmount.SetFocus
Exit Sub
End If
If Not Me.TotalReceipt.Value = Form_frmPCHeaderDetail.GrossTotal _
Or IsNull(Me.TotalReceipt) Then
MsgBox "Please check the Receipt Amount Details as ""Gross Total"" and ""Receipt Total"" are not matching"
Exit Sub
End If
If Me.ReceiptScanned.AttachmentCount = 0 Then
MsgBox "Please scan the receipt and add it to this transaction", vbInformation + vbOKOnly, "Add the Receipt"
Me.AddReceiptScanned.SetFocus
Exit Sub
End If
If Me.TransactionDate > Date Then
MsgBox "Future Transaction Date not allowed", vbCritical + vbOKOnly, "Transaction not Saved"
Me.TransactionDate.SetFocus
Exit Sub
Else
Dim Result As Long
Result = MsgBox("Saving Transaction!" & vbNewLine & vbNewLine & _
"Attention!" & vbNewLine & vbNewLine & _
"You will not be able to delete nor modify any detail of this transaction!" & vbNewLine & vbNewLine & _
"Are you sure you would like to save this transaction?" & vbNewLine & vbNewLine & _
"Click ""YES"" to save, or click ""NO"" to return.", vbExclamation + vbYesNo, "Save Transaction?")
If Result = 6 Then
DoCmd.Save
DoCmd.Requery
Form_frmPCHeader.TransactionDate.SetFocus
DoCmd.GoToRecord , , acNewRec
MsgBox "Transaction added successfully to the Petty Cash Register", _
vbInformation + vbOKOnly, "Petty Cash transaction added"
End If
End If
End Sub
Private Sub btnClose_Click()
Dim LastID As Long
Dim Result As Long
If IsNull(TransactionID) Then
DoCmd.Close
Exit Sub
End If
LastID = TransactionID
MsgBox("Closing without saving!" & vbNewLine & vbNewLine & _
"If you want to discard the entries, click ""YES"", or click ""NO"" to return.", vbCritical + vbYesNo, "Discard Entries?")
If Result = 6 Then
Application.Echo False
Me.Painting = False
DoCmd.SetWarnings False
Me.TransactionDate = "31/12/2099"
Me.SupplierPayee = "Discarded"
Me.TotalReceipt = 0
DoCmd.Save
DoCmd.Requery
DoCmd.RunSQL "DELETE * FROM tblPCHeader WHERE TransactionID = " & LastID & ""
DoCmd.Close
Application.Echo True
DoCmd.SetWarnings True
End If
End Sub
Private Sub Form_Load()
DoCmd.GoToRecord , , acNewRec
End Sub
For a Delete (-) button, consider code:
DoCmd.SetWarnings False
DoCmd.RunCommand acCmdDeleteRecord
DoCmd.SetWarnings True
For Add (+) button, just move to new record row with code you already know.
Docmd.GoToRecord , , acNewRec

MS Access '16 - Query not pulling a value from a field

[Disclaimer: I'm self-taught and a total novice!]
I have a FORM with which a QUERY pulls data and uses it to populate a REPORT. As the end user finishes the report and clicks a button, the following is supposed to happen:
1) The FORM saves all the data in a new record on the TABLE 2) A query pulls that record by the ID (which is autonumbered) from the FORM 3) The QUERY populates a REPORT with the data from the TABLE 4) The FORM and QUERY close - no need to save.
The QUERY pulls all the data from the corresponding TABLE with the following criteria: [Forms]![Data_Input_Form]![ID]
However, my REPORT comes up blank! Eek!
I have a similar QUERY that pulls data from the same TABLE and populates it to a similar REPORT with the following criteria: Like Nz([Forms]![Home_Form]![Incident_ID_Lookup_text],"*")
Unsurprisingly, when I added this to the QUERY that wasn't working how I wanted it to, it reported ALL the previous records.
'------------------------------------------------------------
' Add Report [and Open Report] Button Click
'
'
'------------------------------------------------------------
Private Sub Add_Rpt_Btn_Click()
If MsgBox("Are you sure? No backsies.", vbYesNo, "Add Report?") = vbNo Then
Exit Sub
End If
'Check for Necessary Fields and Add New Record
If (IsNull(Me.Person_Filing) Or IsNull(Me.Nature_Lst) Or IsNull(Me.Location_Cmb) Or IsNull(Me.Summary) Or IsNull(Me.Narrative)) = True Then
MsgBox "Looks like you left some important information out. Please fill out all fields with an asterisk.", vbOKOnly, Whoops
Exit Sub
Else
DoCmd.GoToRecord , , acNewRec
End If
'Run Query to Open Report
DoCmd.OpenQuery "Form_to_Report_Qry"
DoCmd.OpenReport "Incident_Report_1", acViewReport, , [ID] = [Forms]![Data_Input_Form]![ID]
'Close Query without Saving
DoCmd.Close acQuery, "Form_to_Report_Qry", acSaveNo
'Close Form without Saving
DoCmd.Close acForm, "Data_Input_Form", acSaveNo
End Sub
The REPORT needs to populate with the most recent record, but it keeps coming up blank.
That's because you move a new (empty) record - having no ID.
I guess, all you need is to use the current ID of the form - and use the correct syntax for the filter:
Private Sub Add_Rpt_Btn_Click()
If MsgBox("Are you sure? No backsies.", vbYesNo, "Add Report?") = vbNo Then
Exit Sub
End If
' Check for Necessary Fields and Add New Record
If (IsNull(Me.Person_Filing) Or IsNull(Me.Nature_Lst) Or IsNull(Me.Location_Cmb) Or IsNull(Me.Summary) Or IsNull(Me.Narrative)) = True Then
MsgBox "Looks like you left some important information out. Please fill out all fields with an asterisk.", vbOKOnly, Whoops
Exit Sub
End If
' If not saved, save the current record.
If Me.Dirty = True Then
Me.Dirty = False
End If
DoCmd.OpenReport "Incident_Report_1", acViewReport, , "[ID] = " & Me![ID].Value & ""
' Close Form without Saving
DoCmd.Close acForm, Me.Name, acSaveNo
End Sub

Command Button in msgbox vba possible?

si it possible to add a command button in the msgbox window in vba?
For example, i want to add a cancel button that stops the code rather than continuing it. I could create a new userform, but it would be nice if i save some space and use the msgbox that is already here.
VBA has several different types of MessageBoxes with built in command buttons for this very purpose. The type of buttons included in the message box is declared as the second parameter - MsgBox(Prompt, Buttons as)
The types you are probably interested in are:
vbYesNo
vbYesNoCancel
vbAbortRetryIgnore
vbOkCancel
vbRetryCancel
These Buttons return integer values that need to either be stored or used for comparison.
VBA has these integer answers stored as constants (e.g. vbOK = 1, VbCancel = 2, etc.) See Microsoft Developer Network MsgBox Function for more details on that.
Sub mySub()
Dim answer as Integer
answer = MsgBox("Would you like to choose yes?", vbYesNoCancel)
If answer = vbYes Then
'Do whatever you want
ElseIf answer = vbNo Then
'Do whatever
Else
Exit Sub
End If
End Sub
Try this:
If MsgBox("Cancel or Continue, are you sure?", vbOKCancel) = vbOK Then
'continue whatever you want to do.
End if

Message Box on Record Change

I have a form that queries records that the user may want to edit. I want the user to only be able to save the record if they've clicked the 'Save' button. Hitting the 'Close' button will prompt the user if they haven't saved yet, and may ask if they want to save.
I'm encountering a problem when the user changes through the records: I want to have a Y/N message box prompt the user for saving the changes they made to the previous record, otherwise their changes will be discarded. I have the following code set up:
Private Sub CmdCloseForm_Click()
If Me.Dirty Then
'checks that needed fields are completed
If IsFormValidated = False Then
If MsgBox("Required fields aren't filled." & vbCrLf & "Would you like to close this form without saving?", vbYesNo + vbQuestion + vbDefaultButton2, "Warning") = vbNo Then
Exit Sub
End If
Else
'checks if form has been saved already
If mSaved = False Then
Select Case MsgBox("Form hasn't been saved. Do you want to save and close?" & vbCrLf & "If you click 'No' the form will close without saving.", vbQuestion + vbYesNoCancel, "Save As")
'selecting yes will save and close form
Case vbYes:
mSaved = True
'selecting no will close the form w/o saving
Case vbNo:
mSaved = False
'selecting cancel will cancel out of the prompt
Case vbCancel:
Exit Sub
End Select
ElseIf mSaved = True Then
'if form has been previously saved, will finally close the form
If MsgBox("Would you like to close this form?", vbYesNo + vbQuestion + vbDefaultButton2, "Close Form") = vbNo Then
Exit Sub
End If
End If
End If
End If
DoCmd.Close acForm, Me.Name, acSaveNo
End Sub
'won't save automatically unless mSaved is true
Private Sub Form_BeforeUpdate(Cancel As Integer)
'if mSaved = False then the record won't save
If mSaved = False Then
Cancel = True
Me.Undo
Cancel = False
End If
End Sub
I pretty much want the 'CmdCloseForm' Message Boxes to run when the user moves on to the next record. Is there any way to do this?
If you really want to ask user about saving changes for each row, ask in Form_BeforeUpdate and in Form_BeforeDelConfirm. Those events will be fired each time when user changes edited record, or when subform with edited records loses focus, or user closes form with data. But this is not good solution because messageboxes will be too annoying. The better way is to copy edited data to temporary table, allow user edit the data and copy back to source table changed data when user clicks "Save". It's quite simple if you don't need multi-user data editing, in this case you will need some additional code for avoiding collisions.

Read-Only and undo properties MS Access (VBA)

I have been surfing the wed looking for an answer to what I thought it was a pretty simple question, for a newbie like me.. But havent found any so here I am!. To keep things simple, i'll attach the two bits of my code that are giving me a bit of a headache. What I intend to do is to switch from a Read-Only mode to a Write Allowed state by clicking a button. In order to do so, I want the routine to check for changes on the record and, if there are any ask the user to decide whether to save the changes or discard them.. While testing this particular button, I found out something quite "funny".. It seems to work well when no changes are introduced. Switches perfectly from read-only to write-allow states. However, when in write-allow and changes have been made, if the "Save option" has been selected/clicked then it does not lock the content although all the other subroutines and changes are implemented.
My other problem, closely related to this, is that I cant find a way to set a "saving point" for the undo option. I would like to find a way to "save a record" so when the undo button is pressed doesnt undo all the changes that the record has suffered since the database has been firstly opened (as its currently happening), but since the button has been pressed. I tried the DoCmd Save function but is not behaving as I was expecting (Note: the last 'else' has been my last try to this problem but, again, its not working as expected)
Many thanks for all your future collaboration,
Alex
Private Sub Command28_Click()
If Form_AODNewRecord.AllowAdditions = True Then
Call isModified_Save
Form_AODNewRecord.AllowAdditions = False
Form_AODNewRecord.AllowEdits = False
Form_AODNewRecord.AllowDeletions = False
MsgBox "Read Only. Addition, Edits and Deletions are now locked"
Command28.Caption = "LOCKED"
Else
Form_AODNewRecord.AllowAdditions = True
Form_AODNewRecord.AllowEdits = True
Form_AODNewRecord.AllowDeletions = True
MsgBox "New records, edits and deletions are now allowed"
Command28.Caption = "Lock mode OFF"
End If
MsgBox Form_AODNewRecord.AllowAdditions
End Sub
Sub isModified_Save()
If Form_AODNewRecord.Dirty Then
Dim strMsg As String, strTitle As String
strMsg = "You have edited this record. Do you want to save the changes?"
strTitle = "Save Record?"
If MsgBox(strMsg, vbQuestion + vbYesNo, strTitle) = vbNo Then
Me.Undo
Else
DoCmd.OpenTable "AOD Type", acViewPreview, acReadOnly
DoCmd.Save acTable, "AOD Type"
DoCmd.Close acTable, "AOD Type", acSaveYes
End If
End If
End Sub
I think you want the following code. You cannot open a table that the form is bound to and affect the form, when you open the table, you have two different instances and they do not affect one another.
An odd side effect of running a macro in Office applications is that it clears the Undo list, so I created a small macro that just shows a message "Undo cleared" and that is exactly what it does!
As an aside, rename your control with meaningful names, such as cmdLock, rather than Command28, you will thank yourself later.
Private Sub Command28_Click()
If Me.AllowAdditions = True Then
Call isModified_Save
Me.AllowAdditions = False
Me.AllowEdits = False
Me.AllowDeletions = False
MsgBox "Read Only. Addition, Edits and Deletions are now locked"
Command28.Caption = "LOCKED"
Else
Me.AllowAdditions = True
Me.AllowEdits = True
Me.AllowDeletions = True
MsgBox "New records, edits and deletions are now allowed"
Command28.Caption = "Lock mode OFF"
End If
''MsgBox Me.AllowAdditions
End Sub
Sub isModified_Save()
If Me.Dirty Then
Dim strMsg As String, strTitle As String
strMsg = "You have edited this record. Do you want to save the changes?"
strTitle = "Save Record?"
If MsgBox(strMsg, vbQuestion + vbYesNo, strTitle) = vbNo Then
Me.Undo
Else
''Save record
Me.Dirty = False
''Clear undo list
DoCmd.RunMacro "ClearUndo"
End If
End If
End Sub