MS Access save record as PDF using ID - vba

My organization uses a MS Access database to store incident reports. I have a report called "Case Details" and I want to have the option to save the report that's currently open as a PDF. I've got it working for the most part, the only issue is that when saving the PDF, it's saving all of the records, not just the record that was being viewed.
How do I fix it so that it only saves the record being viewed, using the record's ID?
Here's the code for the save button.
Private Sub Command1626_Click()
DoCmd.OutputTo acOutputReport, "Case Details", acFormatPDF, "G:\Police\Restricted\Saved Reports\ " & Me.txtPDFRef & ".pdf", True
End Sub
The "txtPDFRef" box on the report contains the following code, which is used to name the report. (Case Number - Officer - Date Saved)
="CR" & Format(Date(),"yy") & "-000" & [ID] & " - " & [ReportingOfficer] & " - " & Format(Date(),"yyyymmdd")

It seems the only way is to filter the report to the record to be printed.
So it's essential to determine the ID of the record to be printed.
It's not clear for me, if your button is located on the report itself or maybe on a form.
Button on the report itself
I tried to get it running when the button is on the report itself.
To determine the current ID it seems to be necessary that the calling button is located in the detail section of the report.
Then you can filter the report, export it to pdf and restore the maybe before applied filter.
The only backdraw is, that I found no way to view the last viewed record in the report after the code executed.
Instead you are on the first record.
This would be the code for the button:
Dim currentFilter As String
currentFilter = Me.Filter
Dim currentFilterOn As Boolean
currentFilterOn = Me.FilterOn
'If field type of ID is a number use this:
Me.Filter = "[ID] = " & Me.ID
'If field type of ID is a string use this:
'Me.Filter = "[ID] = '" & Me.ID & "'"
Me.FilterOn = True
DoCmd.OutputTo acOutputReport, Me.Name, acFormatPDF, "G:\Police\Restricted\Saved Reports\ " & Me.txtPDFRef & ".pdf", True
Me.Filter = currentFilter
Me.FilterOn = currentFilterOn
Button on a form
If the button is for example on a form and you just want to print the regarding report, then you could use this code in this button:
Const REPORT_NAME As String = "Case Details"
Dim condition As String
'If field type of ID is a number use this:
condition = "[ID] = " & Me.ID
'If field type of ID is a string use this:
'condition = "[ID] = '" Me.ID & "'"
DoCmd.OpenReport REPORT_NAME, acViewPreview, , condition, acHidden
'You would have to provide txtPDFRef in another way, because the report isn't open yet.
DoCmd.OutputTo acOutputReport, REPORT_NAME, acFormatPDF, "G:\Police\Restricted\Saved Reports\ " & Me.txtPDFRef & ".pdf", True
DoCmd.Close acReport, REPORT_NAME
It closes the report after saving to pdf. Be aware that you maybe have to provide txtPDFRef in a different way. But maybe it exists on the form too with the same name, that would make it run immediately.

Simplest solutions:
Option 1
Open the report in preview with a filter, then use outputTo without the ObjectName argument.
docmd.openReport "Case Details",,"id = " & id
docmd.outputTo objectType:=acOutputReport, outputFormat:=acFormatPDF, outputFile:= somefileName
docmd.close acOutputReport, "Case Details"
Option 2 (even simpler)
In design view, change the reports'filter property to refer to a control in the calling form.
Something like id = forms!someForm.idControl

Related

Create PDF button for current record

Private Sub CreatePDF_Click()
Dim FileName As String
Dim FilePatch As String
FileName = "Geleidelijst" & Me.OrderNrCopy
Filepath = "C:\Users\A\Desktop\Test\" & FileName & ".pdf"
Forms("GeleidelijstForm").Filter = "[InvoerOrderNr]='" & Me![OrderNrCopy] & "'"
Forms("GeleidelijstForm").FilterOn = True
DoCmd.OutputTo acOutputForm, "GeleidelijstForm", acFormatPDF, Filepath
End Sub
It seems to create a PDF of all records, I only want it for the current record but it won't work.
And if possible, if the file already exist to create it with a different name by adding a number behind it or something but that's not necessary.
Thanks for any help.
For anyone that needs the code to create a PDF file from the current record.
Had to change the entire code, it will save the current Form so the Report displays the accurate information and will refresh after, and ask you where you would like to safe the PDF file. Afterwards it will close the print preview.
Replace the FormName, NameOfColumnInTable, NameOfMatchingTextboxOnForum, ReportName and File to your own.
Private Sub CreatePDF_Click()
DoCmd.Save acForm, "FormName"
Me.Refresh
DoCmd.OpenReport "FormName", acViewPreview, , "NameOfColumnInTable = '" & Me.NameOfMatchingTextboxOnForum & "'"
DoCmd.OutputTo acOutputReport, "ReportName", acFormatPDF, File, False, , , _
acExportQualityPrint
DoCmd.Close
End Sub

Filter SubForm based on multiple criteria

I have a Form with a SubForm, i'm trying to filter based on a range of two dates and an Username (i take the criteria from 3 textboxes), the part of the dates works fine but when i press the button to start the filter, a pop-up shows saying "Enter parameter value" (even if i type the username in the textbox), i enter an username and filters correctly, but the parameter its kept and the filter won't work anymore, until i close the Form and open again, any ideas?
I don't know why ask me to enter a parameter if i have already the username in the textbox.
Here my code:
Private Sub Filter_Click()
Dim QIL As Form
Set QIL = Forms("QIL")
If IsNull(Me.username_textbox) Or IsNull(Me.date_from_textbox) Or IsNull(Me.date_to_textbox) Then
MsgBox "Insert date or username"
Else
With Me.Superlinks_subform.Form
.Filter = "[Date] = #" & Format(Me.date_from_textbox, "mm\/dd\/yyyy") & _
"# AND #" & Format(Me.date_to_textbox, "mm\/dd\/yyyy") & "# AND [User] = " & Me.username_textbox.Value & ""
.FilterOn = True
End With
End If
End Sub
Regards
Diego.
Assuming the field [User] is a String - include single quotes like this:
[User] = '" & Me.username_textbox.Value & "'"

Code returns incorrect records/fails to update form correctly

So I'm going to try my best to explain the background to clarify understanding of what I'm hoping to achieve. I have a form (Events) that has a tab control, the tab control has 3 different pages each with a different subform on.
One of the subforms (speakers) has a button control that checks the 'speakers' attendeeID and if there is a match opens the 'Onboarding' form to the record that matches.
What it is suppose to do if the record doesn't match is open form to a new record and insert the ContactID, AttendeeID and EventID.
This is the 4th iteration of the code and works to a degree/doesn't return errors
Dim myR As Boolean
Dim strSQL As String
Dim myV1 As Integer
Dim myV2 As Integer
Dim myV3 As Integer
'Define the variables to be input
myV1 = Me.AttendeeID
myV2 = Me.ContactID
myV3 = Me.EventID
'Is there a Matching Onboard Record for the current Attendee Record?
myR = DCount("*", "tbl_Onboarding", "[AttendeeID] = " & Me.AttendeeID) > 0
If myR = True Then
DoCmd.OpenForm "usf_Onboarding", acNormal, , , acFormEdit, acWindowNormal 'Edit Mode
Else 'No Matching Record, so Add one
If Me.Dirty = True Then Me.Dirty = False 'Save pending Edits
DoCmd.OpenForm "usf_Onboarding", acNormal, , , acFormAdd, acWindowNormal 'Add Mode
Forms!usf_Onboarding!txt_ForceFocus.SetFocus
strSQL = "INSERT INTO tbl_Onboarding (AttendeeID,ContactID,EventID) VALUES (" & myV1 & ", " & myV2 & ", " & myV3 & ")"
Debug.Print strSQL
CurrentDb.Execute strSQL, dbFailOnError
Me.Requery
DoCmd.Close acForm, "usf_Events", acSaveYes
End If
Using immediate I have confirmed myV1, myV2 and myV3 are all holding the correct values, and I used breakpoints to check line by line and all seemed to run okay with zero errors thrown back but I still have the following issues depending on whether myR is True/False
If the record exists (myR = TRUE) then something is now causing it
to only load the 1st record of the table (Not the one where the
attendeeID matches).
If the record does not exist (myR = FALSE) after running this the
table has the new record in with the contactID/AttendeeID/EventID
but the form doesn't update to show this (The form controls are set
to locked = False) This results in an error when closing. So
choosing not to save the data (Clicking yes on the box to discard
changes) allows the force exit but the record/data IS saved with
contactID/AttendeeID/EventID
Debug.Print strSQL also didn't do anything weirdly.
Issue 1. "If the record exists (myR = TRUE) then something is now causing it to only load the 1st record of the table (Not the one where the attendeeID matches)."
I needed to add a where clause to the openform command
DoCmd.OpenForm "usf_Onboarding", acNormal, , "AttendeeID = " & Me.AttendeeID, acFormEdit, acWindowNormal
Issue 2. "If the record does not exist (myR = FALSE) after running this the table has the new record in with the contactID/AttendeeID/EventID but the form doesn't update to show this (The form controls are set to locked = False) This results in an error when closing. So choosing not to save the data (Clicking yes on the box to discard changes) allows the force exit but the record/data IS saved with contactID/AttendeeID/EventID"
I was loading the form before creating the new records and trying to then requery another new record not the one it created. All I needed was add record first then use the open code above to load that record instead
Else 'No Matching Record, so Add one
If Me.Dirty = True Then Me.Dirty = False 'Save pending Edits
strSQL = "INSERT INTO tbl_Onboarding (AttendeeID,ContactID,EventID) VALUES (" & myV1 & ", " & myV2 & ", " & myV3 & ")"
CurrentDb.Execute strSQL, dbFailOnError
DoCmd.OpenForm "usf_Onboarding", acNormal, , "AttendeeID = " & Me.AttendeeID, acFormEdit, acWindowNormal

Access report not updating after query change

I have a form, below, that allows the user to filter the database multiple ways. When they push the filter button on the form a report populates based on the filter query. The issue is if I filter the database again, even with .requery in the report code, the report doesn't update to the new Query results. I know if I manually close out of the report it works, however when I code it to DoCmd.Close it doesn't actually close the report. If I show it in
acViewPreview it updates each time I use the refilter button on the form but then I cant use buttons on the report. I am trying to make it like a kiosk so I don't want the nav tabs to show.
Filter form
Report
Form Code:
Private Sub btnFilter_Click()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim SQL2 As String
Dim ToDate As Date
Dim FromDate As Date
SQL2 = ""
Set db = CurrentDb()
Set qdf = db.QueryDefs("Filter")
If cmbFilter.Value = "Vended Date" Then
ToDate = Format(DTPickerTo.Value, "YYYY-MM-DD")
FromDate = Format(DTPickerFrom.Value, "YYYY-MM-DD")
SQL2 = "SELECT CribMaster_Quality.Line,CribMaster_Quality.[Vended Date],CribMaster_Quality.PartNumber,CribMaster_Quality.Group,CribMaster_Quality.ItemNumber,CribMaster_Quality.Amount,CribMaster_Quality.Description,CribMaster_Quality.Cost,CribMaster_Quality.[Extended Cost],CribMaster_Quality.User " & _
" FROM CribMaster_Quality" & _
" WHERE CribMaster_Quality.[Vended Date]" & _
" BETWEEN #" & FromDate & "# AND #" & ToDate & "#" & _
" ORDER BY CribMaster_Quality.[Vended Date] DESC;"
ElseIf ckbDateConst = True Then
ToDate = Format(DTPickerTo.Value, "YYYY-MM-DD")
FromDate = Format(DTPickerFrom.Value, "YYYY-MM-DD")
SQL2 = "SELECT CribMaster_Quality.Line,CribMaster_Quality.[Vended Date],CribMaster_Quality.PartNumber,CribMaster_Quality.Group,CribMaster_Quality.ItemNumber,CribMaster_Quality.Amount,CribMaster_Quality.Description,CribMaster_Quality.Cost,CribMaster_Quality.[Extended Cost],CribMaster_Quality.User " & _
" FROM CribMaster_Quality" & _
" WHERE CribMaster_Quality." & Me!cmbFilter.Value & " = '" & Me!cmbFilterBy.Value & "' And CribMaster_Quality.[Vended Date] " & _
" BETWEEN #" & FromDate & "# AND #" & ToDate & "#" & _
" ORDER BY " & Me.cmbFilter.Value & " DESC;"
Else
SQL2 = "SELECT CribMaster_Quality.Line,CribMaster_Quality.[Vended Date],CribMaster_Quality.PartNumber,CribMaster_Quality.Group,CribMaster_Quality.ItemNumber,CribMaster_Quality.Amount,CribMaster_Quality.Description,CribMaster_Quality.Cost,CribMaster_Quality.[Extended Cost],CribMaster_Quality.User " & _
" FROM CribMaster_Quality" & _
" WHERE CribMaster_Quality." & Me!cmbFilter.Value & " = '" & Me!cmbFilterBy.Value & "'" & _
" ORDER BY " & Me.cmbFilter.Value & " DESC;"
End If
qdf.SQL = SQL2
Set db = Nothing
Set qdf = Nothing
DoCmd.OpenReport "CribMasterReport", acViewReport
End Sub
Report Code:
Private Sub btnReFilter_Click()
DoCmd.Close , acSaveNo
DoCmd.OpenForm "Filter Database Form"
End Sub
Private Sub Report_Load()
Me.Requery
With VendedDatetxt
.Requery
End With
With ItemNumbertxt
.Requery
End With
With Linetxt
.Requery
End With
With PartNumbertxt
.Requery
End With
With Usertxt
.Requery
End With
With Amounttxt
.Requery
End With
With Costtxt
.Requery
End With
With ExtendedCosttxt
.Requery
End With
End Sub
Issue 1: Requerying the Report
When a report is opened using standard techniques, such as clicking on a report in the Navigation pane or when opening a report using DoCmd.OpenReport, Access creates a default instance of the Report that is accessible via the Application.Reports collection. Before the report is first opened or if the default report instance is completely closed (i.e. removed from memory), the Application.Reports collection will not contain an instance of the report. Before accessing the default instance, ensure that the report is already open.
Like other MS Office object-model collections, Application.Reports does not have a "Contains" method or other direct way to test whether a report is already open, only by looping through numeric indexes and testing each report object. Although it seems sloppy to me, the easiest method is to use error handling to try getting the report directly, then catching the error if it's not found:
On Error Resume Next
Set frm = Application.Reports("CribMasterReport")
If err.Number <> 0 Then
'Default instance not open
End If
CAUTION: Do not refer to the report using the class name like an object, as in Report_CribMasterReport.Requery. If you do that, VBA will automatically create a new, hidden instance of the report, but it is NOT the same default instance as described above and this new instance will not be accessible via the Application.Reports collection. Likewise, using the properties and calling methods on such an object will be largely ineffective. (It is possible to create and use such independent instances, but that is an advance technique riddled with its own pitfalls and challenges.)
As the question describes, which is also confirmed by other online sources, the Report.Requery is not effective in refreshing the report after the underlying query or data have changed. However, resetting the Report.RecordSource forces a full refresh of the report when in normal Report View.
Issue 2: Report not closing
The DoCmd.Close command was missing a comma. It should be DoCmd.Close , , acSaveNo. Even better is to always use explicit names for optional parameters. Typing an extra parameter is definitely worth the saved frustration and time with typos in an ambiguous list of commas:
DoCmd.Close Save:=acSaveNo
Issue 3: Unnecessary calls
It is completely unnecessary to call Requery on the report and every single control in the Report_Load event. I get that you were trying to debug the situation, but this behavior should happen automatically. Also, the Form_Load event occurs only once when the form is first loaded, so that code would not be called again unless the report is completely closed and reopened.
Finally some alternative code
Private Sub btnFilter_Click()
'... Include previous code to reset report query
'* Call DoCmd.OpenReport every time to
'* 1) Ensure default report is open
'* 2) Automatically activate the report (even if it was already open)
DoCmd.OpenReport "CribMasterReport", acViewReport
On Error Resume Next
Dim frm As Report_CribMasterReport
Set frm = Application.Reports("CribMasterReport")
If Err.Number = 0 Then
'* Force the Report object to re-run query and recreate report
frm.RecordSource = frm.RecordSource
End If
End Sub
It is no longer be necessary to completely close the report.
Private Sub btnReFilter_Click()
''DoCmd.Close Save:=acSaveNo
DoCmd.OpenForm "Filter Database Form"
End Sub
Private Sub Report_Load()
'* Eliminated unnecessary Requery calls
End Sub

Export query from a report in access to excel with parameters

Private Sub txtExportCleanRecords_Click()
DoCmd.OutputTo acOutputQuery, "vCleanRecordsExport", "Excel97- Excel2003Workbook(*.xls)", "",
True, "", , acExportQualityPrint
End Sub
I created a button on an access report and I am trying to export a query that is already created. The intention of the query is gather data that has already been validated and approved so the database does not become cumbersome. The Report filters approved data by a date range and I need to export only the records that match the report. So the query ID must match the report ID and I only need the records exported that match the Report ID. So far all my report is doing is exporting the entire query and I cannot figure out how to put a where clause on the Command acOutputQuery to filter the export. Any ideas on how I can tweak my code so that I can export based on the report ID matching the query ID?
Private Sub txtExportCleanRecords_Click()
Const strcExportQuery = "ExportQuery" ' Name of the query for exports.
Dim S As String
Dim strFile As String
' Adapt to your actual fields / filter
S = "SELECT vMayClean.LogID As 'CleanRecordsID', vMayClean.[Mark Read], vMayClean.[Report Available], vMayClean.[Has Images], vMayClean.[Performing Resource], vMayClean.Org, " & _
"vMayClean.[Exam Date/Time], vMayClean.[Patient Nam], vMayClean.[Accession #], vMayClean.MRN, vMayClean.Modality, vMayClean.[Exam Description], vMayClean.[Exam Status], " & _
"vMayClean.[Referring Phys], vMayClean.[Ordering Location], vMayClean.COMMENTS, vMayClean.STATUS, vMayClean.Exceptions, vMayClean.CR, vMayClean.[CPU/ Spreadsheets], vMayClean.PACs, vMayClean.Facility, " & _
"CodeRyteID, [Patient MRN], [Patient Name], [Account Number], [Patient DOB],[Signing Physician Location], [Referring Physician], [Pri Ins Name], " & _
"[Accident Code], [Accident Event], [Accident Date], [Admit Date], [Signing Physician], [Date Of Service], Service, [Stay Type], " & _
"[Accession Number], [Order CPT], [CPT Annotation], CPT4, Modifiers, ICD1, ICD2, ICD3, ICD4, [ICD10-1], [ICD10-2], " & _
"[ICD10-3], [ICD10-4], Units, [Override Queue Level], [Manual Route Queue], [Note Handle] FROM vCleanRecordsExport " & _
"WHERE vMayClean.LogID = " & Me.ID
' Set SQL of export query. This is all it takes, no explicit "Save" needed.
CurrentDb.QueryDefs(strcExportQuery).SQL = S
strFile = "T:\Users\Reuben\Reconciliation Testing\ExportQuery"
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, strcExportQuery, strFile
DoCmd.OutputTo acOutputQuery, "ExportQuery", "Excel97-Excel2003Workbook (*.xls)", "", True, "", , acExportQualityPrint
DoCmd.OpenQuery "vCleanRecordsDelete", acViewNormal, acEdit
End Sub
Everything is working properly after I fixed the SQL statement, except for the data that the vMayClean.LogID is being compared to.
"Where vMayClean.LogID = " & Me.ID
This line of code compares the Query ID to only the current Report ID. What I need is for the export to contain all the query ID's that match all the Report ID's not just one. Let me know if I need to provide additional information.
New EDIT
I have added the code that filters the report. The report uses the vCleanRecords Query and I am exporting the vCleanRecordsExport Query which is supposed to have all the records from the vCleanRecords query, but with more data because I am exporting to delete out of the database. The report is filtered based on a start and end date that matches the date of service.
I understand what you are saying about having the where clause match the date filter where clause, but how can I tweak it so it works for the report?
Dim strReport As String
Dim StrDateField As String
Dim strWhere As String
Const strcDateConst = "\#mm\/dd\/yyyy\#"
strReport = "rptCleanRecords"
StrDateField = "[DateOfService]"
If IsDate(Me.txtStartDate) Then
strWhere = "(" & StrDateField & " >= " & Format(Me.txtStartDate, strcDateConst) & ")"
End If
If IsDate(Me.txtEndDate) Then
If strWhere <> vbNullString Then
strWhere = strWhere & " AND "
End If
strWhere = strWhere & "(" & StrDateField & " < " & Format(Me.txtEndDate + 1, strcDateConst) & ")"
End If
DoCmd.OpenReport strReport, acViewReport, , strWhere, , strWhere
This doesn't work directly. DoCmd.OpenForm or DoCmd.OpenReport have a parameter WhereCondition, but DoCmd.OutputTo or DoCmd.TransferSpreadsheet don't.
The easiest way is to have an "Export query", where you dynamically set its SQL property to the filtered list. Create this query manually with a dummy SQL, afterwards the SQL will be overwritten with each export.
Adapted from a newsgroup post by Allen Browne:
Const strcExportQuery = "ExportQuery" ' Name of the query for exports.
Dim S As String
Dim strFile As String
' Adapt to your actual fields / filter
S = "SELECT * FROM vCleanRecordsExport " & _
"WHERE QueryID = " & Me.ReportID
' Set SQL of export query. This is all it takes, no explicit "Save" needed.
CurrentDb.QueryDefs(strcExportQuery).SQL = S
strFile = "C:\Data\MyExport.xls"
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, strcExportQuery, strFile
Edit:
Maybe I'm starting to understand what you mean by "Report ID" and "Query ID".
Your report lists a number of record, filtered by date?
And the export query should export the same set of records (i.e. the records with the same ID)?
Then: what is the record source for the report?
If it's something like
SELECT Fields FROM Table WHERE someDate BETWEEN x AND y
then you should use the same filter or WHERE clause for your export query (someDate BETWEEN x AND y).
If I'm wrong: where do the IDs for the report come from?
Edit 2
So you are already constructing a WHERE string (strWhere), and passing it as OpenArgs to the report.
Then you can simply use that string instead of vMayClean.LogID = " & Me.ID.
You have the field in the export code as [Date Of Service],
and in the report code as StrDateField = "[DateOfService]".
If it's not possible to use the same name in both queries, you can do
strWhere = Replace(Me.OpenArgs, "[DateOfService]", "[Date Of Service]")
in the Export code.