Get caption of closed report - ms-access

I have a custom build print dialog that is used for many reports. Its arguments are the report name, filter string, open args for the report etc. What I would like to do is to display the caption of the report specified for printing on the form. For performance reasons, I would rather not open the report, get the caption and close it again. I would rather get it from the database somehow without actually opening the report itself.
One thing that DOES work is to call the report using it's class name report_some_report.caption but there is no way to do this without with a report name stored in a variable. I would have expected Reports("some_report").caption to work also but it only works for open reports.
Is there a better way to do this or am I going to have to do something like the following? (Which works)
docmd.OpenReport "schedule_simple",acViewDesign,,,acHidden
strCaption = Reports("schedule_simple").Caption
docmd.Close acReport,"schedule_simple"

There's no way to get a report caption from a report without first opening the report or using the report class object (as you know). It's also worth noting that "lightweight" reports (ie, ones whose HasModule property = False) do not have class objects.
You have a couple of options.
You could create a local table with a RptName and RptCaption field and query that. Of course, then you need to keep it updated somehow.
You could write a function that "memoizes" the results, so that you only have to open a given report once each time the program runs. For example:
.
Function GetReportCaption(RptName As String) As String
Static RptCaptions As Collection
If RptCaptions Is Nothing Then Set RptCaptions = New Collection
On Error Resume Next
GetReportCaption = RptCaptions(RptName)
If Err.Number = 0 Then Exit Function
On Error GoTo 0
DoCmd.OpenReport RptName, acViewDesign, , , acHidden
RptCaptions.Add Reports(RptName).Caption, RptName
DoCmd.Close acReport, RptName
GetReportCaption = RptCaptions(RptName)
End Function

Related

Opening multiples a report in more than one tab (Access Database)

I have an access database that has a report. There is a button I click to open it, and everything works fine if I just want one report. However, if I want to open the same report twice, say to compare the two, it does not work. Instead of opening the second report in a separate tab, it just takes me to the tab that has the first report on it. Is there a way that I can make the report always open in a new tab?
You can achieve this quite easily, with a little VBA. You do need to add a module to the report and to the form/report with the button:
On the buttons on click event:
Public Sub MyButton_Click()
Dim rpt As New [Report_Labels and Remarks]
rpt.Visible = True
Set rpt.Myself = rpt
End Sub
On the report, in the module:
Public Myself As Report
Private Sub Report_Unload(Cancel As Integer)
Set Myself = Nothing
End If
Note that you might need to rewrite other code, like macros closing the report, DoCmd.Close and code fetching values from the report using the Reports collection, since there are multiple instances of the report.

Can I use criteria from any current form in a single query in Access 2003

I have a report (ReportX) that I wish to open from two different forms (FormA and FormB) in my database. I wish to do this because FormA and FormB address different aspects of my data, even if they ultimately get to the same output. ReportX is based on data from QueryX.
The problem I have is that QueryX would ideally filter the data based on the current RecordID in the current form. But I don't know how to accomplish this. I'd like to design QueryX so that the criteria for RecordID is essentially CurrentForm!RecordID, but research suggests that I cannot do this. Must I make separate but otherwise identical queries and reports for each form? Or is there a way to use VBA to define the query criteria when I click on the OpenReportX command button?
I already tried using the WHERE condition in the OpenReport command:
DoCmd.OpenReport "ReportX", acViewPreview, ,"RecordID = " & RecordID
but that did not display the results I wished. I need the report header to display/print for each RecordID and the page count in the page footer to reflect only the current/total pages of the RecordID in question. (In other words, if record 1 is one page, record 2 is two pages and record 3 is three pages, then ReportX, when displaying the first page of record 2, should say "Page 1 of 2" and not "Page 2 of 6.") So being able to display and print a single record properly using record filters would also solve my problem.
Which is the least cumbersome/most possible solution?
You should be able to accomplish this using the WHERE condition argument when you open a report:
DoCmd.OpenReport "rptName", acViewPreview, ,"RecordID = " & Me!RecordID
In the case where a I need more control over a Report's recordsource than what the Where condition argument can do for me, I will set the Reports RecordSource to be blank (after designing the report). Next I write code create the correct SQL statement in the Open Report button's Click event, followed by code to open the report and pass in the SQL as an opening argument for the report.
Private Sub cmdOpenReport_Click()
Dim sSQL as string
sSQL = "SELECT * FROM tblWhatever WHERE RecordID = " & Me!RecordID
DoCmd.OpenReport "rptReportName", acViewPreview, , , ,sSQL
End Sub
Then in the report's Open event I write code to set the recordsource:
Private Sub Report_Open(Cancel As Integer)
If IsNull(Me.OpenArgs) = False Then
Me.RecordSource = Me.OpenArgs
End If
End Sub
If neither of those accomplish what you want then you have an issue of a different sort. It's a little difficult for me to understand why you need All Records to show up in the header but only one record in the detail area. And how you expect to accomplish this. You might be best off trying to write a query first that gives you the exact results that your looking for so you know that it can be done.
As a side note, I actually use very few saved queries in my designs. It's not that there's anything wrong with using them, as the option is there for your convenience. I frequently use raw SQL on both forms and reports and set the RecordSource to the SQL on the Form or Reports Open or Load events.
Yes you can point to form data items in a query, and subsequently use that query in a report. The forms need to be open before the report runs. As far as having a header for each record, that is controlled in the settings of the report and how it displays the data.
In the Field, or Critera you can use the format:
[Forms]![frm_Process_Candidates]![QuestionTemplate]
Where frm_Process_Candidates would be the name assigned to your form, and QuestionTemplate is either the name of a control on your form, or a field from the data source of your form.
If you have a sub-form, there will be another [Form] call in the middle there.
[Forms]![frm_Dropdown_Admin]![frm_Dropdown_Admin_Detail].[Form]![text22]
Access should figure it out from there.

Access Report not Filtering when Others Are

I have a form which allows the user to edit the properties of a filter via some combo boxes, then open a report. The report is opened with
DoCmd.OpenReport rptName, acViewReport, , whereClause, acWindowNormal
'whereClause = "Building = '005'" for instance
Some reports open fine, by which I mean they populate with the filtered info. Others, however, even though they are based off the same in-house template, IGNORE the filter all together and display a report based on ALL data (not the filtered data).
Why would a report ignore the filter? When I edit the reports in design mode after opening them with the form:
Working Report | Non Working Report
Filter: Building = '005' | Filter:
Filter On Load: No | Filter On Load: No
What could be causing the non-working report to not register the filter argument? There's no On Load VBA, nor any VBA, in these reports (except for an Export to PDF and a close button which is copy-paste for each report).
EDIT
Should have checked before, this happens regardless of whether or not the query driving the report is empty (ie the filter is never applied to some reports, regardless of blankness)
Not sure if the code will help, but:
Private Sub btnOpenSummary_Click()
If IsNull(Me.cboSummary) Then
MsgBox "Please select a building for the SUMMARY report."
Exit Sub
End If
strCrit = "Building = '" & Me.cboSummary & "'"
MsgBox strCrit
survArray = getSurveyArray()
For Each Survey In survArray
DoCmd.OpenReport Survey, acViewReport, , strCrit, acWindowNormal
Next Survey
DoCmd.OpenReport "Total Summary", acViewReport, , , , Me.cboSummary
End Sub
My fault.. there was code which had for some reason been linefed all the way down the code page and out of view. There was an On Open which played with the Control Source. It ended up being useless (as the control source only needed to be set once, not every time) but it was disabling the filter for some reason. Anybody else who may have this problem:
Make sure the control source is not being altered in your VBA for the report.
Thanks to those that helped, sorry my information was wrong.
My OnOpen code:
Private Sub Form_Open(Cancel as Integer)
Me.RecordSource = Me.Name
End Sub
It takes the name of the report, which corresponds to a name of a query, and puts it as the recordsource. (I have about 40 reports done this way, so it's dependent on names to make it fast to duplicate for different items).
Removing this made it work perfectly using Access 2010. Not sure if this was a problem specific to my setup or what, but, this change directly fixed it.
This is not a direct solution, but rather a workaround which should almost certainly work. Instead of applying filtering to the report, dynamically change the report data source by passing the where clause as a parameter.
To open the report use:
DoCmd.OpenReport rptName, acViewReport, , , acWindowNormal, whereClause
Note that the whereClause string is being passed as the OpenArgs parameter.
Then in the report VB:
Private Sub Report_Open(Cancel As Integer)
On Error GoTo ReportOpenError
If Not(IsNull(Me.OpenArgs)) Then
Me.RecordSource = Replace(Me.RecordSource,";"," WHERE " & Me.OpenArgs & ";")
End If
Exit Sub
ReportOpenError:
MsgBox "Unable to open the specified report"
Cancel = 1
End Sub
This solution assumes the report RecordSource is defined as a semicolon terminated SQL query (not a query name) and the record source does not already contain any WHERE, GROUP BY, etc., clauses. In those cases, it may be easier to redefine the query from scratch.
This problem may also occur when a report is copied and re-purposed. I had a report that was working fine then made a copy of it and was no longer able to filter it.
Perhaps there is a glitch in Access that causes it to ignore the filter when the report is copied under certain circumstances.
Solution: Instead of copying and re-naming the report, try creating a new report, linking the data source, and copying the fields back into place. If you are dealing with a new report, try re-creating it.

Access Report won't allow me to refer to a field in VBA unless it's on the report in its own right

So, in an Access Form or Report a good way to show something dynamic on the screen that is more complex than =[UnitPrice]*[Quantity] is to drop into VBA.
e.g. in this simplified example, the underlying table for this Report has two fields ShowTax and TaxRate. By making a TextBox's control source =GetTaxInfo I get to introduce some complexity in VBA:
Public Function GetTaxInfo() As String
Dim result As String
If Me!ShowTax = 0 Then
result = "Tax included # " & Me!TaxRate
Else
result = ""
End If
GetTaxInfo = result
End Function
OK, this works ... so long as I have a field somewhere else that refers to TaxRate. Otherwise it just prints #Error. It's as if it needs to preload the field before it can be used in VBA code. It isn't the end of the world because I can have a bunch of fields in the report all set to not be visible, but it's untidy.
So is it the case that you can't refer to a field in VBA code backing a report unless you have already referred to the field in the conventional way as a field baked into the report?
I can't remember encountering this limitation before. Or is it that I have a corrupt report? (I have tried the usual compact/repair, export/reimport the Report etc)
Edit:
the weird thing is ... now it's working again. And - I'm pretty sure - there is no control in the report. which is why I was thinking it was a corruption in the report.
You'll need a control on the form/report.
If this is too messy, you could put the function in a Module and use in the RecordSource (based on a query). No sense burying all this logic in a report when it could be used in other places as well.
Public Function GetTaxInfo(ShowTax as Boolean, TaxRate as Single) As String
Dim result As String
If ShowTax = 0 Then
result = "Tax included # " & TaxRate
Else
result = ""
End If
GetTaxInfo = result
End Function
Then the control is set to this field in this report and others.

Best way to prompt for report parameters in microsoft access

Lets say you are designing a sales report in microsoft access. You have 2 parameters: Startdate and EndDate.
I can think of 3 ways to prompt the end user for these parameters when the report is run.
Create a form with 2 Text Boxes and a button. The Button runs the report, and the report refers back to the form by name to get the start date and end date.
Create a form with 2 text boxes and a button. The button runs the report but sets the appropriate filter via the docmd.openreport command.
Base the report on a Query and define query parameters. Access will automatically prompt for those parameters one by one.
Which is the best way to go?
Which is best depends on a number of factors. First off, if you want to run the report without parameters, you don't want to define them in the recordsource of the report. This is also the problem with your first suggestion, which would tie the report to the form (from Access/Jet's point of view, there is little difference between a PARAMETER declared in the SQL of the recordsource and a form control reference; indeed, if you're doing it right, any time you use a form control reference, you will define it as a parameter!).
Of the three, the most flexible is your second suggestion, which means the report can be run without needing to open the form and without needing to supply the parameters at runtime.
You've left out one possibility that's somewhat in between the two, and that's to use the Form's OnOpen event to set the recordsource at runtime. To do that, you'd open the form where you're collecting your dates using the acDialog argument, hide the form after filling it out, and then write the recordsource on the fly. Something like this:
Private Sub Report_Open(Cancel As Integer)
Dim dteStart as Date
Dim dteEnd As Date
DoCmd.OpenForm "dlgGetDates", , , , , acDialog
If IsLoaded("dlgGetDates") Then
With Forms!dlgGetDates
dteStart = !StartDate
dteEnd = !EndDate
End With
Me.Recordsource = "SELECT * FROM MyTable WHERE DateField Between #" _
& dteStart & "# AND #" & dteEnd & "#;"
DoCmd.Close acForm, "dlgGetDates"
End If
End Sub
[Edit: IsLoaded() is a function provided by MS. It's so basic to all my Access coding I forget it's not a built-in function. The code:]
Function IsLoaded(ByVal strFormName As String) As Boolean
' Returns True if the specified form is open in Form view or Datasheet view.
Const conObjStateClosed = 0
Const conDesignView = 0
If SysCmd(acSysCmdGetObjectState, acForm, strFormName) <> conObjStateClosed Then
If Forms(strFormName).CurrentView <> conDesignView Then
IsLoaded = True
End If
End If
End Function
Now, there are certain advantages to this approach:
you can pre-fill the dates such that the user would have to click only OK.
you can re-use the form in multiple locations to collect date values for multiple forms, since the form doesn't care what report it's being used in.
However, there is no conditional way to choose whether to open the form or not.
Because of that, I often use a class module to store filtering criteria for reports, and then check if the relevant class module instance has filter values set at the time the OnOpen event fires. If the criteria are set, then I write the SQL for the recordsource on the fly, if they aren't set, I just use the default recordsource (and any filter passed in the OpenReport argument). In this setup, you would run the report only after you've collected the criteria and set up the class module instance. The advantage of this approach is that the report can be run in either of the two contexts, and none of the parts need to know anything about each other -- the report simply needs to understand the class module's interface.
I used to use the Docmd.Openreport Where clause, your option 2. But I've switched to using report filters in the reports Open event, your option 1, as it supports creating PDF files which the Where clause does not. See Microsoft Access Report Printing Criteria Selection Form at my website.
As far as the dates go in SQL strings I use the Format statement as at Return Dates in US #mm/dd/yyyy# format
Also your option three can be handled by putting in the following example in the criteria in the reports record source SQL query. Forms!Form_Name!Control_Name. This is generally simpler for folks who don't want to get into VBA.