How to set controlsource of a textbox from SQL - sql

I have a subform bound to a SQL statement. Inside the subform, I have a few text boxes bound to the fields of this SQL. However, I have another text box that needs to be bound to a field from a different SQL statement with criteria from the first one. My code looks like below:
Dim subform As Object
Dim formFilter As String
formFilter = "SELECT * FROM my_table_1"
Set subform = Me!my_subform.Form
subform.RecordSource = formFilter
subform.field1.ControlSource = "tb1f1"
subform.field2.ControlSource = "tb1f2"
...
subform.f3.ControlSource = "= SELECT TOP 1 tb2f3 FROM my_table_2 WHERE tb2f1 = '" & [tb1f1] & "' AND tb2f2 = '" & [tb1f2] "' ORDER BY tb2f4"
I cannot use a DLOOKUP function here directly, because I need to sort the table result.
Thanks in advance for your help.

I think I would simply create a little function to go get the result you want. It would probably be best to simply rework DLookup in your own function and add sort but I won't do that here.
First the form code. Notice I am not setting the recordsource, just the value which may not be what you want.
subform.f3 = fGet_tb2f3([tb1f1], [tb1f2])
Then the function code (put in your own error handling)
Public Function fGet_tb2f3(tblf1 as String,tblf2 as String) as String
Dim rst as dao.recordset
Dim db as database
set db = currentdb
set rst = db.openrecordset("SELECT TOP 1 tb2f3 FROM my_table_2 WHERE tb2f1 = '" & tb1f1 & "' AND tb2f2 = '" & tb1f2 "' ORDER BY tb2f4",dbopensnapshot
if not rst is nothing then
if not rst.eof then fGet_tb2f3 = rst!tb2f3
rst.close
set rst = nothing
end if
db.close
set db = nothing
end Function

You can't bind controls on the same form to 2 different recordsets. The only thing you could do is pull data from 2 different recordsets, but that's probably not the best way to do anything.
In order to do that, you'd have to create a second recordset and grab that value in it. Something like:
Dim db as Database
Dim rec as Recordset
Set db = CurrentDB
Set rec = db.OpenRecordset("SELECT TOP 1 tb2f3 FROM my_table_2 WHERE tb2f1 = '" & [tb1f1] & "' AND tb2f2 = '" & [tb1f2] "' ORDER BY tb2f4")
Me.MyControlName = rec(0)

Related

dbOpenDynaset - 'Object variable or With block variable not set'

I have a query called 'qryAddressBook'. I want to be able to loop vertically through the records in a specific field called 'Client_Address' and display those records on a single row in a table 'tblClient'.
I have done this in the past with tables using "Set rs = dbs.OpenRecordset("tblAddressBook", dbOpenTable)" with no issues....
...and I followed the syntax showed from Access Database.OpenRecordset method (DAO): https://learn.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/database-openrecordset-method-dao
I continue to get an error that says, 'Object variable or With block variable not set' and it highlights the following text from my code:
Set rs = dbs.OpenRecordset("qrySpecificNCR", dbOpenDynaset)
Here is my total code:
DoCmd.OpenQuery "qryAddressBook"
Dim dbs As DAO.Database
Dim rs As Recordset
Dim SeqNum As Integer
Set dbs = CurrentDb
SeqNum = 1
Set rs = dbs.OpenRecordset("qryAddressBook", dbOpenDynaset)
Do Until rs.EOF
Dim srtAddress As String
srtAddress = rs.Fields("Client_Address").Value
Dim strSQLAddress As String
strSQLAddress = "UPDATE tblClient SET " & SeqNum & " = '" & srtAddress & "' WHERE Record = 1;"
DoCmd.RunSQL strSQLAddress
SeqNum = SeqNum + 1
rs.MoveNext
Loop
I still don't understand the explicit part...but I found the error.
My qryAddressBook had the following line of code:
FROM qryGlobalAddress
WHERE (((qryAddress.Client) = [FORMS]![frmClientAddress]![CmbClientName]));
I was pushing a form parameter from a combo box. When I changed this to a specific client name such as:
FROM qryGlobalAddress
WHERE (qryAddress.Client) = 'Smith, John';
Then the Set rs = dbs.OpenRecordset("qryAddressBook", dbOpenDynaset) worked perfectly.
The problem now is I'll need to figure out a way to push a form parameter to the query. :(
cancatenate the form combo value
"FROM qryGlobalAddress WHERE (((qryAddress.Client) = '" & [FORMS]![frmClientAddress]![CmbClientName] & "'));"

How to populate a ComboBox with query results

I had a problem populating a ComboBox from query results in access vba. My goal was to query for one column of a table and use every record from the result as an option for the combobox.
There are some things about the properties of ComboBoxes you need to be aware of and assign properly to make this work. Here's my code that seemed to hold the correct information but did not display anything in the dropdown list:
Dim RS As DAO.Recordset
Dim SQL As String
'Clean-up. not sure if it's needed but I'm "clearing" the old data (if there's any) before putting the new in
combox.RowSourceType = "Table/Query"
combox.RowSource = ""
SQL = "SELECT [some_value] FROM [a_table] WHERE [another_value] = '" & argv(0) & "'"
combox.RowSource = SQL
This was part of another question I asked but for clearer structure I'm moving this question (and it's answer) to this thread.
Your first attempt is fine, you just need to requery the combo box to actually load in the results of the query.
Dim SQL As String
combox.RowSourceType = "Table/Query"
combox.RowSource = ""
SQL = "SELECT [some_value] FROM [a_table] WHERE [another_value] = '" & argv(0) & "'"
combox.RowSource = SQL
combox.requery 'Clears old data, loads new data
After some refactoring and fixing I came to this result which makes the ComboBox behave as I intend:
combox.RowSourceType = "Value List"
combox.RowSource = ""
SQL = "SELECT [some_value] FROM [a_table] WHERE [another_value] = '" & argv(0) & "'"
With combox
.RowSource = kombSQL
.ColumnCount = 2
.ColumnWidth = 1
.ColumnWidths = "1.5in."
End With
Set RS = CurrentDb.OpenRecordset(SQL)
RS.MoveLast
RS.MoveFirst
combox.RemoveItem 0
Do Until RS.EOF
Me.combox.AddItem RS.Fields("some_value")
RS.MoveNext
Loop
RS.Close
Set RS = Nothing
Me.combox.BoundColumn = 0
Me.combox.ListIndex = 0

My query for counting subrecords in Acces does not work?

I'm having a problem with my query. I'm having a database with a Table "Label" that contains some subrecords("ReleaseID").
What I want to do: I want to count the subrecords that are linked to the LabelID in my Label table. I have the following code:
Dim db As Object
Dim rst As Recordset
Set db = CurrentDb
Dim qryCount As String
Dim Value as integer
qryCount = "select count(ReleaseID) as aantal from(select LabelID, ReleaseID from Label where LabelID = " & Me!LabelID")
Set rst = db.OpenRecordset(qryCount, dbOpenDynaset)
Value = rst!aantal
The query is working when I try it in the Query design in Acces. But when I use it in VBA then it doesn't.
Appreciate any help.
It's hard to see your actual code when you don't format it.
This is what you last posted
qryCount = "select count(ReleaseID) as aantal from Label where LabelID = " & Me!LabelID
Set rst = db.OpenRecordset("Label", dbOpenDynaset)
Value = rst1!aantal
If that's what you actually have then you
Probably can't use Value - I think that's a reserved word
You've set the recordset name to rst but you're trying to use rst1 for value reference
I'm not sure if its just a copy mistake, but the closing brace is missing, isn't it?
qryCount = "select count(ReleaseID) as aantal from(select LabelID, ReleaseID from Label where LabelID = " & Me!LabelID & ")"
If your are just looking for a count you can do it with DCount
varCount = DCount("ReleaseID", "Label", "LabelID = " & Me!LabelID)
No recordsets required. If you're not iterating through the recordset Dcount is much simpler and less taxing on the system.
It's called a domain function, well worth looking up if you have a spare moment (Dlookup, DSum, Dmax, Dcount).
Why not use DCount:
Dim Value As Long
Value = DCount("*", "ReleaseTable", "[LabelID] = " & Me!LabelID.Value & "")

Update combobox based on another combobox through query

I have several combo boxes (CB) populating from my access database. They all pull from the same table and use the same hidden primary key from the table. When I select a value from one of the CB's I would like to have the others updated with the associated value based on the matching primary key.
Is this possible?
I've been trying to use variations of the following for a while now with no success:
Dim strSQL As String
strSQL = "SELECT gsr_id FROM task WHERE task_wid = " & Me.cboTask.Column(0)
Me.cboGSRTask.Section = CurrentDb.OpenRecordset(strSQL)
Debug.Print "SELECT gsr_id FROM task WHERE task_wid = " & Me.cboTask.Column(0)
Thank you.
If you open a recordset, you need to read a value from it, you can't use the recordset as value.
I guess what you are looking for is:
Dim strSQL As String
Dim RS As Recordset
strSQL = "SELECT gsr_id FROM task WHERE task_wid = " & Me.cboTask.Column(0)
Set RS = CurrentDb.OpenRecordset(strSQL)
' This assumes that gsr_id is the bound column of cboGSRTask
Me.cboGSRTask = RS!gsr_id
RS.Close
Or instead all of the above, using DLookup() :
Me.cboGSRTask = DLookup("gsr_id", "task", "task_wid = " & Me.cboTask.Column(0))
Or it might be even easier to add gsr_id to the row source of cboTask (as a column with width = 0) and use that column to assign to cboGSRTask.

Table for priorities?

I am curious to know if there is a way to make a table based off priorities?
As in you have a form, subform (datasheet), and 2 buttons.
The subform takes data from a query which takes data from a table.
From here, the query shows projects. You can select the project on the subform and click a button to dec priority, which moves it DOWN on the list by 1 project. If you click the inc button, it moves it UP. If it's at the very bottom and you click the decrease button it will pop up saying "This project is already the lowest priority!" same with the increase, but it'll say it's already the highest.
Is this possible? I really don't know any VBA to access a subform's datasheet and modify it, and I'd like to learn.
UPDATE:
I have 1 table, with 5 priority types, and 1 key.
The table is named ProjectsT, the key is named ProjectID and the 5 priorities are:
CuttingPriority, ProjPriority, EngineerPriority, CutplanPriority, HardwarePriority. Each priority is listed as a number datatype.
This is one set of code I have so far for the buttons from an answer below:
Up button:
Dim strSQL As String
Dim intSavePos As Integer
Dim intSavePosMin As Integer
Dim intSavePosMax As Integer
'Save start and end value (It's assumed you start with 1 ! The value 0 (zero) is used for swapping value's)
intSavePosMin = DMin("CuttingPriority", "ProjectsT")
intSavePosMax = DMax("CuttingPriority", "ProjectsT")
'When the subform is linked to a keyfield use that field for a WHERE like:
'intSavePosMin = DMin("sequence", "tblTableNico5038", "Function='" & Me.sfrmFunctionTables.Form.Function & "'")
'intSavePosMax = DMax("sequence", "tblTableNico5038", "Function='" & Me.sfrmFunctionTables.Form.Function & "'")
intSavePos = Me.txtCuttingPriority
'is it the first ? ==> no action
If intSavePos = intSavePosMin Then Exit Sub
'switch positions
DoCmd.SetWarnings False
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = 0 WHERE CuttingPriority=" & intSavePos & ";"
'When the subform is linked to a keyfield use that field for a WHERE like:
'strSQL = "UPDATE tblTableNico5038 SET tblTableNico5038.Sequence = 0 WHERE Function='" & Me.sfrmTableNico5038.Form.Function & "' AND sequence=" & intSavePos & ";"
DoCmd.RunSQL strSQL
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = " & intSavePos & " WHERE CuttingPriority=" & intSavePos - 1 & ";"
'When the subform is linked to a keyfield use that field for a WHERE like:
'strSQL = "UPDATE tblTableNico5038 SET tblTableNico5038.Sequence = " & intSavePos & " WHERE Function='" & Me.sfrmTableNico5038.Form.Function & "' AND sequence=" & intSavePos - 1 & ";"
DoCmd.RunSQL strSQL
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = " & intSavePos - 1 & " WHERE CuttingPriority=0;"
'When the subform is linked to a keyfield use that field for a WHERE like:
'strSQL = "UPDATE tblTableNico5038 SET tblTableNico5038.Sequence = " & intSavePos - 1 & " WHERE Function='" & Me.sfrmTableNico5038.Form.Function & "' AND sequence=0;"
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True
Me.Refresh
Me.ProjectsTCuttingSubF.SetFocus
SendKeys ("{up}")
Down button:
Dim strSQL As String
Dim intSavePos As Integer
Dim intSavePosMin As Integer
Dim intSavePosMax As Integer
intSavePosMin = DMin("CuttingPriority", "ProjectsT")
intSavePosMax = DMax("CuttingPriority", "ProjectsT")
intSavePos = Me.txtCuttingPriority
'is it the last ? ==> no action
If intSavePos = intSavePosMax Then Exit Sub
'switch positions
DoCmd.SetWarnings False
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = 0 WHERE CuttingPriority=" & intSavePos & ";"
DoCmd.RunSQL strSQL
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = " & intSavePos & " WHERE CuttingPriority=" & intSavePos + 1 & ";"
DoCmd.RunSQL strSQL
strSQL = "UPDATE ProjectsT SET ProjectsT.CuttingPriority = " & intSavePos + 1 & " WHERE CuttingPriority=0;"
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True
Me.Refresh
Me.ProjectsTCuttingSubF.SetFocus
SendKeys ("{down}")
--
I was curious to see if I could come up with a solution that didn't resort to "SQL glue-up". The result is available for download here (Access 2010 or later).
The key components are a [Managers] table
ID ManagerName
-- --------------
1 Thompson, Gord
2 Elk, Anne
a [Projects] table
ID ManagerID Description Priority
-- --------- -------------------- --------
1 1 buy bacon 1
2 1 wash the car 2
3 1 clean out the garage 3
4 2 test1 1
5 2 test2 2
two saved parameter queries (QueryDefs) to locate the next highest/lowest-priority project
[GetHigherPriorityProject]
PARAMETERS prmManagerID Long, prmCurrentPriority Long;
SELECT TOP 1 Projects.ID, Projects.Priority
FROM Projects
WHERE (((Projects.Priority)<[prmCurrentPriority])
AND ((Projects.ManagerID)=[prmManagerID]))
ORDER BY Projects.Priority DESC , Projects.ID;
[GetLowerPriorityProject]
PARAMETERS prmManagerID Long, prmCurrentPriority Long;
SELECT TOP 1 Projects.ID, Projects.Priority
FROM Projects
WHERE (((Projects.Priority)>[prmCurrentPriority])
AND ((Projects.ManagerID)=[prmManagerID]))
ORDER BY Projects.Priority, Projects.ID;
one more saved parameter query to update the priority of a given project
[SetProjectPriority]
PARAMETERS prmNewPriority Long, prmID Long;
UPDATE Projects SET Projects.Priority = [prmNewPriority]
WHERE (((Projects.ID)=[prmID]));
a dead-simple Class just to hold a couple of Properties
[projectInfo]
Option Compare Database
Option Explicit
Private pID As Long, pPriority As Long
Public Property Get ID() As Long
ID = pID
End Property
Public Property Let ID(Value As Long)
pID = Value
End Property
Public Property Get Priority() As Long
Priority = pPriority
End Property
Public Property Let Priority(Value As Long)
pPriority = Value
End Property
a rudimentary form with a subform
and the code behind that form
Option Compare Database
Option Explicit
Private Sub cmdMoveDown_Click()
AdjustPriority "lower"
End Sub
Private Sub cmdMoveUp_Click()
AdjustPriority "higher"
End Sub
Private Sub AdjustPriority(Direction As String)
Dim cdb As DAO.Database, rst As DAO.Recordset, qdf As DAO.QueryDef
Dim currentProjectID As Long, otherProject As projectInfo
Set rst = Me.ProjectsSubform.Form.RecordsetClone
rst.Bookmark = Me.ProjectsSubform.Form.Recordset.Bookmark
currentProjectID = rst!ID
Set otherProject = GetOtherProject(rst!ManagerID, rst!Priority, Direction)
If otherProject.ID = 0 Then
MsgBox "There is no project with a " & Direction & " priority."
Else
Set cdb = CurrentDb
Set qdf = cdb.QueryDefs("SetProjectPriority")
' swap priorities
qdf!prmNewPriority = rst!Priority
qdf!prmID = otherProject.ID
qdf.Execute
qdf!prmNewPriority = otherProject.Priority
qdf!prmID = currentProjectID
qdf.Execute
Set qdf = Nothing
Set cdb = Nothing
Me.ProjectsSubform.Requery
' now restore the previous current record in the subform
Set rst = Me.ProjectsSubform.Form.RecordsetClone
rst.FindFirst "ID=" & currentProjectID
Me.ProjectsSubform.Form.Recordset.Bookmark = rst.Bookmark
End If
rst.Close
Set rst = Nothing
Set otherProject = Nothing
End Sub
Private Function GetOtherProject(prmManagerID As Long, _
prmCurrentPriority As Long, _
Direction As String) As projectInfo
Dim cdb As DAO.Database, qdf As DAO.QueryDef, rst As DAO.Recordset
Dim rtn As New projectInfo
Set cdb = CurrentDb
If Direction = "higher" Then
Set qdf = cdb.QueryDefs("GetHigherPriorityProject")
Else
Set qdf = cdb.QueryDefs("GetLowerPriorityProject")
End If
qdf!prmManagerID = prmManagerID
qdf!prmCurrentPriority = prmCurrentPriority
Set rst = qdf.OpenRecordset(dbOpenSnapshot)
If rst.EOF Then
rtn.ID = 0
rtn.Priority = 0
Else
rtn.ID = rst!ID
rtn.Priority = rst!Priority
End If
rst.Close
Set rst = Nothing
Set qdf = Nothing
Set cdb = Nothing
Set GetOtherProject = rtn
Set rtn = Nothing
End Function
EDIT re: comment
is there a way to make it automatically add the next priority number on the list if you are adding a record through another form?
Yes. I forgot to mention that in the existing sample solution there is a Before Change Data Macro on the [Projects] table to do just that:
If [IsInsert] Then
If Not IsNull([ManagerID]) Then
SetField
Name Priority
Value = Nz(DMax("Priority", "Projects", "ManagerID=" & [ManagerID]), 0) + 1
End If
End If
Read through the ENTIRE conversation here:
re-order a records sequence using up and down buttons
You're going to need at aleast a mediocre understanding of VBA and how to apply your specific data to a pre-existing example. This person was looking to do almost precisely what your question describes, and the person who was working with him was an Access MVP. I say to read through the entire conversation because there were several iterations and tweaks performed over the course of the solution.
If you have any specific questions after integrating this solution, feel free to come back and ask.
I have a work ticket system in my work place and to create priorities I created two tables: Work_Tickets and Work_Ticket_Criteria. The criteria table has a list of low, low-medium, etc... and a field in Work_Tickets pulls from that 2nd table. Then sort by date.
It doesn't give a single ticket a numerical priority like you are looking for because to do that I believe you would have to create a separate field and then modify the numerical field of each record after every update. Switch 1 with 2, or make the new record 1 and then add 1 to each and every record's priority field to move them down the list.
Or if you start with a number like 1000 then you can make records more or less than 100 in increments of 5, 10, or 20 but then you'll eventually run out of numbers...
Update
If you're willing to go my method of adding another column, then I would just add column and name the field Priority_Numbers or something. Then you would mark each as 1 - whatever but you may want to make check to make sure your number doesn't already exist by making it a key or giving it a check.
Then each time you would want to view your tickets you would use something like:
Dim strSQL As String
Dim myR As Recordset
strSQL = "SELECT * FROM table_name WHERE criteria_here ORDER BY Priority_Numbers ASC"
Set myR = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset)
And bam you have your prioritized list.
Now to change the priority you would need to select that recordset, do a findfirst to get the record with the value you want replaced, +1 or -1 to each priority number in a While not EOF loop and keep moving next. This will become tedious if your tickets become too high I'm sure.