Runtime sorting of data in microsoft Access - ms-access

I have an access report which fetches data from an underlying access query. The problem I am having is that I want to be able to allow the user the ability to sort the data based on 3 separate fields. How can I give the user this facility that he can choose if he wants to sort the incoming data based on a field A, B or C?
Kindly help.
Thanks!

The following should help.
First, use openArgs parameter to pass user's selected OrderBy field:
DoCmd.Close acReport, "MyReport"
DoCmd.OpenReport "MyReport", acViewPreview, , , , "OrderByColumnName"
Then, use passed value for ordering on report Load:
For Access 2007+:
Private Sub Report_Load()
Me.Report.OrderByOn = True
Me.Report.OrderBy = Me.Report.OpenArgs
End Sub
For Access 2003:
Private Sub Report_Open(Cancel As Integer)
Me.Report.OrderByOn = True
Me.Report.OrderBy = Me.Report.OpenArgs
End Sub
The outcome is the same: report will be [re]sorted based on the passed parameters.
Hope this helps.

Pivot Charts are the way to go for more complicated visualization of data.
If you really only want them to select on of the 3 fields, you can have a form where the user selects the field (through a listbox i.e.), open the report through the form and set its source attribute accordingly.

Related

MS Access 2016: Set Report's RecordSource to get data from a Subform

Is there some sort of work-around that could make this possible? Or could anyone offer just some general advice on my situation below? I tried to set the record source through VBA but had no luck.
My situation:
I have a main form with a subform contained within, and I want the subform to be purely for data entry (Data Entry = Yes). Upon clicking a button, the user is sent from the main form to a report (print preview only). I want the source for this report to be the subform the users are entering data into, but I don't have this option from the report's property sheet itself (no forms), and I also was unable to set it through VBA. Here's my code, it's one line so I highly doubt it's the problem.
Private Sub Report_Load()
Reports![P18003 SDR Report].RecordSource = "P18003 SDR Subform"
End Sub
Previously, to work-around this I had a parameter query that waited for the user to enter data into an unbound textbox from the main form, and an after update trigger on that textbox would load any data relevant to that parameter (my employer and I miscommunicated the requirements).
It turns out though that I don't need to load any older data, and I run into problems with my current parameter query in the event that the user does input a parameter which loads old data - that old data is transferred to the report in addition to the new data they've just entered. This is the main problem with the method I am currently using, and it trashes almost all functionality with this form and report. The events that a user would need to enter a parameter which queries older data are few and far between, but it's not a functional product unless I can get the subform to be connected to the report directly. There's likely something obvious I'm missing here (or at least, I hope there is).
Thanks in advance for taking the time to read this and for any help you may offer.
you can either send the recordsource to the report itself in the OpenArgs by the open report event, after the click event in the subform
Private Sub btnSubform_Click()
Dim strSQL as String
strSQL = "SELECT * FROM SubformQuery WHERE ID = " & CurrentSubfromRecordID
Docmd.OpenReport, acViewReport, , , , strSQL
End Sub
and then in the Report.
Private Sub Report_Open(Cancel As Integer)
Me.recordsource = Me.OpenArgs
End Sub
Or you can make a paramter Query and set this Query criteria as record source for the report. So the parameter in the query is pointing to the current selected row in the subform. Like this:
--- At the Criteria in the Query designer:
--- RecordSource for the Report:
Forms![FormMain]![YourSubform]![ID]
Now every time the reports obens he gets the ID from the current selected record of your subform.

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.

MS Access - opening a form with a new record and inserting a value from a previous form

I have a form in an MS Access database which lists Orders with an Order Number with one order per page. At the bottom of the form there is a button which opens another form, to add an item for the order.
I am trying to use vb in MS Access to take the order number and automatically put it in a field in the details form for the new item. I have tried different ways but using OpenArgs seems to be recommended. But the detail form won't open and I get run-time errors.
Here are the details of the problem - advice will be much appreciated:
The forms and field concerned are:
Form with orders is frmPedidoAvifiFind
Form with order-lines for one order is frmPedidoAvifi-dtlAdd (a separate form for adding details but not for viewing existing ones).
Field on both forms for Order Number is PedidoAvifiNo. This is a numeric field in both tables which are linked by a one-to-many relation via this field.
Main form: Button bring up detail form, code as follows:
Code on main form button:
Sub AddDetails_Click()
Dim strDocName As String
strDocName = "frmPedidoAvifi-dtlAdd"
' Open frmPedidoAvifi-dtl form in data entry mode and store PedidoAvifiNo in the form's OpenArgs property.
DoCmd.OpenForm strDocName, , , , acFormAdd, , [frmPedidoAvifiFind]![PedidoAvifiNo]
End Sub
Detail form: On Open property
Private Sub Form_Open()
If Me.OpenArgs <> vbNullString Then
Me.PedidoAvifiNo = Me.OpenArgs
End If
End Sub
Test 1: select an order number on main form so that record shows.
Press button to add orderline. - run-time error '2465' can't find the field "|" referred to. Debug highlights the DoCmd line.
Test 2:
Change openform line to:
DoCmd.OpenForm strDocName, , , , acFormAdd, , Me.PedidoAvifiNo
result: - run-time error 2501 the openForm action was canceled.
Thank you,
Mike Gunner
Reus, Spain
The error you are getting means that you have misspelled the name of the control PedidoAvifiNo.
When you type Me. intellisense will give you a list of available fields, see what you have that is similar to PedidoAvifiNo, or check the properties. It can be very easy to switch one letter and not notice.
As for the second part, you should use the Load event, rather than the Open event on frmPedidoAvifi-dtlAdd, because the controls are not yet available in the Open event.

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.