Pass a selected value to a second combo-box to filter available values - combobox

I am creating a form in Access 2013 which would allow the user to select a previously entered record for which they want to enter additional, related data. The underlying table has thousands of records so I want to use two combo boxes to make selection easier. According to multiple posts I’ve found elsewhere I should be able to set the Row Source of the cboGetSite combo-box to a table that lists all available sites. I then set the AfterUpdate() event to use the selected site to filter the second combo-box to a list that includes the available visits to that site with something like:
Private Sub cboGetSite_AfterUpdate()
Me.cboGetDate.RowSource = “SELECT VisDate FROM” & _
“qrySiteVisits WHERE location =” & _
Me.cboGetSite & _
“ORDER BY VisDate”
End Sub
When I then select a value in the cboGetSite combo-box, I get an error that states,
“The expression After Update you entered as the event property setting produced the following error: Invalid outside procedure. *The expression may not result in the name of a macro, the name of a user-defined function, or [Event Procedure]. *There may have been an error evaluating the function, event, or macro.”
Can anyone suggest where I may be going wrong? I do not use VBA, so this is a stretch for me. I’m following guides found in several threads online. Please don’t respond with, “Well the error obviously tells you…” If it were obvious I wouldn’t be asking.
Can someone just walk me through the steps? Given a query that lists the available sites and dates of visits I need to:
Select a site from a combo-box thus setting a cboGetSite value
Pass cboGetSite to cboGetDate combo-box, thus filtering to a set of visit dates.
Select a date which sets a tempVar (with SetTempVar()) which is then set as the value in subsequent forms to add related data to one of several tables, linking it back to the correct Visit record via the cboGetDate variable.

If your vba-code is painted red it is not valid!
After writing code useDebug->Compile ...in vba ide, this would show an syntax error!
From where did you copy that code? It uses wrong double-quotes (ASCII Char 147, 148 instead of 34 (Shift+'))
After that you will receive another error because you're missing blanks in your sql-string "SELECT VisDate FROM" & "qrySiteVisits WHERE location =" gets "SELECT VisDate FROMqrySiteVisits WHERE location =". Missing a blank after FROM.
IfcboGetSiteandlocationare numbers this code will work.
Private Sub cboGetSite_AfterUpdate()
Dim SQL as String
SQL = "SELECT VisDatem, id FROM " & _
"qrySiteVisits WHERE location = " & _
Me.cboGetSite & _
" ORDER BY VisDate"
'If location and cboGetSite are strings use this: SQL = "SELECT VisDate, id FROM " & _
"qrySiteVisits WHERE location = '" & _
Me.cboGetSite & _
"' ORDER BY VisDate"
Debug.Print SQL ' shows the string in immidiate window in vba ide
Me.cboGetDate.RowSourceType = "Table/Query"
Me.cboGetDate.RowSource = SQL
End Sub
What should happen ifcboGetDateis selected first (cboGetSiteis empty)? Show nothing, show all or move to cboGetSite?

Related

How do I use an array of ranges to propagate data for a search

it's 3:20 am and I'm about spent, so I'm tossing this up here in hopes someone can help me. I'm not sure this is a difficult problem, but I don't honestly know how to ask this clearly.
I made a User Form a couple of weeks ago with some help here to let users store information into a table. I'm now making a Search form to allow them to search the table (namely the full name column) and as there will be multiple entries with the same name, have it propagate a combo box so that the user can choose which entry they want to view. Depending on which entry they choose in the combobox will also propagate all the fields below it.
First, I think I've got the search function working correctly and building the array of ranges right. I had originally stored the array as strings and it populated my combo box perfectly, but then I had lost the range/address to propagate other data later. So I switched it back to an array of ranges and from there I'm having problems. Currently if I use the Combobox.additem I will of course only get a range from my array, but I can't do something like LookUpTable.Range(Array(i)).Value for my AddItem either. So, I'd like to be able to figure out how to propagate the combobox with the values in those stored ranges. I think once I learn how to do that, propagating the other fields afterwards will be pretty straightforward.
I hope this makes sense. Apologies, my brain is fried and I need some sleep.
EDIT:
The combobox will be propagated with all the duplicates as well as an identifier to easily separate them (in this case the date and person who did the evaluation) so that the user can choose which evaluation they would like to view. Right now it just shows the Full Name which is the stored range. I want to be able to essentially use the stored range to grab the entire row of values in another array that can then propagate all the fields for that report. I could make an array for every result at the time of searching, but this would be inefficient I think. Instead it should be created once the user chooses which report they want to view so it's limited to only making one array. I think I can maybe figure that out, but because it happens after they choose from the combobox, I'm unable to figure out to use that one range and pull two more columns of data with it. If I try using ,Offset with it I get an "Expected Object" error. If I try using my Table and the Array value for a range, I get a different error. I hope all this makes sense.
Public Sub Search_button_Click()
Dim NameColumn As Range
Dim NameLookUp As Range
Dim SearchResultsArray() As Variant
Dim SearchResultsCounter As Integer
Dim ResultsPropagate As Integer
Dim FirstResult As String
'Sets/Resets counter to 1 each time search button is pressed
SearchResultsCounter = 1
'Converts the text box values to strings and uppercases the first character and combines them into a full name value.
FirstLookUp = StrConv(StudentFirst_textbox.Value, vbProperCase)
LastLookUp = StrConv(StudentLast_textbox.Value, vbProperCase)
FullLookUp = FirstLookUp & " " & LastLookUp
'Sets NameColumn to the Full Name column in the table
Set NameColumn = LookUpTable.Range.Columns(3)
'Sets NameLookUp to the Full Name column in the table and searches for the FullLookUp string
Set NameLookUp = LookUpTable.Range.Columns(3).Find(What:=FullLookUp, LookIn:=xlValues, _
LookAt:=xlPart, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
'Saves the first result to prevent infinit looping and readjusts the array to match results size.
If Not NameLookUp Is Nothing Then
FirstResult = NameLookUp.Address
ReDim Preserve SearchResultsArray(SearchResultsCounter)
SearchResultsArray(SearchResultsCounter) = NameLookUp
Do
ReDim Preserve SearchResultsArray(SearchResultsCounter)
SearchResultsArray(SearchResultsCounter) = NameLookUp
Set NameLookUp = NameColumn.FindNext(NameLookUp)
SearchResultsCounter = SearchResultsCounter + 1
Loop Until NameLookUp Is Nothing Or NameLookUp.Address = FirstResult
SearchResults_combobox.AddItem ("Choose a result to view.")
For ResultsPropagate = LBound(SearchResultsArray) To UBound(SearchResultsArray)
SearchResults_combobox.AddItem (SearchResultsArray(ResultsPropagate)) 'Here I want to use the range stored in the array and pull the value from the table.
Next ResultsPropagate
SearchResults_combobox.ListIndex = 0
Else
MsgBox "Sorry, no entries matched your search.", vbOKOnly
End If
End Sub

Excel VBA: Create Array from Filter Field Items?

A report I am creating in Excel involves several very similar pivot tables needing to be specifically filtered many times (i.e. a Year-to-Date table, a Quarter-to-Date table, etc, all needing to be filtered the exact same way before exported, then filtered again, then exported, etc)
So I looked into VBA as a way of accepting a few filter criteria, then filtering multiple tables that way, before looping.
However, I'm having a very tough time properly targeting PivotTables and specific fields, as it appears an integrated Value field is targeted and filtered via code differently than, say, a "filter' field I have attached to the top of the PivotTables, where they can accept no "begins with", "contains", etc, strings. They are just checkboxes, and one or multiple can be selected.
So it's one thing for me to tell it via VBA to select one item, and having it select all but one item. The latter requires the code to target every single possible value, but not the one that I want excluded.
My idea for this, then, is to create an array from every possible existing value in this filter field, then going through a loop where each value is added to my code as a value to check.
I have some code so far:
ActiveSheet.PivotTables("QTD_Pivot_By_Category").PivotFields( _
"[Range].[Address_1].[Address_1]").VisibleItemsList = Array( _
"[Range].[Address_1].&", "[Range].[Address_1].&[0]", "[Range].[Address_1].&[101]" _
, "[Range].[Address_1].&[INC]", "[Range].[Address_1].&[KRT]", _
"[Range].[Address_1].&[LTD]", "[Range].[Address_1].&[RPO]", _
"[Range].[Address_1].&[ INC]", "[Range].[Address_1].&[CORP]", _
"[Range].[Address_1].&[INC.]", "[Range].[Address_1].&[LTD.]", _
"[Range].[Address_1].&[LTEE]", "[Range].[Address_1].&[PAWS]", _
Now, if I just record this macro from actions in Excel, and do "select All", then de-select the one I don't want, it will error. It errors because it's selecting ~300 values, and while it's 'writing' this code, it errors when it hits the limit of "_" delimited breaks in one straight line of VBA code.
If my field is called "Address_1" as above, part of the range..."Range" (not sure where that's defined or why, but it works), can I get some help as to the most efficient way to define said ".VisibleItemList" as all POSSIBLE items in the list from a dynamic array rather than needing to be selected manually? This list will be different day-to-day so it can't just be a hardcoded flat list.
Ideally, also in a way that circumvents the max limit on "_" line breaks in a line of code in VBA for Excel.
If it's of any use for context, my table looks like this. See that checkbox drop-down? I want a snapshot of every updated value sitting in there to be put into an array and then iterated upon being added in a way similar to my example code:
Edit:
Since that filter field's values are being pulled from a local datasource, I decided to just grab those and make an array that way! So I'm starting my code this way:
Dim OGDataRange As Range, OGDataLastRow As Long
Dim ValueArray As Variant
OGDataLastRow = Worksheets("DATA QTD").Range("U2").End(xlDown).Row
Set OGDataRange = Worksheets("DATA QTD").Range("U2:U" & OGDataLastRow)
ValueArray = OGDataRange.Value
"ValueArray" is now my array. So I need help one-by-one pulling the values of this array, and adding them to my VisibleItemList as seen above.
Thank you so much for any assistance.
This might help you
Private Sub this()
Dim pf As PivotField
Dim pi As PivotItem
Dim strPVField As String
strPVField = "this"
Set pt = ActiveSheet.PivotTables("PivotTable1")
Set pf = pt.PivotFields(strPVField)
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error Resume Next
pf.AutoSort xlManual, pf.SourceName
For Each pi In pf.PivotItems
pi.Visible = False
Next pi
pf.AutoSort xlAscending, pf.SourceName
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
borrowed from
Deselect all items in a pivot table using vba

Access 2010 w/SQL backend - send multiple reports to pdf using vba without preview

Scenario is an application using Access 2010 front end, SQL backend. Need exists for user to select one or more reports from form, then click button that runs through choices and runs report using strCriteria type filters depending on specific report. Most times would end up with as many as 10 different reports in 20 sets (different geographic criteria). Need to send the resulting reports to export files (PDF) for continued processing by the application (as appropriate either zips and sends files as attachments using SQL DatabaseMail system or sets task for user to send some other way).
I would like to be able to export the files without having to open the report (doCmd.OpenReport) to preview - user should not have to be involved once clicking the button. Would like to be able to pass criteria to report in command line with a WhereCondition, open report and then use doCmd.OutputTo and save as PDF (or other formats). Yes, I can pass criteria through modifying the report QueryDef first, OR create a temp table for each report that holds the data, or have fields on the selector form - have used all at one time or other. May have to, but seems there should be a way to a) OpenReport with conditions, b) keep report open without viewing OR printing, c) OutputTo a pdf (I've all sorts of functions that look at setting tables for destinations, etc.), d) close report - loop.
Any thoughts? May have to end up with temp tables (been there, done that a lot for other things), but these are NOT complicated reports - most look at a SQL view and apply the conditions. Don't wish to do through SSRS.
Thanks - Ben
I think something like this will work for you, surely by altering the parameters to meet your needs. this will create the reports silently, meaning, without prompting the users. Once the reports are created, you can complete whatever else you need to do:
Sub Test()
Const Param1 As Long = 1
Const Param2 As String = "x"
Const RptName As String = "r_t_test"
DoCmd.OpenReport RptName, acViewPreview, , ("[value1] = " & Param1 & " And [value2] = '" & Param2 & "'"), acHidden
DoCmd.OutputTo acOutputReport, RptName, acFormatPDF, CurrentProject.Path & "\" & RptName & ".pdf", False
DoCmd.Close acReport, RptName
End Sub

restart sequential numbering in access DB for new year

I have a simple access database that tracks projects. There's a SLR project number column that i have set up to automatically increment up. However I would like it to restart numbering back to 1 when the year changes. I have found several different discussions that talk about this and have tried to modify the code to fit my DB but i keep getting error messages. My form has fields linked to the underlying table for Start_Date and newLogNum. I added a button to the form to generate a new number with this code, which i found on another forum and modified to match my table and field names:
Private Sub cmdNewLogNum_Click()
If IsNull(Me.txtStart_Date) Then
MsgBox "Enter Date to generate number", vbOKOnly
Me.txtStart_Date.SetFocus
Else
Me.txtnewLogNum = Nz(DMax("[newLogNum]", "tblSLRTasks", "Year([Start_Date]) = " & Year(Me.[txtStart_Date])), 0) + 1
End If
End Sub
When I try to run this I first get an error message saying "Compile Error: Expected enf of statement" which hilights the second word in my msgbox code. So i tried removing all but one word withing the quotes within msgbox and then I get a compile error saying Sub or Function not defined for the first use of "Year" in the criteria statement. Can anyone help me fix this line of code so it will work? Thanks!
Most programming languages require double quotes like these: "". You seem to have typographic quotes: “”. Microsoft Access will require the first kind of double quotes.
The next step in troubleshooting Access native functions (VBA native functions) is usually to run them piece-by-piece in the Immediate Window. First evaluate Year([Start_Date]). Next, evaluate DMax("[newLogNum]", "tblSLRTasks", "Year([Start_Date]), etc.

Access form to run a query and display the results

I have a query in an MS Access database. How can I create a form that has a button to run the query and display the results in the same form, so that it looks more user friendly. (the result is only 5 records of a two column table)
I don't need a complete solution. Just some advice on the code for the button and the space to display the result.
I suggest using a subform with a continuous form to display the results. I guess the query is a select query of some description, to the record source of the subform can be set to the sql string:
strSQL="SELECT ID, Description, Count(SomeVal) " _
& "FROM Table " _
& "GROUP BY ID, Description " _
& "HAVING SomeVal=" & Me.txtSomeVal
Me.[Subform Control Name].Form.RecordSource = strSQL
Based on the answers, I guess don't I understand the question. It sounds like the OP has a DML query (or "action query" in Access terms) that modifies data and wants to display the results in a form. The current answers explain how to display the results, but not how to run the query.
So, here's an answer based on my interpretation of the question.
First, create a continuous or datasheet form that is bound to the results.
That's the easy part. The "hard" part is executing the SQL to do the updates the results of which you're going to display. You don't give any context for where you're launching this from, nor how you determine which particular records to update, so I'm going to give two fairly generic answers.
Method 1. create a macro with two parts:
the first command is OpenQuery and you'd supply the name of your saved query as the argument.
the second command is OpenForm that opens the form you created to display the results.
Now, I haven't supplied any method for executing the macro, but that's because you didn't supply any context.
Method 2. on a form from which it is appropriate to initiate this process:
create a comand button.
use the OnClick event to perform the desired action.
a. use the macro you wrote with Method 1 as the argument for the OnClick event of the command button.
b. write VBA code to do both tasks:
CurrentDB.Execute "MySaveQueryThatUpdatesData", dbFailOneError
DoCmd.OpenForm "MyFormThatDisplaysTheResults"
But this is all really begging the questions, as this is all pretty darned elementary. The hard part of this kind of thing comes about when your SQL update is operating on a subset of records and you need to display only that subset of records.
It is very likely that your original query will be keyed to the original context. Say, for instance, that you want to launch the entire process from a form that displays Companies and your SQL operates on the Employees of the currently displayed Company record. In that case, you'd want an update of the Employees table limited to the Company you're currently viewing. There are two ways to do that:
use a reference to the CompanyID in the Company form in the WHERE clause of your saved QueryDef:
UPDATE Employees
SET [blah, blah, blah]
WHERE Employees.CompanyID = Forms!Company!CompanyID
instead of using a saved QueryDef hardwired to require that your Company form be open for it to work, write the SQL on the fly in the code behind your command button:
Dim strSQL As String
strSQL = "UPDATE Employees "
strSQL = strSQL & "SET [blah, blah, blah] "
strSQL = strSQL & "WHERE Employees.CompanyID = "
strSQL = strSQL & Me!CompanyID
CurrentDB.Execute strSQL, dbFailOneError
Now, for the second part of it, you need to open the results form to display just those records that have been updated. That means you want the form opened with the same WHERE clause as was used for the update. There are two methods for this, too.
the first is very much like the the first method for performing the update, i.e., hardwiring the reference to the Company form in the WHERE clause of your results form's Recordsource's WHERE clause. So, the Recordsource for your results form would look like this:
SELECT Employees.*
FROM Employees
WHERE Employees.CompanyID = Forms!Company!CompanyID
Then you'd open the results form the same way as originally stated:
DoCmd.OpenForm "MyFormThatDisplaysTheResults"
the second approach avoids hardwiring the Recordsource of your results form to require the Company form be open, and instead, you just supply the WHERE clause (without the WHERE keyword) in the appropriate parameter of the OpenForm command:
DoCmd.OpenForm "MyFormThatDisplaysTheResults", , , "[CompanyID] = " & Me!CompanyID
Learning to do this is one of the most powerful and easy aspects of using Access, since you can create a form that returns all the records in a table, and then open that form and display subsets of data by supplying the appropriate WHERE parameter in the OpenForm command. Keep in mind that Access applies these very efficiently, that is, it doesn't open the form and load the entire recordset and then apply the WHERE argument to it, but applies the WHERE parameter to the recordsource before any records are loaded in the form.
Now, a consideration of what is the best way out of all the alternatives:
I would write the SQL on the fly for the update and use the WHERE parameter of the OpenForm command to do the filtering. So, in one of my apps, the code behind the OnClick event of your command button on the Company form would look like this:
Dim strSQL As String
strSQL = "UPDATE Employees "
strSQL = strSQL & "SET [blah, blah, blah] "
strSQL = strSQL & "WHERE Employees.CompanyID = "
strSQL = strSQL & Me!CompanyID
CurrentDB.Execute strSQL, dbFailOneError
DoCmd.OpenForm "MyFormThatDisplaysTheResults", , , "[CompanyID] = " & Me!CompanyID
Now, because of the dbFailOnError argument for CurrentDB.Execute, you'd need an error handler. And if you want to know how many records where changed, you'd need to use a database object other than CurrentDB, so more likely, I'd do it like this:
On Error GoTo errHandler
Dim strSQL As String
Dim db As DAO.Database
strSQL = "UPDATE Employees "
strSQL = strSQL & "SET [blah, blah, blah] "
strSQL = strSQL & "WHERE Employees.CompanyID = "
strSQL = strSQL & Me!CompanyID
Set db = CurrentDB
db.Execute strSQL, dbFailOneError
Debug.Print "Updated " & db.RecordsAffect & " Employee records."
DoCmd.OpenForm "MyFormThatDisplaysTheResults", , , "[CompanyID] = " & Me!CompanyID
exitRoutine:
Set db = Nothing
Exit Sub
errHandler:
MsgBox Err.Number & ": " & Err.Description, _
vbExclamation, "Error in Forms!Company!cmdMyButton.OnClick()"
Resume exitRoutine
My reason for constructing the SQL on the fly in the command button's OnClick event is so that it's very easy to add in more criteria should they become necessary. I like to avoid overloading my saved QueryDefs with dependencies on UI objects, so I will tend to write SQL like this on the fly in the place where it is being used.
Some people worry that this degrades performance because on-the-fly SQL is not optimized by your database engine's query optimizer. This may or may not be true. Many server database engines cache optimization plans of on-the-fly SQL commands, and because of the way Jet/ACE parses a SQL command like this and hands it off to the server, it is likely to be sent as a generic stored procedure. Because of that, a server like SQL Server will cache that query plan and be able to re-use it each time you execute the on-the-fly SQL, even if each time it has a different CompanyID value.
With a Jet/ACE back end, there is no caching like this, but the difference in execution time between the optimized and unoptimized SQL is going to be very small in all cases where you're not operating on really large datasets. And even updating, say, 1000 employee records is not something that counts as a large dataset for Jet/ACE. So I think there is seldom enough of performance hit from writing SQL on the fly to justify moving it to a saved QueryDef. However, on a case-by-case basis, I might very well choose to do so -- it would just not be my first choice.
The more significant objection, though, is that you'll have a bunch of SQL strings littered throughout your code, and this can become a maintenance nightmare. I don't know what to say about that, except that there are ways to handle that such that you eliminate as much duplication as possible, either by saving a base SELECT query as a saved QueryDef and using that such that the SQL you construct in code is unique only the parts specific to the action being taken in that particular case, or by using defined constants in your code that hold the base SQL statements that you use (such that you only have to change the definition of the constant to change the results anywhere it is used).
That's fairly weak, but with Access, I don't see any alternative. If you save every SQL statement as a QueryDef you end up with a different kind of unmanageable mess with too many saved queries, each slightly different from the other, and it can be just as duplicative as SQL repeated in code.
But that's another issue, and I probably shouldn't make this any longer by trying to resolve it here!

Resources