I'm writing an Access database. I have a number of forms that are identical. These are used to edit look up lists for different fields in my main contacts table.
e.g. there is a company field and a country field. The forms that open for each editable list are identical with repeat vba code in each becasue I cannot work out how to reference the active table from the active form.
The code I currently have for clearing all the yes/no boxes in the table is:
Private Sub cmdClearTicks_Click()
Dim db As Database
' Dim sel As Control
Set db = CurrentDb
' Clear all ticks of selected records
db.Execute "UPDATE ContactCompany " _
& "SET Selected = null "
' Update Selected Field
Me.Requery
End Sub
ContactCompany is the name of the table. I would like to be able to set this sub globally but cannot work out what I should replace ContactCompany with to reference the table in the currently open form. I've already tried Me.RecordSource which does not work.
I'm very grateful for what I assume is a very easy fix!
Sean posted a great fix below. I'm now stumped with including a filter too and defining it globaly.
Sub SelectFiltered(RS As String)
Dim strFilter As String
Dim strSQl As String
If InStr(RS, "FROM") Then
RS = Mid(RS, InStr(RS, "FROM") + 5)
If InStr(RS, " ") Then RS = Left(RS, InStr(RS, " ") - 1)
End If
strFilter = Me.Filter
If Me.FilterOn = False Then
'Select Case MsgBox("No search or filter applied.", vbCritical + vbOKOnly, "Warning")
'End Select
strSQl = "UPDATE " & RS & " " & _
"SET Selected = 1 "
Else
strSQl = "UPDATE " & RS & " " & _
"SET Selected = 1 " & _
"WHERE " & strFilter
End If
DoCmd.SetWarnings False
DoCmd.RunSQL strSQl
DoCmd.SetWarnings True
End Sub
Me.filter doesn't work in the global sub. Sean - I'm sure you'll have an answer for this in a sec. Thanks again!
you are close with using Me.Recordsource
db.Execute "UPDATE " & Me.Recordsource & " SET Selected = null "
or, if you want it as a global function, pass Me.Recordsource to it
Sub ClearTicks(RS as string,StrFilter as string)
Dim db As Database
Set db = CurrentDb
If InStr(RS, "FROM") Then
RS = Mid(RS, InStr(RS, "FROM") + 5)
If InStr(RS, " ") Then RS = Left(RS, InStr(RS, " ") - 1)
End If
' Clear all ticks of selected records
db.Execute "UPDATE " & RS & " SET Selected = null "
If StrFilter="" then 'no filter
Else 'filter
End If
End Sub
and your calling function would be:
Private Sub cmdClearTicks_Click()
ClearTicks Me.Recordsource,Me.Filter
Me.Refresh
End Sub
If you want a more reusable function method that could be expanded more easily, then call the sub/function with Me.Name as the parameter (e.g. MySub Me.Name) and then in your reusable function:
sub MySub(FrmName as string)
Forms(FrmName).Filter
Forms(FrmName).Recordsource
Forms(FrmName).AnyOtherParamater
Related
All I really need to know is how to make it where I can make selections in multiple multi-select listboxes, but leave any number of them blank and still have the macro/query work without having to put in an error message about it.
This also includes doing the same with the textboxes. The textboxes would function the same as the listboxes where they would search for anything in a data table to matches what I am looking for in the records and display what I am looking for in a table.
Here is my code
Private Sub Command62_Click()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim varItem As Variant
Dim District As String
Dim Circumstance As String
Dim Location As String
Dim Method As String
Dim Point As String
Dim Rank As String
Dim strSQL As String
Set db = CurrentDb()
Set qdf = db.QueryDefs("qryMultiselect")
For Each varItem In Me!District.ItemsSelected
District = District & ",'" & Me!District.ItemData(varItem) & "'"
Next varItem
If Len(District) = 0 Then
MsgBox "You did not select anything in the Distrcit field." _
, vbExclamation, "Nothing to find!"
Exit Sub
End If
District = Right(District, Len(District) - 1)
For Each varItem In Me!Circumstance.ItemsSelected
Circumstance = Circumstance & ",'" & Me!Circumstance.ItemData(varItem) &
"'"
Next varItem
If Len(Circumstance) = 0 Then
MsgBox "You did not select anything in the Circumstance field." _
, vbExclamation, "Nothing to find!"
Exit Sub
End If
Circumstance = Right(Circumstance, Len(Circumstance) - 1)
For Each varItem In Me!Location.ItemsSelected
Location = Location & ",'" & Me!Location.ItemData(varItem) & "'"
Next varItem
If Len(Location) = 0 Then
MsgBox "You did not select anything in the Location field." _
, vbExclamation, "Nothing to find!"
Exit Sub
End If
Location = Right(Location, Len(Location) - 1)
For Each varItem In Me!Method.ItemsSelected
Method = Method & ",'" & Me!Method.ItemData(varItem) & "'"
Next varItem
If Len(Method) = 0 Then
MsgBox "You did not select anything in the Method field." _
, vbExclamation, "Nothing to find!"
Exit Sub
End If
Method = Right(Method, Len(Method) - 1)
For Each varItem In Me!Point.ItemsSelected
Point = Point & ",'" & Me!Point.ItemData(varItem) & "'"
Next varItem
If Len(Point) = 0 Then
MsgBox "You did not select anything in the Point field." _
, vbExclamation, "Nothing to find!"
Exit Sub
End If
Point = Right(Point, Len(Point) - 1)
For Each varItem In Me!Rank.ItemsSelected
Rank = Rank & ",'" & Me!Rank.ItemData(varItem) & "'"
Next varItem
If Len(Rank) = 0 Then
MsgBox "You did not select anything in the Rank field." _
, vbExclamation, "Nothing to find!"
Exit Sub
End If
Rank = Right(Rank, Len(Rank) - 1)
strSQL = "SELECT * FROM tblDataEntry " & _"WHERE tblDataEntry.District
IN(" & District & ") AND tblDataEntry.Circumstance IN(" & Circumstance &
") AND tblDataEntry.Location IN(" & Location & ") AND tblDataEntry.Method
IN (" & Method & ") AND tblDataEntry.Point IN (" & Point & ") AND
tblDataEntry.Rank IN(" & Rank & ");"
qdf.SQL = strSQL
DoCmd.OpenQuery "qryMultiselect"
Set db = Nothing
Set qdf = Nothing
End Sub
I still need to add the textboxes, but I'm not sure where. (Please note that I'm still learning VBA).
Firstly, since you are repeatedly performing the same operation for each form control (in this case, constructing a comma-delimited string from the selected items), you can abstract this operation away into a function, and pass such function each List Box function.
For example, you could define a function such as:
Function SelectedItems(objBox As ListBox) As String
Dim strRtn As String, varItm
For Each varItm In objBox.ItemsSelected
strRtn = strRtn & ",'" & objBox.ItemData(varItm) & "'"
Next varItm
If strRtn <> vbNullString Then SelectedItems = Mid(strRtn, 2)
End Function
Which could then be evaluated with a List Box control argument, and would return either a null string ("") or a comma-delimited string of the selected items in the list box, e.g. something like:
?SelectedItems(Forms!Form1!List1)
'A','B'
Furthermore, since your form controls appear to be named consistently relative to the fields in your table, you could further condense your code to something along the following lines:
Private Sub Command62_Click()
Dim strSQL As String
Dim strArr As String
Dim varItm
For Each varItm In Array("District", "Circumstance", "Location", "Method", "Point", "Rank")
strArr = SelectedItems(Me.Controls(varItm))
If strArr <> vbNullString Then
strSQL = strSQL & "t." & varItm & " in (" & strArr & ") and "
End If
Next varItm
If strSQL <> vbNullString Then strSQL = "where " & Left(strSQL, Len(strSQL) - 5)
With CurrentDb.QueryDefs("qryMultiselect")
.SQL = "select * from tblDataEntry t " & strSQL
End With
DoCmd.OpenQuery "qryMultiselect"
End Sub
Note that the above is entirely untested.
Here, the main for each loop iterates over an array of strings corresponding to the names of your form controls and the names of your table fields.
For each form control in this array, the function obtains a comma-delimited string of the selected items in the control, and concatenates this with the existing SQL code only if one or more items have been selected.
As such, if not items are selected, the field will not feature in the SQL where clause.
If any filter has been selected, the trailing five characters (and) are trimmed from the end of the SQL string, and the where keyword is concatenated to the start of the SQL string - this ensures that if no filter has been selected, the resulting SQL code will not include a where clause.
Finally, the SQL for the query definition is updated and the query is opened, per your original code.
Where textboxes are concerned, the task merely need to skip the call to SelectedItems and obtain the value of the textbox directly.
Here is an example incorporating both listboxes & textboxes:
Private Sub Command62_Click()
Dim strSQL As String
Dim strArr As String
Dim varItm
For Each varItm In Array("District", "Circumstance", "Location", "Method", "Point", "Rank")
strArr = vbNullString
Select Case Me.Controls(varItm).ControlType
Case acListBox
strArr = SelectedItems(Me.Controls(varItm))
Case acTextBox
If Not IsNull(Me.Controls(varItm).Value) Then
strArr = "'" & Me.Controls(varItm).Value & "'"
End If
End Select
If strArr <> vbNullString Then
strSQL = strSQL & "t." & varItm & " in (" & strArr & ") and "
End If
Next varItm
If strSQL <> vbNullString Then strSQL = "where " & Left(strSQL, Len(strSQL) - 5)
With CurrentDb.QueryDefs("qryMultiselect")
.SQL = "select * from tblDataEntry t " & strSQL
End With
DoCmd.OpenQuery "qryMultiselect"
End Sub
I hope this helps, but please note that the above is untested and only theory.
I am getting an "Object variable or With block variable not set (Error 91)" error with the following code:
Dim db As Database
Dim rs As Recordset
Private Sub Form_Load()
Dim mySQL As String
mySQL = "SELECT Tuteurs.ID_Tuteur, Tarifs_17_18.*, Paiements_17_18.* " & _
"FROM (Tuteurs INNER JOIN Tarifs_17_18 ON Tuteurs.ID_Tuteur = Tarifs_17_18.TuteurID_Trf) " & _
"INNER JOIN Paiements_17_18 ON Tuteurs.ID_Tuteur = Paiements_17_18.TuteurID_Pmt " & _
"WHERE ID_Tuteur =" & [Forms]![Eleves]![TuteurID_Elv]
Set db = CurrentDb
Set rs = db.OpenRecordset(mySQL, dbOpenDynaset, dbSeeChanges)
rs.MoveFirst
End Sub
Private Sub btn_Enregistrer_Click()
Dim totIns As Integer
totIns = DSum("Montant", "Paiements_17_18", "[Mois_Regle]='Inscription'")
If totIns = rs!Tarif_Inscription Then
MsgBox "Yes" & totIns & " = " & rs!Tarif_Inscription
Else
MsgBox "No" & totIns & " # " & rs!Tarif_Inscription
End If
End Sub
totIns is working very well but rs!Tarif_Inscription is the missing object variable.
[Tarif_Inscription] is a field in the [Tarifs_17_18] Table.
Any Help Please?
I Found the Solution,
My recordset is not in scope and My variables are declared outside My procedure.
Solution found by #Moke123.
I have a database where i can add a full name of a person, and i am trying to implement a search function using a textBox and a button but i only want to search for the first or last name not necessarily entering the full name.
I tried using SELECT FROM WHERE CONTAINS like this:
OleDbCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM Table WHERE CONTAINS (column, '"+textBox.Text+"')";
But i keep getting this error:
Syntax error (missing operator) in query expression 'CONTAINS (column,'the text i tried to search')'.
I also tried changing the + to % or * or & but still it didn’t work.
Contains is not valid Access SQL. Use Like:
cmd.CommandText = "SELECT * FROM Table WHERE [YourNameField] Like '*" + textBox.Text + "*')";
Here is an example of a search such as you want:
Private Sub cmdFind_DisplayName_Click()
Dim dbs As Database, rstPatient As Recordset
Dim txtDisplayName, strQuote As String
strQuote = Chr$(34)
On Error GoTo ErrorHandler
Me.OrderBy = "DISPLAYNAME"
Me.OrderByOn = True
Set dbs = CurrentDb
Set rstPatient = Me.RecordsetClone
txtDisplayName = Trim(InputBox("Please Enter Patient Name ", "Patient Find By Name"))
txtDisplayName = UCase(txtDisplayName) & "*"
If IsNull(txtDisplayName) Then
MsgBox ("No Patient Name Entered - Please Enter a Valid Patient Name")
Else
rstPatient.FindFirst "[DISPLAYNAME] Like " & strQuote & txtDisplayName & strQuote
If Not (rstPatient.NoMatch) Then
Me.Bookmark = rstPatient.Bookmark
Me.Refresh
Else
MsgBox ("Patient Not Found - Please Enter a New Patient Name")
End If
End If
GoTo Exit_cmdFind_Click
ErrorHandler:
MsgBox LTrim(RTrim(Me.NAME)) + "." + "Patient Find By Display Name - " + "Error: " + AccessError(Err.Number)
Exit_cmdFind_Click:
rstPatient.Close
Set dbs = Nothing
Set rstPatient = Nothing
End Sub
Create 1 textbox (txtMain) and search command button(btnSearch) to execute SQL. Then add a listbox (listResult) to display results.
Private Sub btnSearch_Click()
Dim mainSQL As String
mainSQL = " SELECT YOUR_FIELD_NAME " & _
" FROM MasterReg " & _
" WHERE Left(,InStr(YOUR_FULL_NAME_FIELD,' ')-1) LIKE '" & me.txtMain & "*'" & _ ' Firstname Search
" OR RIGHT( YOUR_FULL_NAME_FIELD,Len( YOUR_FULL_NAME_FIELD )-InStr( YOUR_FULL_NAME_FIELD,' ')) LIKE '" & me.txtMain & "*'" 'Surname Search
Me.listResult.SetFocus
Me.listResult.RowSource = mainSQL
Me.listResult.Requery
End Sub
I have a master form which contains three list boxes and one sub form. I would like to build a routine which allows me to switch links between the sub form and the three list boxes. Is this possible? Or do i have to create three copies of the same sub form and hide two while one the other is activated?
To be practical, my form will work like this: The sub form contains a list of records of people participating in a project, their specific role, and which internal team they come from. I would like to use three list boxes to allow the user to filter this form by either:
(1) All participants coming from a certain team
(2) All participants by roles (titles)
(3) Filter by name of particants
Where I am short is on how to re-link the filter on the sub form so that it changes from list box to list box as the user passes from filter to filter.
Using Krish's suggestion below as a simple test i am trying the following code but am getting a compilation error message on the recordsource line stating that it is impossible to find the method or the data member.. Not sure what that means:
Private Sub lstRoles_AfterUpdate()
Dim SQL_GET As String
SQL_GET = "SELECT * from tblProjectGovernanceResources where ((role like '" & lstRoles.Value & "')"
Me.frmProjectGovernanceResources.RecordSource = SQL_GET
End Sub
you can retrieve the selected value from a listbox simply byt listbox1.value.
As Wayne G pointed. you would add a code in your listbox_after_update event to update your subform's recordsource.
something like:
dim SQL_GET as string
sql_get = "SELECT * from tbl_myTAble where ((condition like '" & listbox1.value & "') OR (condition2 like '"& listbox2.value &"') OR (condition3_number like "& listbox3.value &"))
me.mysubform.recordsource = sql_Get
obviously you need to improve this as per your requirements.
Try this and for a better answer, produce what you have coded so far..
I created some code for the easiest version possible. This means all of your listboxes have the 'multi select' property set to 'None' (this means you can't select multiple items in the list and you can't 'deselect' an item by clicking on it again. I did add some code at the end so you can see how a different multi-select option may work.
My form has three listboxes, a subform, and two buttons. One button will clear all selections in all listboxes. The other button applies the filter to the subform.
Option Compare Database
Option Explicit
'*** NOTE!!! THIS CODE ASSUMES YOU HAVE SET YOUR LISTBOX PROPERTY to 'NONE'.
' IF YOU SET 'MULTI SELECT' To 'SIMPLE' or 'EXTENDED', you MUST use different code to find all selected items.
Dim strWhereTeam As String
Dim strWhereRole As String
Dim strWhereParticipant As String
Private Sub cmdClear_Click()
' Clear all selections in all listboxes
Dim i As Integer
For i = 0 To Me.lstParticipant.ListCount 'Deselect ALL rows in Listbox
lstParticipant.Selected(i) = False
Next i
For i = 0 To Me.lstRole.ListCount 'Deselect ALL rows in Listbox
lstRole.Selected(i) = False
Next i
For i = 0 To Me.lstTeam.ListCount 'Deselect ALL rows in Listbox
lstTeam.Selected(i) = False
Next i
strWhereTeam = ""
strWhereRole = ""
strWhereParticipant = ""
Me.MySubForm.Form.Filter = "" ' Reste filter to NONE
Me.MySubForm.Form.FilterOn = False
End Sub
Private Sub cmdFilter_Click()
'Build Filter (concatenate three selections)
Dim strFilter As String
strFilter = ""
If strWhereTeam & "" <> "" Then
strFilter = strWhereTeam
If strWhereRole & "" <> "" Then
strFilter = strFilter & " AND " & strWhereRole
If strWhereParticipant & "" <> "" Then
strFilter = strFilter & " AND " & strWhereParticipant
End If
Else
If strWhereParticipant & "" <> "" Then
strFilter = strFilter & " AND " & strWhereParticipant
End If
End If
ElseIf strWhereRole & "" <> "" Then
strFilter = strWhereRole
If strWhereParticipant & "" <> "" Then
strFilter = strFilter & " AND " & strWhereParticipant
End If
ElseIf strWhereParticipant & "" <> "" Then
strFilter = strWhereParticipant
End If
If strFilter = "" Then
Me.MySubForm.Form.Filter = ""
Me.MySubForm.Form.FilterOn = False
Else
Me.MySubForm.Form.Filter = strFilter
Me.MySubForm.Form.FilterOn = True
End If
End Sub
Private Sub lstParticipant_Click()
strWhereParticipant = "[Participant] = '" & Me.lstParticipant.ItemData(Me.lstParticipant.ListIndex) & "'"
Debug.Print strWhereParticipant
End Sub
Private Sub lstRole_Click()
strWhereRole = "[Role] = '" & Me.lstRole.ItemData(Me.lstRole.ListIndex) & "'"
Debug.Print strWhereRole
End Sub
Private Sub lstTeam_Click()
If Me.lstTeam.MultiSelect <> 0 Then
MsgBox "You have set the 'Multi Select' property to either Simple or Extended. This code may not work!", vbOKOnly + vbCritical, "ListBox MultiSelect not 'None'"
End If
strWhereTeam = "[Team] = '" & Me.lstTeam.ItemData(Me.lstTeam.ListIndex) & "'"
Debug.Print strWhereTeam
'Simple_Code
End Sub
'' Sample code if set 'Multi Select' to 'Simple' or 'Extended'
'Sub Simple_Code()
' Dim var As Variant
' strWhereTeam = ""
' For Each var In Me.lstTeam.ItemsSelected
' strWhereTeam = strWhereTeam & "[Team] = '" & Me.lstTeam.ItemData(var) & "' OR "
' Next var
' strWhereTeam = "(" & left(strWhereTeam, Len(strWhereTeam) - 4) & ")"
' Debug.Print strWhereTeam
'End Sub
Thanks a lot! This did it all!
Private Sub lstRoles_AfterUpdate()
Dim SQL_GET As String
SQL_GET = "SELECT * from tblProjectGovernanceResources where ([role] = '" & lstRoles.Value & "')"
Me.frmProjectGovernanceResources.Form.RecordSource = SQL_GET
End Sub
Copy from: https://softwareengineering.stackexchange.com/questions/158330/cascading-comboboxes
ok so i have a form, in Access 2010, with 1 Textbox and 3 ComboBoxes (1 Enabled & 2 Disabled).
the first ComboBox is not tied to the datasource but is subjective to the other 2 comboboxes. So i handled the Click event for the first Combobox to then make the other 2 enabled, and preload the 2nd ComboBox with a custom RowSource SQL Script dynamically built based on the 1st ComboBox Value.
This all works great for New information but when i goto review the information, via Form, its back to the New mode on the controls.
Question:
What event do i need to handle to check if the current Form Data contains data for the Control Source of the Controls?
As i would express it in Logic (its a mix between C & VB, i know but should get the pt acrossed):
DataSet ds = Form.RowSet
if (ds = Null) then
cbo2.enabled = false
cbo3.enabled = false
else
cbo2.rowsource = "select id, nm from table"
cbo2.value = ds(3)
cbo3.value = ds(4)
end if
... do some other logic ...
Updated Logic - Still problem, cant catch for RecordStatus for some reason (gives 3251 Run-Time Error)
Private Sub Form_Current()
Dim boolnm As Boolean: boolnm = (IsNull(txtName.Value) Or IsEmpty(txtName.Value))
Dim booltype As Boolean: booltype = IsNull(cboType.Value)
Dim boolfamily As Boolean: boolfamily = IsNull(cboType.Value)
Dim boolsize As Boolean: boolsize = IsNull(cboType.Value)
Dim rs As DAO.Recordset: Set rs = Me.Recordset
MsgBox rs.AbsolutePosition
' If rs.RecordStatus = dbRecordNew Then
' MsgBox "New Record being inserted, but not committed yet!", vbOKOnly
' Else
' MsgBox rs(0).Name & " - " & rs(0).Value & vbCrLf & _
' rs(1).Name & " - " & rs(1).Value & vbCrLf & _
' rs(2).Name & " - " & rs(2).Value & vbCrLf & _
' rs(3).Name & " - " & rs(3).Value
' End If
'MsgBox "Name: " & CStr(boolnm) & vbCrLf & _
"Type: " & CStr(booltype) & vbCrLf & _
"Family: " & CStr(boolfamily) & vbCrLf & _
"Size: " & CStr(boolsize), vbOKOnly
End Sub
Here is the final result, with Remou's assistance, and this is only a precursor to the end result (which is out of the context of the question).
Private Sub Form_Current()
If Me.NewRecord Then <=======================
cboType.Value = 0
cboType.Enabled = True
cboFamily.Enabled = False
cboSize.Enabled = False
Else
Dim rs As DAO.Recordset: Set rs = Me.Recordset
'get Family ID
Dim fid As String: fid = rs(2).Value
'Build SQL Query to obtain Type ID
Dim sql As String
sql = "select tid from tblFamily where id = " & fid
'Create Recordset
Dim frs As DAO.Recordset
'Load SQL Script and Execute to obtain Type ID
Set frs = CurrentDb.OpenRecordset(sql, dbOpenDynaset, dbReadOnly)
'Set Type ComboBox Value to Type ID
cboType.Value = frs(0)
cboType_Click 'Simulate Click Event since the Value has changed
'Make sure all 3 Comboboxes are enabled and useable
cboType.Enabled = True
End If
End Sub