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

[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

Related

VBA - MS Access 2016 - saving a CSV from a form and adding a value from the form to the file name

I am working with a form in Ms Access 2016, and using VBA, I need to add to the VBA, to export a csv file with the forms values, and also add a few more columns into the CSV from the table the form is derived from, (all from the same table) there is only one table associated with the form, “tblOnlineJobTable”, and when the button named “cmdAction” is clicked on the form it generates a unique despatch group code, and adds it to the “tblOnlineJobTable”, I need to add the depatchgroup code value, the field is named “txtDespatchGroupBatchNumber” to the exported csv file name.
I have heard that is would be simpler to convert the form to a report first, before saving as a CSV, which all needs to be achieved when clicking “cmdAction”.
I have not shown what I have tried as none of it has worked and will probably just confuse matters.
I am struggling changing the VBA to achieve the above, the currect VBA in place is:
Private Sub cmdAction_Click()
If Me.Dirty Then Me.Dirty = False
If Valid Then
If Nz(Me.txtDespatchGroupBatchNumber, "") <> "" Then
If vbNo = MsgBox("Warning - You have already sent this - this will create a new DGN number, " & _
" Do you wish to continue?", vbQuestion + vbYesNo, "Warning") Then
Exit Sub
End If
End If
' 01Aug17 - add the nz to get started
' 07aug17 - change the DGN to a text field
' Me.txtDespatchGroupBatchNumber = Nz(DMax("DespatchGroupBatchNumber", "tblOnlineJobTable"), 0) + 1
Me.txtDespatchGroupBatchNumber = "W" & Nz(DMax("DGNnumber", "qryfrmDespatchEntry_maxDGN"), 0) + 1
DoCmd.SetWarnings False
DoCmd.OpenQuery "qry_wtbl_DespatchEntry_update"
' 01Aug17
DoCmd.OpenQuery "qry_wtbl_DespatchEntry_update_wtbl"
DoCmd.SetWarnings True
MsgBox "Jobs have been Updated", vbInformation, "Information"
' 01aug17 - always enabled
' Me.cmdPrintDelivery.Enabled = True
Me.cmdPrintDelivery.SetFocus
Me.cmdAction.Enabled = False
''' DoCmd.Close acForm, Me.Name, acSaveNo
End If
End Sub

Subform blocking Recordset.AddNew (Error 3027)

Having a subform displaying the same table used in recordset makes the table read only (error 3027). Getting rid of the subform fixes the problem. Similar setup works in my other form interface.
I tried to delete the subform, which fix the accessibility problem. But that would defeat the original UX purpose.
Option Explicit
Public UnitRS As DAO.Recordset
Public ModelRS As DAO.Recordset
Public NameUnitRecords As String
Public NameModelRecords As String
Public Sub Form_Load()
'Initialization
NameUnitRecords = "tblBatteriesMainRecordsUnits"
NameModelRecords = "tblBatteriesRecordsModels"
End Sub
Private Sub SetUnitRecordsets()
'Set the path to the Battery Records table
Set UnitRS = CurrentDb.OpenRecordset(NameUnitRecords, dbOpenDynaset)
End Sub
Private Sub txtBatteryID_AfterUpdate()
'Set the recordset path for unit records
Call SetUnitRecordsets
'do a findfirst search for the Battery ID, using value from textbox txtBatteryID
UnitRS.FindFirst "[Battery ID]=" & txtBatteryID
'If no matching record, leave the other fields empty
If UnitRS.NoMatch Then
'If there is a matching record, then, grab the model number
Else
'as there is an existing record with model number, run a search on the model number and grab the model info
End If
'close recordset
UnitRS.Close
'check if the button can be enabled
End Sub
Private Sub cmbModelNumber_AfterUpdate()
'Set the recordset path for model records
'do a findfirst search for the Model Number, using value from combobox cmbModelNumber
'If no matching record, leave the other fields empty
If ModelRS.NoMatch Then
'If there is a matching record, then, grab the Model Info
Else
End If
'close recordset
'check if the button can be enabled
End Sub
Private Sub btnSaveAndCLear_Click()
Dim Response, strOldModelNumber
'Set the recordset path for unit records
Call SetUnitRecordsets
'Set the recordset path for model records
'close all related tables, queries and forms
DoCmd.Close acTable, NameUnitRecords, acSaveYes
DoCmd.Close acForm, "frmSubBatteriesMainRecordsUnits", acSaveYes
'If a new model record is required
ModelRS.FindFirst "[Model Number]='" & cmbModelNumber & "'"
If ModelRS.NoMatch Then
'msg box confirm model information
'If user chooses yes
If Response = vbYes Then
'create new model record
'this block could be done with "With...End" format for less error vulerability?
'nah, unless it is repetitively called, it's too much work to inplement just the .addnew part
'requery the two combobox to reflect newest changes
'User chooses no
Else
'popup a message telling the user the battery and model record is not logged, but don't clear the field.
Exit Sub
End If
End If
'need to find the record first, otherwise it will edit the first one
UnitRS.FindFirst "[Battery ID]=" & txtBatteryID
'store the old model number value
strOldModelNumber = UnitRS("Model Number")
'New record
If UnitRS.NoMatch Then
'create a new battery record
UnitRS.AddNew
UnitRS("Battery ID") = Me.txtBatteryID
'If this is an edit on existing record
Else
'if the new value is the same as the old one
If strOldModelNumber = cmbModelNumber Then
'msgbox the same value, no change is done to the database
MsgBox "the data is the same as the old record, no change is made to the record", vbInformation, "Same data"
Exit Sub
Else
'msg box confirm edit
Response = MsgBox("Please confirm edit on existing record: " & Chr(13) & Chr(10) & "BatteryID: " & txtBatteryID & Chr(13) & Chr(10) & "Model Number: " & cmbModelNumber, vbYesNo, "New Model Record Dectected")
'If user chooses yes
If Response = vbYes Then
'goto edit mode
UnitRS.Edit
'if user chooses no
Else
'msgbox notify the user nothing is changed in the database
MsgBox "Battery and Model record not logged, you may retry logging", vbInformation, "Record not logged"
Exit Sub
End If
End If
End If
'both changes the model number and comment field anyway
UnitRS("Model Number") = Me.cmbModelNumber
UnitRS("Comment") = Me.txtComment
'commit update
UnitRS.Update
UnitRS.Close
'clear all flieds
'reset all locks
'requery the sub form to reflect the newest changes
Me.subFrmBatteryRecords.Requery
End Sub
What I would like to achieve is to have a display in the form interface to show the content of the actual record table, so that the user knows what is in the table.
There is nothing wrong with my code. There is a property option in the form object, it's called "record lock", somehow mine had "All Records" selected. By making it "No locks", the accessibility problem is gone.

Executing Append Query not doing anything

Executing Append Query not doing anything
I'm having an odd problem that just reared its ugly head for some reason. I have a form that is used to add/edit/delete records in tblWorkOrder. When the record is saved, a check is made to see if the companion record in tblServiceRecord exists, and if not (like if it were the first time the record in tblWorkOrder is being saved/input) it will execute a query (qryCreateSR).
Several weeks ago it worked just fine. I had no problems with it, but then I updated tblServiceRecord to add several new columns and now it's not working at all. However, the SQL for the query doesn't delineate any of these new columns, let alone any specific information from tblWorkOrder. So I'm not entirely sure how this bug came up.
Here is the SQL:
INSERT INTO tblServiceRecord ( WorkOrderID )
SELECT Forms![frmWorkOrders].Form![txtID];
And here is the code behind the command button:
Private Sub cmdSave_Click()
If DCount("*", "[tblServiceRecord]", "[WorkOrderID] = " & [Forms]![frmWorkOrders].[Form]![txtID]) > 0 Then
Else
DoCmd.SetWarnings False
DoCmd.OpenQuery "qryCreateSR"
End If
DoCmd.RunCommand acCmdSaveRecord
DoCmd.GoToRecord , "", acNewRec
Me.lstWorkOrders.Requery
Me.lstWorkOrders.Value = ""
Me.txtComments.Value = ""
cmdSave_Click_Exit:
Exit Sub
cmdSave_Click_Err:
MsgBox Error$
Resume cmdSave_Click_Exit
End Sub
After removing the warnings suppression I get a key violation issue.
No clue what is causing the key violations. I checked my tables, and the two tables in question are tblWorkOrder and tblServiceRecord. Both have no records in them, I compacted the database, the linked fields (in tblServiceRecord, there is a reference to tblWorkOrder with the field WorkOrderID) are set to the same data type (number), and the child-tables are set to Indexed (No).
Just in case anyone wants to look at the database itself, here is a link:
https://drive.google.com/open?id=1_T-G9fyYQYjH3-YBe4PXhbBDTKNmY3ce
Try saving the current record in the form (by setting Me.Dirty = False), before inserting the record to the other table. Since you try to insert into a child table with a relation to a parent table, you must have a corresponding (saved) record in the parent table. When you create a new entry in the form, it first doesn't exist in the table until it is saved for the first time.
Private Sub cmdSave_Click()
Me.Dirty = False ' Or DoCmd.RunCommand acCmdSaveRecord <==== Save here
If DCount("*", "[tblServiceRecord]", "[WorkOrderID] = " & [Forms]![frmWorkOrders].[Form]![txtID]) = 0 Then
DoCmd.SetWarnings False
DoCmd.OpenQuery "qryCreateSR"
End If
'Removed: DoCmd.RunCommand acCmdSaveRecord <==== instead of here
DoCmd.GoToRecord , "", acNewRec
Me.lstWorkOrders.Requery
Me.lstWorkOrders.Value = ""
Me.txtComments.Value = ""
cmdSave_Click_Exit:
DoCmd.SetWarnings True
Exit Sub
cmdSave_Click_Err: // This code will never run, since a "On Error Goto cmdSave_Click_Err" is missing
MsgBox Error$
Resume cmdSave_Click_Exit
End Sub

Me.Dirty moves currently selected record

I have an Access 2007 form that's giving me some headache.
I have a list of records that start as a combo box to pick a company and then a series of checkboxes to indicate the company's role.
If the user needs to add a new company, they'd pick the company name from the combo box, and then click the checkbox that indicates what role the company is playing. When the checkbox is checked, the form follows the following code to show a popup that captures additional information:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
'DoCmd.RunCommand acCmdSaveRecord'
If Me.Dirty Then Me.Dirty = False
If chkOperationsAndMaintenance.Value = True Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
Me.Requery
End If
End Sub
This code will save the record on the CompanyProject table to create the row. It then pulls the CompanyProjectID (PK of the CompanyProject table) so it knows which ID to feed the popup.
The issue I'm having is that on the Me.Dirty line (and also the above commented-out acCmdSaveRecord), the entire form saves and refreshes, moving the selected row to the first record (in this case, "Gamesa") rather than the newly entered record. So the ensuing popup is fed the CompanyProjectID of the first record rather than the newly-entered record, and it also reads the "checked" state of the checkbox from the first record rather than the one upon which the user is working.
I doctored the code to look like this:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
Dim CPID As Long
Dim CID As Long
Dim rs As Recordset
Set rs = Me.RecordsetClone
CID = Me.CompanyID
'DoCmd.RunCommand acCmdSaveRecord'
If Me.Dirty Then Me.Dirty = False
CPID = DLookup("MAX(CompanyProjectID)", "CompanyProject", "cpProjectID = " & Me.cpProjectID & _
" AND CompanyID = " & CID)
rs.Find "[CompanyProjectID] = " & CPID
Me.Bookmark = rs.Bookmark
If chkOperationsAndMaintenance.Value = True Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
Me.Requery
End If
End Sub
The idea with these alterations is that we'll get the FK from the parent form ("cpProjectID") and the CompanyID of the selection from the combobox, then save the record. Once the record is saved, we have the CompanyProjectID already stored, so then the rs.Find and Me.Bookmark lines will then select the record that matches that CompanyProjectID.
This sometimes works, and sometimes doesn't. Generally doesn't. In this case, I refreshed the parent form and the current form and attempted to add a new company and then click the "Owner" checkbox (which uses the same code as above, just a different checkbox ID) to see the Bookmark on the wrong row:
At this point, I'm not sure what to do. If I don't save the record (via acCmdSaveRecord or Me.Dirty=False) then I don't have a CompanyProjectID to send as the input parameter for the ensuing popup, but if I do save the record, then the form changes the record and the wrong parameter is sent and the wrong checkbox's checked state is read. I can't just use an arbitrary index to work off of (such as acNewRec), as the user might need to edit an existing row instead of adding a new one.
I tried the method in this post already: MS Access how to Update current row, move to next record, not first, but the find/bookmark isn't consistently working.
EDIT (12/15/2014)
I ended up going with the following VBA code:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
Dim CPID As Long
Dim CID As Long
Dim rs As Recordset
Set rs = Me.RecordsetClone
CID = Me.CompanyID
If Me.Dirty Then Me.Dirty = False
CPID = DLookup("MAX(CompanyProjectID)", "CompanyProject", "cpProjectID = " & Me.cpProjectID & _
" AND CompanyID = " & CID)
Do While Me.CompanyProjectID <> CPID
If Me.CurrentRecord < Me.Recordset.RecordCount Then
DoCmd.GoToRecord , , acNext
Else
DoCmd.GoToRecord , , acFirst
End If
Loop
If chkOperationsAndMaintenance.Value = True Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
Me.Requery
End If
End Sub
I feel like there has to be a better answer for this, but this is appearing to work right now. I have my end user/lab rat testing it at the moment, so I'll mark this complete if this pans out. I still think there has to be a better solution for this, but at the moment, this solution is able to capture the requisite ID to pass to the popup, and it selects the appropriate row after this ID is captured.
Have you considered saving the current position - like Me.CurrentRecord, then after the save reposition to the desired record. As an example, you could add a 'Before' or 'After' Insert to save the position, then later reposition. See the following:
Option Compare Database
Option Explicit
Dim lCurRec As Long
Private Sub Form_AfterInsert()
lCurRec = Me.CurrentRecord
Debug.Print "After Insert, Current: " & Me.CurrentRecord
End Sub
<<< YOUR SUB>>>
DoCmd.GoToRecord acDataForm, Me.Name, acGoTo, lCurRec
This code will work when adding a new record as well as when editing an existing record:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
Dim c As Long
Me.Dirty = False
If chkOperationsAndMaintenance Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
c = Me.CurrentRecord
Me.Requery
DoCmd.GoToRecord , , acGoTo, c
End If
End Sub
I am guessing that your popup form does things that are specific to Operations & Maintenance, and does not change the values of any of the checkboxes on the main form. If this is the case, you don't need a Requery at all, and the code can be simplified:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
Me.Dirty = False
If chkOperationsAndMaintenance Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
End If
End Sub

Trouble trapping 2501 error

I am sending data from frmSearchEmployeeWorksheets to frmStatsCorr which runs a query (qryStatsCorr). On frmStatsCorr I am checking to make sure the query returns records otherwise I will Msg the user and return to the search form. My problem is that I am having problems 'ignoring' the 2501 caused by the DoCmd.OpenForm ("frmStatsCorr") which I learned here on Stackoverflow...
What am I doing wrong that is causing me major Access VBA Frustration??
This is the sub on the Search form (frmSearchEmployeeWorksheets):
Private Sub btnSearch_Click()
' I only change focus to force the updated data to submit to query
Me.[txtEmployee].SetFocus
Me.txtShift.SetFocus
If txtUnit = "7" Then
'First close the form in order to update
DoCmd.Close acForm, "frmStatsCorr"
' Open Stats form
On Error GoTo myErr
**DoCmd.OpenForm ("frmStatsCorr") 'causes error**
End If
myExit:
Exit Sub
myErr:
Echo True
If Err.Number = 2501 Then GoTo myExit
MsgBox Err.Description
GoTo myExit
End Sub
In frmStatsCorr I simply check to make sure the query returns records if not I inform the user, close the form, and return to the frmSearchEmployeeWorksheets
Private Sub Form_Load()
If strFormStatus = "view" Then
If DCount("*", "qryStatsCorr") = 0 Then
MsgBox "Your search does not produce any results. Try a different search.", vbOKOnly
DoCmd.Close
DoCmd.OpenForm ("frmSearchEmployeeWorksheets")
Exit Sub
End If
txtDay = WeekdayName(Weekday(Me.WorkDate)) 'This line returns an error so I check for an empty query and return to the search form.
Me.[WorkDate].SetFocus
Me.txtUnit.Enabled = False...
I'm unsure how well I understand your code or the logic behind it. My hunch is you should check the DCount result from btnSearch_Click, and not fiddle with closing then re-opening frmStatsCorr, and having frmStatsCorr close itself when it contains no data. Just do not open frmStatsCorr when it will not contain data.
If the current form (frmSearchEmployeeWorksheets) which holds your btnSearch_Click procedure contains unsaved data changes, you can save them with Me.Dirty = False
Private Sub btnSearch_Click()
Dim strPrompt As String
If Me.Dirty Then ' unsaved data changes
Me.Dirty = False ' save them
End If
If Me.txtUnit = "7" Then
If DCount("*", "qryStatsCorr") = 0 Then
strPrompt = "Your search does not produce any results. " & _
"Try a different search."
MsgBox strPrompt, vbOKOnly
Else
' if frmStatsCorr is open, just Requery
' else open frmStatsCorr
If CurrentProject.AllForms("frmStatsCorr").IsLoaded Then
Forms("frmStatsCorr").Requery
Else
DoCmd.OpenForm "frmStatsCorr"
End If
' uncomment next line to close current form
'DoCmd.Close acForm, Me.Name
End If
End If
End Sub
If frmStatsCorr is open and you need to check whether it is in Design View, examine its CurrentView property.
Forms("frmStatsCorr").CurrentView ' Design View = 0
I suggested that approach because I suspected frmStatsCorr's Form_Load may trigger the 2501 error when it closes itself. But I'm not certain that's the cause of the error and I'm not motivated enough to set up a test.
If you still have 2501 errors with the approach I suggested, there are two other possible causes I've encountered:
corruption
broken references