I have a form where there is string input that is an input to a parameter in a query (insert sql injection joke here), and a subform that displays the query's results.
Currently the parameter is essentially someVar Like "*" & forms!myForm!input & "*", but since the user can enter more than one string (i.e. a sentence) what I really want is someVar Like "*firstWord*" or someVar Like "*secondWord*"... etc
Since the number of parameters varies, I need to programatically generate the query. Looping through the words in the input and dynamically generating the where statement is not too hard in VBA:
dim sc as variant
sc=split(myInput)
dim where as string
where=""
for c=0 to UBound(sc)
where = where & "like '*" & sc(c) & "*' or "
next
where = left(where, len(where) - 3)
dim qd as querydef
set qd=currentDb.querydefs("myQuery")
qd.sql="select var where " & where
[my subform].requery
However, when I update the query, the subform that displays its data does not update even though I tell it to requery. If I leave the form and reenter it has the correct data. My approach seems to be wrong. What would be a better way to approach this?
I would have "myQuery" saved as the base query without any where criteria. Then you could go with:
[my subform].RecordSource = "select * from myQuery where somevar like '*" & replace(myInput, " ", "*' or somevar like '*") & "*'"
[my subform].Requery
This does away with needing to loop through the words in the input string and picks up on Andre's suggestion of modifying the RecordSource for the subform rather than trying to modify the query that the RecordSource is pointing to.
Related
i have created an access 2010 search box that filters results based on a column within a table and then presents me with the results based on query.
what i am trying to achieve is to be able to put not just one item at a time in the search box but multiple items.
this is for a whole estate of routers that i manage and every day i get a list of routers that need to be status checked so what i am doing now is copying and pasting each router name on the search box and it gives me the status, location and circuit ref but what i want to do i to copy and paste all of the router names in one go and get independent results for each router.
this is the code that i have applied for the filter in the text box:
Where Condition = [Circuit Reference] Like "*" & [Forms]![Query1]! [Text12] & "*"
i could add more text boxes and apply this filters to them but i would still have to copy and paste every router name independently.
i am not an access guru so appologies if this question is too easy to answer but i cant find anything on the web that helps me with my issue.
It sounds like you want multiple wildcard searches on the same field. You can do this by using OR in your SQL query.
Dim strSearchConditions As String
Dim strTerms() As String
Dim strSQL As String
Dim i as Integer
strSearchConditions = ""
strTerms = Split(Me.txtSearch,",") 'Assuming you separate your search terms with a comma
For i = 0 To UBound(strTerms)
If Not strTerms(i) = "" Then
strSearchConditions = " OR [Circuit Reference] Like '*" & strTerms(i) & "*'"
End If
Next i
If Not strSearchConditions = "" Then
strSQL = "Select * FROM tblMyTable WHERE 1=1 AND (" & strSearchConditions & ")"
Else
MsgBox "No search terms!"
End If
I think my first submission might have been a bit confusing so I decided to rewrite it to better explain what I am attempting to do.
I have an Access database. In it there are two combo boxes, one containing all possible forms of annuity (that I'm dealing with) and the other combo box is the ones the user populates that apply to that particular client. This master list is fed from a table (tblPickAnnuityForms). This table has 3 fields, Name, VarName (these values match to another table), and Deleted (is a 1 or a 0 depending on if the user selected it). I also have a second table called tblPlanSpecs. This table, among other fields, has the fields that match up to the VarName field in the first table.
What I need to do, since tblPickAnnuityForms is basically a temporary table and it changes as you move between records (clients), is to repopulate it when you go to that record based on the values in tblPlanSpecs. Once tblPickAnnuityForms is populated based on the previous elections for this record (client), the two combo boxes are re-queried to display the proper values (ie the left box shows the remaining, unused annuity forms and the right box shows the forms that apply to this client.
Below is my attempt at doing this.
Dim db As DAO.Database
Dim rsList As DAO.Recordset
Dim rsData As DAO.Recordset
Dim CurrForm As String
Dim FormVal As Integer
Dim Plan As String
Set db = CurrentDb
Set rsList = db.OpenRecordset("tblPickAnnuityForms", dbOpenSnapshot)
Plan = [Forms]![FrmHome]![PlanNameCalc].Value
Set rsData = db.OpenRecordset("SELECT tblPlanSpecs.LifeAnnuity, tblPlanSpecs.FiveCC, tblPlanSpecs.TenCC, " _
& "tblPlanSpecs.FifteenCC, tblPlanSpecs.TwentyCC, tblPlanSpecs.FiveCertain, tblPlanSpecs.TenCertain, " _
& "tblPlanSpecs.FifteenCertain, tblPlanSpecs.TwentyCertain, tblPlanSpecs.FiftyJS, tblPlanSpecs.SixtySixJS, " _
& "tblPlanSpecs.SeventyFiveJS, tblPlanSpecs.HundredJS, tblPlanSpecs.MCR FROM tblPlanSpecs " _
& "WHERE tblPlanSpecs.PlanName='" & Plan & "'")
Do
CurrForm = rsList.Fields("VarName")
FormVal = rsData.Fields(CurrForm)
DoCmd.RunSQL ("UPDATE tblPickAnnuityForms " _
& "SET tblPickAnnuityForms.Deleted=" & rsData! & FormVal & " " _
& "WHERE (((tblPickAnnuityForms.VarName)='" & CurrForm & "'))")
MsgBox (CurrForm & "changed to " & FormVal)
rsList.MoveNext
Loop Until rsList.EOF
If Not rsList Is Nothing Then
rsList.CLOSE
Set rsList = Nothing
End If
If there is a better solution, perhaps I can go in a different direction. Currently this is bombing out in the loop where it says rsData! & FormVal It does not like using a variable to call a field. Ideally I would like to avoid specifically calling every variable by name in code when populating rsData. In other words, I want this to work no matter how many other options I add to my master list for the combo box, without going back in to add more items to select query.
Please let me know if I am unclear in my intended direction or methods. I could really use the help figuring out what is wrong.
Well, it seems I solved my own problem. I had so many ideas running through my head, I half-implemented one and forgot. The variable FormVal was already pulling the value I needed from rsData. I then tried to pull the value again using FormVal as the field variable. Anyway, below was the simple solution and everything works now.
DoCmd.RunSQL ("UPDATE tblPickAnnuityForms " _
& "SET tblPickAnnuityForms.Deleted=" & FormVal & " " _
& "WHERE (((tblPickAnnuityForms.VarName)='" & CurrForm & "'))")
In other words, I didn't need to do rsData![ & FormVal & ] (which I am sure is improper syntax) I just needed to use FormVal by itself.
I am using an Access2010 project as frontend, referring to a MS SQL Server 2008 as backend. Within my Access project there is form frmKlientenÜbersicht. This form has a view abfKlientenÜbersicht as dataSource.
Now I am trying to get the current number of records showing up in my form by using this code:
Private Sub Form_Current()
Debug.Print "Form_Current: " & anzahlDatensätze
lblAnzahlDatensätze.Caption = anzahlDatensätze & " Klient(en)"
End Sub
Private Function anzahlDatensätze() As Integer
Dim rs As Recordset
Set rs = Me.RecordsetClone
rs.MoveLast
anzahlDatensätze = rs.RecordCount
End Function
This works fine until I am using some filters. If I am using any filter on my form, the number of records stays unchanged!
What do I have to change to get the current number of records showing up (if filtered or not)?
What is the reason why my code does not show the correct number of records?
EDIT: According to the given comments and answers I tried setting Count([pkKlient] onto a textbox (see new pic) and tried DCount("*", "abfKlientenÜbersicht", me.Filter) from within VBA Code.
Unfortunatelly it seems that the filterClause is not valid when using it as parameter value for DCount. (see pic for filterClause).
As you can see count(..) does not result in a correct number - and the filterClause (generated by access!!) seems not to be valid for use by DCount(..)
If someone wants to try it, on your own, just create an ADP, add a form, add a view, form dataSource is a view, set a filter, and try to get the number of records?!!
Looking forward for any comments/answers/hints!
with VBA, DCount will give you what you need
DCount("*", "MyTable", Me.Filter)
If you want to put this on the form, there's an easier way. use an unbound box, and set it to =count([FieldName])
This count should remain correct, regardless of if it's counted filtered records or not.
Some notes, there are a dozen things that could go wrong with this, it could hardly even be called tested. However, it was returning the correct count for me.
Apparently, the form filter just hides records, whereas this will apply a real filter. However, you need to get the format into the right shape for a valid filter. In the end, a WHERE statement would probably be easier.
Private Sub Form_ApplyFilter(Cancel As Integer, ApplyType As Integer)
With Me.Recordset
''Filter
If ApplyType = 1 Then
''Very, very roughly. Remove form name, use single quotes
''You will need a lot more code for safety
sfilter = Replace(Me.Filter, "[" & Me.Name & "].", "")
sfilter = Replace(sfilter, """", "'")
.Filter = sfilter
MsgBox "Recordset : " & Me.Recordset.RecordCount & vbCrLf _
& "Filtered : " & .RecordCount
Else
''Remove filter - ApplyType 0
.Filter = ""
End If
End With
End Sub
Additional note with similar caveats
You can also set a textbox to something on these lines:
=IIf([FilterOn]=True,DCount("id","ATable",
Replace(Replace([Filter],"[" & [Name] & "].",""),"""","'")),Count([id]))
(Remove the break in the line, it is cosmetic)
I more or less need to add this as a filter option of a calculated field. It's on a form with a search function that runs a query. I'm attempting to consolidate all the queries from the previous creator into one query. This is the only step I'm missing.
If I made that control a combo box and put as the row source
<5;<15;<30
Ideally, I'd like it to be <5; 15>x>5; 30>x>15 but I'm not sure how I can write that where the query can see if it's like that control.
Criteria Like "*" & [Forms]![FRM_SearchMulti]![txtClosing] & "*"
I reckon you can build the string in VBA for speed, or use a UDF if you do not care about related queries failing or speed.
Dim qdf As queryDef
Set qdf = CurrentDB.QueryDefs("TempQuery") ''TempQuery must exist
sSQL = "SELECT * FROM Table WHERE ANumber " & Me.MyCombo
qdf.SQL = sSQL
DoCmd.OpenQuery qdf.Name
Or there abouts.
I have a main form, frm_Main, and it has a subform in it, subform_Child. When the main form is displayed the subform is shown as well, it's just blank because there's no data in it (which is perfectly fine). When the user clicks a button on the main form the code builds a SQL string that contains a WHERE clause based upon what the user has entered in a text box. So far so good, I've done this before. Now the part that I cannot figure out (because I haven't done it before) is populating that subform using the SQL just created! Building the SQL string is no problem, I just don't know Access VBA well enough to know what code to use to update the subform from the main form and have it display the recordset after the query runs.
Edit: It's my understanding that using a QueryDef isn't a recommended method, correct?
Here's what I did as it seems to be the only way to do it.
1) Built a query named "zqry_PlaceHolder". In my case this is the data set that is being used (only the WHERE will change). I did add a WHERE clause in this (WHERE dbo_project.projectid = "_") but only so it would return nothing so as not to delay the displaying of the main form.
2) In the subform set the Source Object to the query I just built, "Query.zqry_PlaceHolder". This is required.
3) When the user clicks the button on the main form the VBA code is run. It creates the WHERE clause in the string variable sWhereFilter and then adds it to the SQL string:
'Build SQL string
sSQL = Empty 'Ensure string is empty
sSQL = "SELECT Proj_Locs.ProjectID, dbo_PROJECTS.PROJECTID, Proj_Locs.Location, Master_Scans.FileName, Proj_Locs.Title, dbo_PROJECTS.TITLE" & vbCrLf
sSQL = sSQL & "FROM (tbl_Project_Locations AS Proj_Locs" & vbCrLf
sSQL = sSQL & " LEFT JOIN dbo_PROJECT AS dbo_PROJECTS ON Proj_Locs.ProjectID = dbo_PROJECTS.PROJECTID)" & vbCrLf
sSQL = sSQL & " LEFT JOIN tblMasterScans AS Master_Scans ON Proj_Locs.ProjectID = Master_Scans.Project" & vbCrLf
sSQL = sSQL & sWhereFilter
sSQL = sSQL & "ORDER BY Proj_Locs.ProjectID ASC, dbo_PROJECTS.PROJECTID ASC;"
Then I throw up a "Please wait" form to let the user know things are processing and set the RecordSource of the subform to the built SQL string:
DoCmd.OpenForm "frm_PleaseWait", acNormal
DoCmd.Hourglass True
DoCmd.RepaintObject acForm, "frm_PleaseWait" 'Needed to show everything in the form immediately, otherwise there's a delay
Me.subform_Results.Form.RecordSource = sSQL 'This updates the subform AND executes it, refreshing the results
Beep 'Let user know processing completed
Me.txt_RecordsReturned = Me.subform_Results.Form.Recordset.RecordCount 'Let user know how many records were returned with their query (if any)
This works and it does not change the placeholder query "zqry_PlaceHolder".
I hope this helps others as it wasn't as intuitive to me. If there is another/better method I'm all for learning something new!