Setting the value of an Access combobox with VBA comparison - ms-access

I'm trying to figure out where I went wrong with this.
I have two tables Request and Parent. Request can only have one related Parent record, but Parent can have many related Request records. So I have the Request table containing the foreign key to Parent.
I have an unbound combobox that pulls it's data from the Parent table using a query (contains company name and ID bound to column 0 and 1, with column 1 being hidden so the user doesn't see the numeric ID). It's unbound because the form's recordset has a lot of complex joins, making anything on that form unable to be updated. So I created an "On Change" event on the combo box to fill in the foreign key using a querydef SQL update query:
Private Sub Combo217_Change()
Dim ComboID As String
Dim ReqID As Long
Dim dbs As DAO.Database
Dim qdfUpdateParentExisting As DAO.QueryDef
ReqID = Me.RequestID.Value
ComboID = Me.Combo217.Column(1)
Set dbs = CurrentDb
Set qdfUpdateParentExisting = dbs.QueryDefs("UpdateReqExistingParent")
qdfUpdateParentExisting.Parameters("VBParent").Value = ComboID
qdfUpdateParentExisting.Parameters("VBReqID").Value = ReqID
qdfUpdateParentExisting.Execute
qdfUpdateParentExisting.Close
DoCmd.Save acForm, "DT2"
Me.Requery
End Sub
This works just fine, but once you exit the form and re-enter it, the value in the combo box is blank and I would like this to contain the same value that was selected.
I've been trying to do an "On load event" with the following code but it's not working
Dim ParID
ParID = Me.ParentID.Value
Me.Combo217.Column(1).Value = ParID
Any input on getting this to work would be fantastic!

Because it's tied to specific column you can loop thru to set the value based on the matching ID
EDIT - Add Row index to Column Value
Dim i as Integer
With Combo217
For i = 0 To .ListCount - 1
If .Column(1, i).Value = ParID Then
.Value = .ItemData(i)
Exit For
End If
Next
End With

Related

Why isn't MS Access "item found in collection?"

I have a non-linked table "tblGrantRptData" in which I am trying to modify field records for subsequent filtering and export to EXCEL. I have ensured that all field names are correctly spelled, yet I still get an Error 3265, Item not found in this collection.
I have confirmed that MemmonthlyIncome is the correct spelling and is identified in the design as "currency."
here is the design veiw that appears to show the field name:
It stops at this line:
If IsNull (!MemmonthlyIncome) Then
with the error 3265
If I can get some help to resolve this, I would then like to store the range "0-30"....
One suggestion below was to “decompile" and "recompile.” I have read that this may cause problems when the database is used on multiple workstations. I have revised the code to just get to first base….Any suggestions?
Private Sub cmdGenerateGrantRpt_Click()
'now run the qqAll query - this generates the tblGrantRptData - then close the query
DoCmd.SetWarnings False
DoCmd.OpenQuery "qqAll", acViewNormal, acEdit
DoCmd.Close acQuery, "qqAll"
DoCmd.SetWarnings True
'First set up the table: tblGrantRptData with the correct data in fields
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("tblGrantRptData", dbOpenTable)
'Check to see if the recordset actually contains rows and fill in particular values
With rs
If .EOF And .BOF Then
MsgBox "There are no records in this time interval"
Exit Sub
Else
.MoveFirst
Do Until .EOF = True
'Replace the monthly income with income categories
If IsNull(!MemmonthlyIncome) Then
.Edit
!MemmonthlyIncome = "0-30"
.Update
End If
Loop
End If
End With
rs.Close 'Close the recordset
Set rs = Nothing 'Clean up
End Sub
You get error #3265, "Item not found in this collection", at IsNull(!MemmonthlyIncome) in this context ...
Set rs = db.OpenRecordset("tblGrantRptData", dbOpenTable)
With rs
If IsNull(!MemmonthlyIncome) Then
That would happen if tblGrantRptData does not include a field named MemmonthlyIncome. What you are seeing as the column heading in the table Datasheet View may be the field's Caption property. You could check the field's Name and Caption properties in the table's Design View. Or you could list the actual field names for your table in the Immediate window.
Here's an abbreviated list of the field names in my Contacts table:
set db = currentdb
for each fld in db.TableDefs("Contacts").Fields : ? fld.name : next
ID
Company
Last Name
First Name
You just added this screen capture of your table in Design View ...
Notice the field is named MemmothlyIncome, not MemmonthlyIncome (moth vs. month). So it wasn't a Name vs. Caption difference after all; you simply tried to use a misspelled field name. That spelling problem is also visible in the DataSheet View screen capture, but we didn't notice it there.
In VBA, there is no Is Null expression as there is in SQL. Change to IsNull(rs!MemmonthlyIncome).
Possibly, Null is being referenced in recordset collection and hence returning the error.

insert data to a record already saved to a table

I have a recordset that is missing one field for each record and would like to add some data from a form by looking up certain criteria. I used a select query to get data onto the form in the first place and tried to reverse the assigning of values but it doesnt work as it says Run-time error 3027 'the Database or Object is Read only.' I think this is because I ran a select query to get the information but how do I input the data to the same records. the code I used is below -
Private Sub CmdAppend_Click()
Dim dbsNorthwind As dao.Database
Dim rstAmend As dao.Recordset
Dim qdfAmend As dao.QueryDef
Dim n As Integer
Set dbsNorthwind = CurrentDb
Set qdfAmend = dbsNorthwind.QueryDefs("Get_Questions_NTL")
qdfAmend.Parameters(0) = [Forms]![TeamLeader]![ComClientNotFin]
qdfAmend.Parameters(1) = [Forms]![TeamLeader]![ComDateSelect]
Set rstAmend = qdfAmend.OpenRecordset(dbOpenDynaset)
n = 0
rstAmend.MoveFirst
Do Until rstAmend.EOF
n = n + 1
rstAmend.Fields("ManagerID") = Form.Controls("SC" & n).Value
rstAmend.MoveNext
Loop
End Sub
You'd have to use the .Edit and .Update methods of the recordset object to update records. You received the error because you are trying to assign a value to a read only property.

How to properly finish an access database transaction with DAO vba?

I'm working with DAO recorsets, the basic idea is to populate one table with records many times as the given argument indicates (limit).
It appears to work, but suddenly when I want to use the form again, it throws 3022 error. When I see table values, none of them is duplicated. I delete all records from that table and refresh table and form. The table doesn't show any value until I refresh the form. The unique value that is shown is the last value i try to save in database.
Here is a little bit of code:
Private Sub add_element(loops_number As Double)
i = 1
While (i < CDbl(loops_number))
function
i = i + 1
Wend
End Sub
That is working apparently fine.
Private Sub populate()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim last As DAO.Recordset
Set db = CurrentDb()
Set rst = db.OpenRecordset("Element", dbOpenTable)
Set last = rst.Clone
With rst
.AddNew
If (last.RecordCount <= 0) Then
'here I pass input form values to recordset fields ,because its the first row
last.Close
.Update
.Close
Else
last.MoveLast
!Pk = Custom_pk 'Custom_pk is obtained with a function --- not relevant
'here I pass remain values from last record to a new one --- because records has the same attributes
last.Close
.Update
.Close
End If
Set rst = Nothing
Set ultimo = Nothing
End With
End Sub
It's like last record values stays "active" after function finish work. I don't get why this happens.
Element pk is alphanumeric e.g. : "A1", then I build a function that separates A from 1,add +1 to number and concatenate values again, so the result is "A2"
I resolved it using an Autonumber field as primary key keeping the original pk (alphanumeric) as a common field then I could mantain my vba code exactly like I wanted it.

Access subform, how to resize columns to best fit?

I have a form with a subform. This subform displays the results of a query that is created dynamically (user enters criteria, I build the SQL, then update the querydef and display). Problem is since the columns are dynamic the width of the columns isn't working out, some are cutting off text.
Is there a way to programmatically loop through the columns (or do the same without loop) and set them all to bestfit width after the query is refreshed?
EDIT: Here is what my code looks like now:
CurrentDb.QueryDefs("SearchResults").sql = sql
CurrentDb.QueryDefs.Refresh
Dim qdf1 As DAO.QueryDef
Dim fld1 As DAO.Field
Set qdf1 = CurrentDb.QueryDefs("SearchResults")
For i = 0 To qdf1.Fields.Count - 1
Set fld1 = qdf1.Fields(i)
fld1.CreateProperty "ColumnWidth", dbInteger
fld1.Properties("ColumnWidth") = -2 'Throws error
Set fld1 = Nothing
Next i
Me.Child20.SourceObject = "Query.SearchResults"
You can set column widths like so:
Sub SetColumnWidth()
Dim qdf1 As DAO.QueryDef
Dim fld1 As DAO.Field
Set qdf1 = CurrentDb.QueryDefs("query3")
For i = 0 To qdf1.Fields.Count - 1
Set fld1 = qdf1.Fields(i)
fld1.CreateProperty "ColumnWidth", dbInteger
'very narrow indeed
'fld1.Properties("ColumnWidth") = 200
'Or -2 : Sizes the column to fit the visible text
'but it is not quite as useful as it would seem
fld1.Properties("ColumnWidth") = -2
Set fld1 = Nothing
Next i
End Sub
See also http://support.microsoft.com/kb/210427
So I've run into this same problem just now. I was fortunate enough to have half of my queries work and the other half not. I've been using this code:
Sub QueryData(strSQL As String)
Dim qryData As DAO.QueryDef
Dim intcount As Integer
Set qryData = CurrentDb.QueryDefs("DataQuery")
qryData.SQL = strSQL
qryData.CreateProperty "ColumnWidth", dbInteger
qryData.Fields(0).Properties("ColumnWidth") = 5760
DoCmd.OpenQuery "DataQuery", , acReadOnly
End Sub
Which generated the error on half of the queries I tried to run with it. I traced it back to this odd, but simple truth: Columns built using an Alias (i.e. all formula columns and expressions) kick out this error. If the column is just a straight data pull, it works fine. If the column is, however, a formulated display.... it spits the no columwidth property error.
Hopefully this'll help someone out! I know this questions about a year old, but it was the first result Google found for me on the topic.
I was able to make this grab the open forms and autofit the selected subform within that form. If you have multiple forms/subforms you would just call the function with the new names using the lines of code at the end of the function and pasting them in your program.
Public Function AutoSizeSbCtrl(frmNameTar, sbCtrlNameTar)
For Each frm In Forms
frmName = frm.Name
If frmName = frmNameTar Then
For Each frmCtrl In frm.Controls
frmCtrlName = frmCtrl.Name
If frmCtrlName = sbCtrlNameTar Then
For Each sbfrmCtrl In frmCtrl.Controls
sbfrmCtrlName = sbfrmCtrl.Name
On Error Resume Next
sbfrmCtrl.ColumnWidth = -2
On Error GoTo 0
Next sbfrmCtrl
End If
Next frmCtrl
End If
Next frm
' paste the lines below in your code where you want it to trigger (i did on an update)
'frmNameTar= "frm12345" ' where frm12345 is the name of the form the subform is in
'sbCtrlNameTar="sbfrm67890" ' where sbfrm67890 is the name of the subform you are trying to autofit
'auSize = AutoSizeSbCtrl(frmNameTar, sbCtrlNameTar)
'end paste
End Function

VBA - Accessing a collection of values

I have two access forms. frm_Main and frm_Sub which has data conditionally displayed depending on the selections of the main form. I need to write a select all function for items displayed in frm_Sub. In VBA is there a way that I can get a list of the id's currently being displayed in frm_Sub?
for example, if I do this
me.controls("Svc_Tag_Dim_Tag_Num").value
I get the value for one of rows in the frm_Sub, is there a way to get all of the values?
Maybe I can ask a different way. I have a form that is displayed as a listview, in VBA, is there a way to get all the values from a specific column?
Another option is to write a function that concatenates the PKs of the recordset that the subform displays. Say your main form is Company and your subform lists Employees. You'd have a LinkMasterFields and LinkChildFields properties of the subform control would be CompanyID (PK of the Company table, FK of the Employees table).
Thus, to get the same set of records as is displayed in the subform when the parent is on a particular Company record:
Dim db As DAO.Database
Dim strSQL As String
Dim rst As DAO.Recordset
Dim strEmployeeIDList As String
Set db = CurrentDB
strSQL = "SELECT Employees.* FROM Employees WHERE CompanyID="
strSQL = strSQL & Me!CompanyID & ";"
Set rs = db.OpenRecordset(strSQL)
If rs.RecordCount > 0 Then
With rs
.MoveFirst
Do Until .EOF
strEmployeeIDList = strEmployeeIDList & ", " & !CompanyID
.MoveNext
Loop
End With
strEmployeeIDList = Mid(strEmployeeIDList, 3)
End If
rs.Close
Set rs = Nothing
Set db = Nothing
Now, why would you do this instead of walking through an already-opened recordset (i.e., the subform's RecordsetClone)? I don't know -- it's just that there may be cases where you don't want your lookup to be tied to a particular form/subform. You could fix that by making your function that concatenates accept a recordset, and pass it a recordset declared as I did above, or pass it the subform's RecordsetClone. In that case, you could use the concatenation function either way, without being tied to the form/subform.
If I understand your question you should be able to access the ID value in the control using Column(x) where x indicates the control's row source column starting from 0. For example, if ID is in column 0 with width 0 in. it will be hidden from view but VBA can "see" it as me.controls.["Svc_Tag_Dim_Tag_Num"].column(0).
To get at the sub-form's record source directly from outside the form's class module you could create a function something like:
Public Function test_get_sub_form_record_set() As String
Dim dbs As Database
Dim rst As Recordset
Dim xcat As String
Set dbs = CurrentDb()
Set rst = [Forms]![Your Main Form Name]![Your Sub-form Name].[Form].RecordsetClone
If rst.RecordCount > 0 Then
rst.MoveFirst
xcat = rst!ID
rst.MoveNext
Do While Not rst.EOF
xcat = xcat & ", " & rst!ID
Loop
Else
xcat = ""
End If
test_get_sub_form_record_set = xcat
rst.Close
Set dbs = Nothing
End Function
This would be included in a separate module and when called would return a concatenated, comma separated list of ID's.