I have a list box in a form. Clicking on it causes the form to jump to another record. It supposed to highlight an item and jump to the correct record. Instead, it highlights, and then instantly clears the selection, although it still jumps to the record. When I use standard record selection buttons, items are correctly highlighted.
I read the index of selected item from .ListIndex property because Selected() does not work in a Single Selection mode when I test which item is selected. However, .ListIndex is read-only property and I use .Selected() to highlight the item.
Option Compare Database
Option Explicit
Private Sub Form_Current()
Call highlightListBox
End Sub
Private Sub lbListBox_Click()
Dim rs As DAO.Recordset
Dim indx As Long
Set rs = Me.RecordsetClone
If Not rs.BOF And Not rs.EOF Then
rs.MoveFirst
rs.FindFirst "[ID]=" & CStr(Me.lbListBox.ItemData(Me.lbListBox.ListIndex))
If Not rs.NoMatch Then
Me.Bookmark = rs.Bookmark
End If
End If
rs.Close
Set rs = Nothing
End Sub
Private Sub highlightListBox()
Dim lngIndx As Long
Dim lngI As Long
Dim bNoMatch As Boolean
lngIndx = 0
bNoMatch = True
If Me.NewRecord <> 0 Or IsNull(Me!ID) Then
For lngI = 0 To Me.lbListBox.ListCount - 1
Me.lbListBox.Selected(lngI) = False
Next lngI
Else
Do
lngIndx = lngIndx + 1
If CLng(Me.lbListBox.ItemData(lngIndx - 1)) = Me!ID Then
bNoMatch = False
End If
Loop Until CLng(Me.lbListBox.ItemData(lngIndx - 1)) = Me!ID Or lngIndx = Me.lbListBox.ListCount
End If
If Not bNoMatch Then
Me.lbListBox.Selected(lngIndx - 1) = True
End If
End Sub
I have been given a suggested about slightly different problem here but thanks to Remou I sorted this out.
The new code is following:
Option Compare Database
Option Explicit
Private Sub Form_Current()
Me.lbListBox = Me!ID
End Sub
Private Sub lbListBox_Click()
Dim rs As DAO.Recordset
Dim indx As Long
Set rs = Me.RecordsetClone
If Not rs.BOF And Not rs.EOF Then
rs.MoveFirst
rs.FindFirst "[ID]=" & CStr(Me.lbListBox.ItemData(Me.lbListBox.ListIndex))
If Not rs.NoMatch Then
Me.Bookmark = rs.Bookmark
End If
End If
Me.lbListBox = Me!ID
rs.Close
Set rs = Nothing
End Sub
I did not realise I could actually set a value to a list box using BoundColumn. By doing so, both highlighting and focusing is set. I am not sure but I think that MultiSelection has to be set to 0. In my case, the line
Me.lbListBox = Me!ID
does the job :)
I hope this answer can help someone else :)
Related
I have an MS Access database with a set of forms to enter vegetation data for a large monitoring project. I have one form called frmTransect with a button that opens a second form called frmLPI which is set up as an unbound main form with a subform called frmLPIDetail bound to a sql server database table. The main form has just two unbound fields, DataObs and DataRec, both of which are comboboxes. These two field are set up with an AfterUpdate event procedure to populate their corresponding fields in the subform, Data_observer and Data_recorder. This works perfectly. I wanted to have the unbound fields autopopulate with the last value in the subform of Data_observer and Data_recorder when the form is lauched again. To do this I used a FormOpen event procedure. Below is the code:
Private Sub Form_Open(Cancel As Integer)
Me.TransectOID = Me.OpenArgs
Dim rs As DAO.Recordset
Set rs = Me!frmLPIDetail.Form.RecordsetClone
If rs.RecordCount > 0 Then
If Not rs.BOF Then
rs.MoveLast
rs.MovePrevious
End If
If Not IsNull(rs!Data_recorder.Value) Then
Me.DataRec.Value = rs!Data_recorder.Value
Me.frmLPIDetail.Form.Data_recorder.DefaultValue = """" & Me.DataRec.Value & """"
End If
If Not IsNull(rs!Data_observer.Value) Then
Me.DataObs.Value = rs!Data_observer.Value
Me.frmLPIDetail.Form.Data_observer.DefaultValue = """" & Me.DataObs.Value & """"
End If
rs.MoveLast
rs.MoveFirst
While Not rs.EOF
rs.Edit
rs!Data_recorder.Value = Me.DataRec.Value
rs!Data_observer.Value = Me.DataObs.Value
rs.Update
rs.MoveNext
Wend
End If
rs.Close
Set rs = Nothing
Me.Dirty = False
End Sub
Here is where things get weird. When I click the command button on frmTransect, frmLPI opens, but the FormOpen event procedure above doesn't get launched. However, if I switch into design view, and then back into Form View, it does trigger, and works as intended! How can I get this event procedure to launch when I open the frmLPI using the command button in frmTransect? Any help would be much appreciated.
And it turned out it was as simple as adding a Me.Refresh and Me.Requery to my code block:
Private Sub Form_Open(Cancel As Integer)
Me.TransectOID = Me.OpenArgs
Me.Refresh
Me.Requery
Dim rs As DAO.Recordset
Set rs = Me!frmLPIDetail.Form.RecordsetClone
If rs.RecordCount > 0 Then
rs.MoveLast
rs.MovePrevious
If Not IsNull(rs!Data_recorder.Value) Then
Me.DataRec.Value = rs!Data_recorder.Value
Me.frmLPIDetail.Form.Data_recorder.DefaultValue = """" & Me.DataRec.Value & """"
End If
If Not IsNull(rs!Data_observer.Value) Then
Me.DataObs.Value = rs!Data_observer.Value
Me.frmLPIDetail.Form.Data_observer.DefaultValue = """" & Me.DataObs.Value & """"
End If
rs.MoveLast
rs.MoveFirst
End If
rs.Close
Set rs = Nothing
Me.Dirty = False
End Sub
I have the following example code on a few events for a few comboboxes:
Private Sub cbo_oc_tours_all_Enter()
' Find the record that matches the control.
Dim rs As Object
Set rs = Me.Recordset.Clone
rs.FindFirst "[ID_T_OC] = " & Str(Nz(Me![cbo_oc_tours_all], Null))
If Not rs.EOF Then Me.Bookmark = rs.Bookmark
Me.cbo_oc_tours_today.Value = Str(Nz(Me![cbo_oc_tours_all], Null))
End Sub
I want to put this into a single function and call it from each event procedure(?). I've used the following code in the function:
Sub goto_record(goto_rec As ComboBox, update_rec As ComboBox)
Dim rs As Object
Set rs = Me.Recordset.Clone
rs.FindFirst "[ID_T_OC] = " & Str(Nz(Me![goto_rec], Null))
If Not rs.EOF Then Me.Bookmark = rs.Bookmark
update_rec.Value = Str(Nz(Me![goto_rec], ""))
End Sub
And I'm trying to call it using:
Sub cbo_oc_tours_all_Enter()
Call goto_record(cbo_oc_tours_all, cbo_oc_tours_today)
End Sub
However, I'm getting an error saying Microsoft Access can't find the field 'goto_rec' referred to in your expression. I'm clearly not passing the combo box in the right way but it's been a while since I've used VBA. What's my issue?
Do not pass the combo box as an object, just pass the value in the combo box. Here is an example:
Sub cbo_oc_tours_all_Enter()
Call goto_record(me.cbo_oc_tours_all, me.cbo_oc_tours_today)
End Sub
Assuming those are the names of the combo boxes themselves. Then you other function would be
'Using a data type of variant for example. Replace with the datatype you are using
Sub goto_record(goto_rec As Variant, update_rec As Variant)
Dim rs As Recordset
Set rs = Me.Recordset.Clone
rs.FindFirst "[ID_T_OC] = " & Str(Nz(goto_rec,0))
If Not rs.EOF Then Me.Bookmark = rs.Bookmark
'You can change this line to this if the function is in the same module as the form with the combobox
me.cbo_oc_tours_today = goto_rec
End Sub
I have a form which comprise of a texbox bound to a field called Year1. I want to create a new record using the new record controls in the bottom of the form and have the value on the previous record carried forward to the new record. I tried the following codes but no luck. Any help is greatly appreciated. Below is my first approach:
Private Sub Form_Current()
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT * FROM tblMyTable")
rs.AddNew
rs.Fields("Year1").Value = Year1.Value
rs.Close
End Sub
I have also tried the following approach but no luck:
Private Sub Form_Current()
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT * FROM tblMyTable")
rs.Edit
rs!Year1 = Year1.Value
rs.Update
rs.Close
End Sub
On the Year1_AfterUpdate() even, adding:
Me.Year1.DefaultValue = "'" & Me.Year1 & "'"
Works as expected.
Is it possible to get the values from rows in an Access table that are showing after the filter is applied?
Example as requested:
I have a table in which employees fill in project tasks, hours on the project etc.
It is made as a table on a form. The columns has limited choices in Initials, Project number, etc. People like to sort the table by the built in filter function in access tables and queries. I filtered so only the project LT1075 is shown in the example.
How can i get those 4 rows as a recordset or something similar? I need to get the values in all hour fields. I need also to copy only those 4 lines in VBA and do stuff to it (Functions wanted by people). But when i use the DAO, i get all rows in the "Unfiltered" table.
How do i get only the rows visible?
In excel, there is a simple function, something with cells_visible but i cant find a pardon to Access.
Best Regards, Emil.
Edit, tryouts:
Public Sub Test1_Click()
Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone
While Not rs.EOF
' Do calculation stuff on record.
rs.MoveNext
Wend
End Sub
It is put on the "Test 1" button in the figure above.
I get the error: "Runtime error 7951 - You entered an expression that has an invalid reference to the RecordsetClone property"
I have a clue that it does not work because of the Me.* function? Since the table is in some sort of subform. But i see only one form in the Navigation panel. (Hidden are also showed).
You can use the RecordsetClone of the form:
Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone
While Not rs.EOF
' Do calculation stuff on record.
rs.MoveNext
Wend
And you can add records to a recordset:
Public Sub CopyRecords()
Dim rstSource As DAO.Recordset
Dim rstInsert As DAO.Recordset
Dim fld As DAO.Field
Dim strSQL As String
Dim lngLoop As Long
Dim lngCount As Long
strSQL = "SELECT TOP 1 * FROM tblStatus"
Set rstInsert = CurrentDb.OpenRecordset(strSQL)
' rstSource can be any recordset, here the RecordsetClone of the form.
Set rstSource = Me.RecordsetClone
With rstSource
While Not .EOF
With rstInsert
.AddNew
For Each fld In rstSource.Fields
With fld
If .Attributes And dbAutoIncrField Then
' Skip Autonumber or GUID field.
ElseIf .Name = "Total" Then
' Special cases.
' Insert default job code.
rstInsert.Fields(.Name).Value = 0
ElseIf .Name = "PROCESSED_IND" Then
rstInsert.Fields(.Name).Value = vbNullString
Else
' Copy field content.
rstInsert.Fields(.Name).Value = .Value
End If
End With
Next
.Update
End With
.MoveNext
Next
rstInsert.Close
.Close
End With
Set rstInsert = Nothing
Set rstSource = Nothing
End Sub
so if i do a SQL statement like so:
sql = "SELECT * FROM tblMain"
set rs = currentdb.openrecordset(sql)
what method can i use to view every "field name" in this collection i have just created. i am getting some very strange error stating that the item is not found in this collection.
i know the field exists in the table, i have triple checked the spelling everywhere when i reference it, and the SQL should be pulling everything, but i want to see it.
is there a debug.print method to see all these fields
thanks
Justin
This is a variation on the other answers, but I believe it's better to use a For/Each loop than a counter:
Dim rs As DAO.Recordset
Dim fld As DAO.Field
Set rs = CurrentDB.OpenRecordset("SELECT * FROM tblMain")
For Each fld In rs.Fields
Debug.Print fld.Name
Next fld
Set fld = Nothing
rs.Close
Set rs = Nothing
You can iterate through the fields collection of the recordset.
Code is OTTOMH
Dim NumFields as Integer
For NumFields = 0 to rs.Fields.Count -1
Debug.Print Rs.Fields(NumFields).Name
Next
Alternately, you can set a breakpoint at set rs = currentdb.openrecordset(sql) and then as soon as the statement executes, right-click on rs, choose add watch and view the whole thing in the Watches window.
Here is a script that will look for a field containing the string you specify in every table in an Access database (except System and Attached Tables) and write it to text files:
Option Compare Database
Option Explicit
Sub main()
Dim db As Database
Dim rs As Recordset
Dim bFinished As Boolean
Dim sFieldName As String
Dim iPosition, z, x As Integer
Dim bRetVal As Boolean
Dim tdTemp As TableDef
Dim iDatabaseNumbers As Integer
Const FIELD_TO_FIND = "FieldName"
Set db = CurrentDb
Open Left(db.Name, Len(db.Name) - 4) & "_" & FIELD_TO_FIND & ".txt" For Output As #1
For x = 0 To db.TableDefs.Count - 1
Set tdTemp = db.TableDefs(x)
bRetVal = IIf(tdTemp.Attributes And dbSystemObject, False, True)
If bRetVal Then
bRetVal = IIf(tdTemp.Attributes And dbAttachedTable, False, True)
End If
If bRetVal Then
Set rs = db.OpenRecordset(db.TableDefs(x).Name)
If rs.RecordCount > 0 Then
For z = 0 To rs.Fields.Count - 1
sFieldName = rs.Fields(z).Name
If InStr(1, sFieldName, FIELD_TO_FIND, vbTextCompare) > 0 Then
Print #1, db.TableDefs(x).Name
Exit For
End If
Next z
End If
End If
Next x
Close #1
MsgBox "Done"
End Sub
You could adjust accordingly to make it do what you need.