I'm creating a navigation form where some of the navigation buttons simply apply filters to the subform. Problem is right now each option is exclusive, i.e. I can select staff either by branch OR by job title. How can I make the options NOT exclusive so that I can apply multiple filters at once?
EDIT just to add. I have no knowledge of VBA so I'm trying to do this using the graphical interface and of macros. If it can't be done using these tools then fine, I'll find a different solution.
If you replace the .Filter property on a form (or subform) with a new value then the previous filter goes away. If you append a new clause onto an existing .Filter string, e.g. by changing...
[Branch]="Main"
...to...
[Branch]="Main" AND [Title]="Manager"
...then the new filter applies both criteria.
This solution requires a moderate amount of VBA (I can't think of a solution that wouldn't require it). Store the user's choices in module level variables and then apply your filters using a master ApplyFilters subroutine.
For example, give each checkbox an AfterUpdate event. This event will do 2 things:
Set the module level variable with the user's selection
Start the ApplyFilters sub
Since all the user's choices are now stored in module level variables, the ApplyFilters can see them all. It will:
Take all the module level variables and creates a master string (hint, if you need a Placeholder, use 1=1)
Apply that string as your subform's filter.
Other notes:
Accessing your subform's controls from the main form is simple. To change your subform's filter to the string NewFilter, try:
Forms!MyMainFormsName!MySubFormsName.Filter=NewFilter
Related
Forgive me if this has already been asked- I can’t seem to find a well written answer.
I am developing a small application for personal use.
Essentially what I have is two forms. Form 1 is a master view of all my contacts listed on a data grid view. Form 2 will be loaded on the cell/row double click of a particular record in order to edit it’s details.
My question is, what is the best practice/method for achieving this? I have seen many different methods.
Should I:
Pass only the primary key of the selected row then populate the fields on form 2 load
Pass all fields as a variable within a class then populate form 2 from that
Maybe I’m headed in the complete wrong direction though.
I have tried both ways, but wondering what the best method is for scalability.
My personal preference would be to pass a datarow into the opening argument of the form (rather than the PK / all the variables). You can then use the datarow inside your Form2 to bind to your controls or set their values, whichever you think is appropriate.
There are some useful examples on working with a datarow if you're unsure, alternatively you can also check out Microsoft Docs.
Public Sub New(ByVal row As DataRow)
InitializeComponent()
' your code for working with row here
End Sub
Edit:
In terms of "Binding" vs "Setting", you can either have your controls linked to your data to be two way (as you edit the data in a control at run time you alter the data in your database) or you can just set the values of the controls.
E.G. TextBox1.Text = row(0)("ColumnName")
You can find more on data binding on the Microsoft Docs page
Ok so I hope the title of the question matches what I about to ask, but here is what I am trying to get at:
So I have an access database that uses a number of unbound forms, and the purpose of the forms are to collect data and save to various tables with VBA click events using SQL statements (INSERT or UPDATE based on whether the ID of the record is present on the form in a hidden text box). When entering a new record (via INSERT), I get the row number with
MyRow = db.openrecordset("SELECT ##Identity")(0) 'thanks David
So you maybe getting the picture. If I have another form that relates to the first form in terms of the record, I just open a recordset and pass that value to another hidden text box.
So my question is, is there a better way to do this regarding passing that value (or just using that value) using a variable instead of this awkward method. So I realize a lot of folks are going to go with the obvious answer of, "Why not just make your forms bound instead of all this code"...and I am sure that is a valid answer, however I inherited this database which was already put together like this, and re-structuring it would be a daunting task.
Any and all advice, or learning resources are greatly appreciated, as they always are!
I use unbound controls on forms for all these kinds of values. The current solution of using an unbound form is sounder than using global or form level variables. If I recall the details correctly while debugging code and you hit the stop button you lose all global or form level variables. Or if the user hits an unhandled error.
Have you looked at OpenArgs?
DoCmd.OpenForm "Form1", , , , , , "Hello"
So how can I pass a value from one form to another? For example: The user select's an organization from a list and this opens up a trip form that allows a user to enter various information regarding the trip. At one place I would like to add another little pop up form where they can enter contact information (just a name and phone for POC) of the organization they are visiting.
So when that initial form opened from the selection screen it has two IDs that are simply hidden in text boxes (one being the tripID, and the other being the OrgID), so how do I pass these to the second little pop up form so that the contact information has the relative IDs with it.
Thanks.
The best approach in these cases is not to attempted to pass a bunch of variables. It is too much code, and is inflexible. For example, if you need to pass two values, what happens over the years when that requirement grows to 5 values? Trying to maintain and pass a whole whack of values is too much coding work.
Keep in mind that each form in ms-access is really a class object that you can manipulate in code. So, use a object approach here and you find you not only write less code, but your code will be more clean, more modular, no need for global vars, and code you write can often be re-used between different forms.
Here is how:
In general when one form launches another form in the 2nd form in the forms on-open event (in fact, you can even use as late as the on-load event) you can pick up a reference to the PREVIOUS form object. In other words, you can use a object approach here.
At the forms module level, for form I declare a form object as:
Option Compare Database
Option Explicit
dim frmPrevious as form
Then, in the forms on-load event, we go:
Set frmPrevious = Screen.ActiveForm
Now, any code in our form can FREELY use code, events, even varibles declared as public from that previous form in code.
So, if you want to force a disk write of the previous form, and re-load of data.
frmPrevious.Refresh
If you want to set the ID value, then go:
frmPrevious!ID = some value
And, note that you can even declare form previous as a PUBLIC variable for that form, and thus if you two forms deep, you could go:
frmPrevious.frmPrevious!ID = some value
So, simply declare a forms object in EACH forms code module (or at lest the ones where you need to use values in code). The above means any code has a ready made reference to the previous form object. Functions declared as public in a form will become a METHOD of the form, and can be run like:
frmPrevious.MyCustomRefresh
or even things like some option to force the previous form to generate and setup a invoice number:
frmPrevous.SetInvoice
or
frmPrevious.SetProjectStatusOn
So not only can you shuffle values and data back and forth, but you can easily execute features and functions that you build in code for the prevous form.
In fact as a coding standard, MOST of my forms have a public function called MyRefresh.
Note that the beauty of this approach is that you can thus read + use + set values from that previous form. This allows your code to not only receive values, but also set values in that previous form. So this approach is bi-directional. You can shuffle data and values back and forth between the forms. The other advantage here is you NOT restricted to just variables, but can use fields, control values (events, properties) etc.
This approach means that much of the previous form is now at your fingertips.
So don’t try to pass a whole whack of variables. Pass a reference to the form and you have a nice ready made object at your fingertips and it makes this type of coding problem a breeze.
The usual way would be to reference the textboxes in the initial form from the popup form, like this:
Forms!frmInitialForm!tripID
Forms!frmInitialForm!OrgID
However, this tightly binds the popup form to the initial form, so that it cannot be used anywhere else in the application.
A better approach is to use OpenArgs:
DoCmd.OpenForm "frmPopup", OpenArgs:=Me.tripID & ", " & me.OrgID
This places your two values into a string, which is passed to the popup form. You can then parse the two values out of the OpenArgs using the Split function.
For more info about passing parameters using OpenArgs, see:
http://www.fmsinc.com/free/NewTips/Access/accesstip13.asp
This one could help
MS Access: passing parameters from one access form to another
I have a form that I intend to allow users to browse powerpoint presentations through, because there are a lot of different briefs for metrics, which is what I use this database for. So, I already know how to set up everything, just got one little hang up.
If I place a combo box on the form to select from a list of different presentation, can I use that in the file path string (that I have to use to pull the ppt into theobject frame in access.
example:
"C:\Users\Justin\Desktop\" & cmbTitle & ".ppt"
I tried it and it gives me the error message variable not defined. I never defined a control before on in these things, would it be as a string?
I realize that the exact file path much match the entered value. Access 2000-2003/XP
Thanks as always guys!
You need to refer to the field as Me.cmbTitle. As it is written, it looks like you're calling the variable cmbTitle which doesn't exist.
Is the value of cmbTitle some ID/Integer field or is it the actual string value? You may want to use the immediate window to check this. Also, make sure the value of cmbTitle doesn't have any backslashes or spaces (That may require quotes?).
I'm somewhat confused as to what you're trying to do. I will write my answer assuming:
you have a form in an Access database.
on that form is combo box that lists the PowerPoint presentations your users are working with.
the bound column of the combo box lists the filename (without path) of each PPT file.
when the user selects a filename from the combo box, you want to display it in an unbound OLE object frame.
The code for that, assuming the list of PPT files is called cmbTitle, would be in the combo box's AfterUpdate event and would look like this:
Private Sub cmbTitle_AfterUpdate()
Dim strPresentation As String
If IsNull(Me!cmbTitle) Then Exit Sub
strPresentation = "C:\Users\Justin\Desktop\" & Me!cmbTitle & ".ppt"
Me!olePPT.SourceDoc = strPresentation
End Sub
Now, I can't get a test unbound OLE object frame to work with this, but it seems to me to be the right way to do it.
My suspicion is that you're either attempting to set the wrong property, or you've defined your OLE frame wrongly, but I can't offer any more advice on that without knowing more about what you're actually attempting to do, and exactly what line of code is causing the error.
I have an Access form where each record has some info that is computed on the fly. I'm using the Form_Current() event; each time a record is selected, I compute some information and change some form controls to reflect it, based on the record's ID.
I want to print a bunch of these records. However, in this situation the Form_Current() event isn't being triggered and the printed records lack that dynamic information.
Any ideas?
Make a query that computes the information you need as the source of your report. You can use vba functions if needed for complex calculations.
In a comment, Luis Oliveira asked:
My function was in the Form itself,
which is why I couldn't call it from
the SQL query, I suppose?
By default, functions in a form are private. If made public they can only be called when the form is open, as in Forms!MyForm.PublicFunction(). I would advise against that. Instead, move the function to a public module (which may require revisions to remove references to form controls/fields).