Putting results of array into a form control - vba

I have created an array in VBA in my Access application, and when I run it I get the intended results in the immediate window. What I am trying to do now is to take that array and put it into a form control (possibly a subform dataset?). I do not know how to this though on a multidimensional array. Below is the code that creates my array (it's dynamic, it can contain from zero to 10 results depending on how many records are in the DB.
' We need to get all of the participants for this engagement (Name, Email, Division and Role)
strSQL4 = "SELECT tblPerson.Person_FName, tblPerson.Person_LName, tblPerson.Email, tblORD_Division.ORD_Div, tblEngParRole.Role FROM tblORD_Division INNER JOIN ((tblEngagements INNER JOIN tblEngParRole ON tblEngagements.ENG_ID = tblEngParRole.Eng_ID) INNER JOIN tblPerson ON tblEngParRole.Person_ID = tblPerson.Person_ID) ON tblORD_Division.ORD_DIv_ID = tblPerson.ORD_Div_ID WHERE tblEngagements.Eng_ID = " & Me.Eng_ID
Set rs4 = CurrentDb.OpenRecordset(strSQL4)
rs4.MoveLast
rs4.MoveFirst
'Let's retrieve ALL Rows in the rs4 Recordset
varParticipants = rs4.GetRows(rs4.RecordCount)
Debug.Print "******************************************" 'Column Format only
Debug.Print "Last Name", "First Name", "Email", , "ORD_Div", "Role"
Debug.Print "---------------------------------------------------------------------------------------------"
For intRowNum = 0 To UBound(varParticipants, 2) 'Loop thru each Row
For intColNum = 0 To UBound(varParticipants, 1) 'Loop thru each Column
'To Print in Table Format, no numbered Fields or Rows
Debug.Print varParticipants(intColNum, intRowNum),
Next
Debug.Print vbCrLf
Debug.Print "******************************************" 'Column Format only
Next
rs4.Close
Set rs4 = Nothing
Thanks

Access doesn't provide a convenient way to display an array on a form. Skip the array and use a form/subform approach to display your data.
Build a query similar to your current query, but with these two changes:
Include tblEngagements.Eng_ID in the list of SELECT columns.
Discard the WHERE clause so the query will return all rows regardless of their Eng_ID values.
Build a new form based on that query.
Add the new form as a subform to your original form. On the subform control's property sheet, set the Link Master Fields and Link Child Fields properties to Eng_ID
Then, in operation, the subform should display only those rows whose Eng_ID values match the Eng_ID of the current row in the parent form.

Related

MS Access Retrieve Values from ListBox

UPDATE: 3/20/2019
After subthread conversation (below), I renamed the ListBox. ItemsSelected property WORKS. Value still returning NULL int he code
This is my first time dealing with multi-select lists in Access. I have a report form with some dropdowns, checkboxes, and a listbox. The listbox contains almost 70 items - Let's call them "Cities".
The ListBox allows multiple selections. In VBA, I'm taking each of the parameters - from the other controls on the form, to create a giant WHERE condition that feeds my report.
The problem is that Access is not reading the values selected from the ListBox. When I step through that line of code, the value is NULL.
So far:
Dim s As Variant
s = Me.City.Value & ""
This is where I know I wrong-turned, but, not having dealt with a multi-select ListBox before, I don't know the syntax to get the values read.
Next: Check for whether or not values are selected in List "s":
If s <> "" Then
Check for other parameters in the current WHERE condition. IF none exist, THEN
If c.WhereCondition = "" Then
c.WhereCondition =
Set WHERE Condition by comparing List values (which are Strings) to the Yes/No values of equivalent fields in Source table.
I have to compare the List values to the 70 fields in the table - to pull out those records that match.
No, there's not 1 field - say Cities, with 70 possible values. Instead, each of the 70 possible Cities is its own Yes/No field. I inherited this DB. It's how it was built.
Currently, my attempt at this looks like:
c.WhereCondition = "( City1 = -1 OR City2 = -1 OR City3 = -1 OR .....)
`IF there are parameters in the current WHERE clause, THEN compare values in List to Source table, AND APPEND result to WHERE condition with "AND"
ELSE
c.WhereCondition = c.WhereCondition & " AND (City1 = -1 OR City2 = -1, OR ...)
End If
End If
I hope I was able to explain this well enough. The 1st problem is getting the values read. I won't know if my attempt at comparison is right or wrong without that.
THIS took a LOT of breadcrumbs to get me here!
Solution:
Dim s As Variant
Dim i As Integer
Dim ctl As Control
Set ctl = Me.Counties
If ctl.ItemsSelected.Count <> 0 Then
For Each s In ctl.ItemsSelected
t.WhereCondition = ctl.ItemData(s) & " = -1"
Next s
End If
I had to rename the control from County to Counties. Looks like the former was part of the report, and screwing everything else up. I did this after initially deleting & re-adding the control.
The comments here really helped. I just needed to figure out how to work with the properties in order to get what I wanted.
I have to compare 70 yes/no fields to the data, pulling out only those that return True. Hence the -1.
It compiles. It runs. Fingers crossed for data accuracy.
Thanks!

Access Report with multiple column groups

So I'm working on automating a tedious process that uncle sam makes us do while deployed. I have a database where we put in a date for each day we are deployed into a table. For instance I have 4/10/2017 through 7/11/2017 listed.
Each day needs the date and location displayed and I need to put six results stacked vertically then move to the right to do the next six three more times.
I have one report named 2282report which is the master one with four subLocation[1-4]s in the appropriate spot. Originally I had it do TOP 6 then the next one would do TOP 6 but where ID > 6 but then I moved to make the date the ID as the date can't be duplicated anyway. I'm unsure of the proper way to make them linked so that the next subreport will display continue the rest.
The report looks like this when ran. I will also have over 90 days usually to list so I will need to create a second page to the main report.
What I'm thinking I'll have to do is create a new subreport for the entire location block but I don't know how to make the report_details move to a new column once it shows 6 results.
Another option I just thought of is to leave the subreports blank then make the master report set the controlsource for each one via vba. I feel this one may work because then it can check to see if there are more days then there are lines so that it can create a new page to continue. But then I need to figure out how to make it continue to the next page. There will also be a bottom section that will only have 16 days versus the 24 on the top.
You might be tempted to use VBA in the various report event handlers, but even if this might work, from my experience that would only lead to headaches trying to get everything to format properly. Instead, I recommend creating a new reporting table with a page number on each row. Source the main report from the sorted page number list and bind a multi-column subreport via the page number field. Populate the reporting table with a simple VBA procedure that correctly paginates the rows according to your scheme.
First the reporting table (add constraints as you find necessary):
CREATE TABLE SubReportTable (PageNum LONG, PageOrdinal LONG, _
Ordinal LONG, LastPage BIT, [Date of Service] DATE, [Location] TEXT)
On the SubReport:
Set RecordSoucre property: SubReportTable (alternatively specify a query that sorts on the desired fields)
Set Number of Columns to 4 along with other column settings (padding, direction, etc.).
Set CanGrow property to No on Detail section and other controls as appropriate.
Resize columns and detail section to properly fit all columns on page. (This will likely require going back and forth between print preview and design on the Main Form.)
On the main report, set the following properties:
RecordSource property: SELECT SubReportTable.PageNum FROM SubReportTable WHERE (((SubReportTable.LastPage)=False)) GROUP BY SubReportTable.PageNum ORDER BY SubReportTable.PageNum
Detail section property Force New Page to After Section.
SubReport object's Link Master Fields and Link Child Fields both to PageNum
Resize SubReport object to fit all columns properly.
Duplicate the behavior on the Main Report on a separate "Last Page" report. Set this report to select the proper subset of records based on the pagination data in the reporting table (i.e. LastPage = True). Depending on how different the last page with 16 records is formatted, it might also require creating a separate SubReport just for the 16 records, but you might get away with using the same SubReport as the main report... that'll be your problem to determine.
RecordSource property: SELECT SubReportTable.PageNum FROM SubReportTable WHERE ((SubReportTable.LastPage = True)) GROUP BY SubReportTable.PageNum ORDER BY SubReportTable.PageNum
Finally some code to populate the reporting table. You can either run this procedure directly from the VBA Immediate Window, or put it in some button's click event handler. The pagination logic can be tweaked to get the right amount of records on the last page.
Public Sub PrepareSubReporTable()
On Error GoTo Catch_PrepareSubReporTable
Dim db As Database
Dim rs As Recordset2
Dim rows As Long, pgs24 As Long, rowsLast24 As Long, rows16 As Long
Dim i As Long, p As Long, pi As Long
Set db = CurrentDb
db.Execute "DELETE * FROM [SubReportTable]", dbFailOnError
db.Execute _
"INSERT INTO SubReportTable ( PageNum, PageOrdinal, Ordinal, LastPage, [Date of Service], [Location] )" & _
" SELECT Null AS PageNum, Null AS PageOrdinal, Null AS Ordinal, False as LastPage," & _
" [Data].[Date of Service], [Data].[Location]" & _
" FROM [Data]" & _
" ORDER BY [Data].[Date of Service], [Data].[Location];", _
dbFailOnError
rows = db.OpenRecordset("SELECT Count(*) FROM SubReportTable").Fields(0)
pgs24 = rows \ 24
rows16 = rows - 24 * pgs24
If rows16 > 16 Then
rowsLast24 = rows16
pgs24 = pgs24 + 1
rows16 = 0
Else
rowsLast24 = 24
End If
Set rs = db.OpenRecordset( _
"SELECT * FROM SubReportTable" & _
" ORDER BY [Date of Service], [Location];")
i = 0
Do Until rs.EOF
p = i \ 24 + 1
rs.Edit
rs![PageNum] = p
If p > pgs24 Then
rs![lastPage] = True
pi = (i - pgs24 * 24) Mod 16 + 1
Else
pi = i Mod 24 + 1
End If
rs![PageOrdinal] = pi
i = i + 1
rs![Ordinal] = i
rs.Update
rs.MoveNext
Loop
rs.Close
Exit Sub
Catch_PrepareSubReporTable:
MsgBox Err.Number & ": " & Err.Description, _
vbOKOnly Or vbExclamation, "Error in PrepareSubReporTable"
End Sub
Now generate the main report and the last-page report, either manually or in VBA code somewhere.
Note: I used the field name PageNum instead of Page because that seemed to cause problems with a SubReport binding during print preview... probably because Page is the name of an existing variable / function for reports.

How to autocomplete a line with data suggestion?

Context:
In my company, some assistants fill out an Excel table, which is a users list (First Names, Last name, ID number). After, I use this list with a PowerShell script. But very often the users list is not correctly completed. For example, assistants forget to input ID number... .So i would like help assitants to fill this Excel with data suggestions/autocomplete.
Technical:
In the "Data" sheet, I have all data possible (First Names, Last name, ID number).
With the "Name Manager" I created:
d_FirstName to select the first cell
c_FirstName to select all column,
l_FirstName to apply function: =OFSSET(d_FirstName;0;0;COUNTA(c_FirstName)-1;1)
In "Form" sheet, I created drop-down list with function: =IF(A1<>"";OFSSET(d_FirstName;MATCH(A1&"*";l_FirstName;0)-1;;SUMPRODUCT((MID(l_FirstName;1;LEN(A1))=TEXT(A1;"0"))*1));l_FirstName)
So, when the user types a letter, the drop down list "suggest" a correct FirstName.
Question:
How to adapt the last query, to complete a line with First Name and Last name and ID number corresponding if user type only First Name ?
For example:
If user select a First Name in drop down list, Excel complete the lign with Last name and ID number corresponding .
If user select a ID number in drop down list, Excel complete the lign with Last name and First Name corresponding.
In second time, how to show dropdown list automatically when user type one letter ?
Thank you
You can accomplish this using the combobox's properties and change event. The combobox will take a 1 or 2 dimensional named range or a formula that returns a range as it's RowSource. Here I have the text column set to the 3rd column.
Private Sub cboEmpID_Change()
With cboEmpID
If Not IsNull(.Value) Then
lblEmployee.Caption = .List(.ListIndex, 1) & ", " & .List(.ListIndex, 0)
End If
End With
End Sub
Private Sub UserForm_Initialize()
Dim ColumnWidths As String
With Worksheets("Sheet1")
ColumnWidths = .Columns(1).Width & ";" & .Columns(2).Width & ";" & .Columns(3).Width
End With
With cboEmpID
.ColumnHeads = True
.ColumnCount = 3
.ColumnWidths = ColumnWidths
.TextColumn = 3
.ListWidth = Range("Sheet1!A:C").Width
.RowSource = "OFFSET(Sheet1!$A$1,1,0,COUNTA(Sheet1!$A:$A)-1,3)"
End With
End Sub
You need making a cascading dependent Excel drop down list.See

Microsoft Access - Add all items from a listbox into a table without having to be selected?

I'm making a data entry form that allows me to add new businesses and details for that business, before importing them into their respective tables. For the most part, I have completed it all.
However, there are some pieces of information that require more than one input. For example - a business could have multiple telephone numbers/documents/staff members etc.
I have set up a text box and an add/remove button which adds/removes the text in the textbox to a listbox. I want to be able to import all of the items in the listbox, without having to select them into a table. Is this possible? Most of the answers that I've found online require you to have the items selected.
An example piece of code that I have on the import button is show below. This code adds the address details of the business to the 'Business Address' table.
'Set Table to 'Business Address' then add the fields to the table
Set RST = CurrentDb.OpenRecordset("Business Address", dbOpenTable)
RST.AddNew
RST![Business Name] = Me.txtBusinessName
RST![Address] = Me.txtAddress1 & ", " & Me.txtAddress2
RST![Town/City] = Me.txtTownCity
RST![Postal Code] = Me.txtPostalCode
RST.Update
RST.Close
I was thinking some sort of for loop to add all items in the listbox to a table?
Logically speaking (This is not a real example of working code, just something I imagine this might look like if possible?):
Set RST = CurrentDb.OpernRecordset("Business Telephone", dbOpenTable)
For each item in TelephoneListBox
Rst.AddNew
Rst![Business Name] = Me.txtBusinessName
Rst![Telephone] = Me.TelephoneListBox.Column(0)
I'm not sure how to go about it and if it can actually be done without the items being selected? Any ideas?
Dim l As Long
For l = 0 To Me.List0.ListCount - 1
' Debug.Print Me.List0.ItemData(l) or me.list0.column(0,l)
Next l
This will loop through the items in the list.
To improve on Nathan_Sav's answer:
Dim i As Long
Set RST = CurrentDb.OpenRecordset("Business Telephone", dbOpenTable)
For i = 0 To Me.TelephoneListBox.ListCount - 1
RST.AddNew
Rst![Business Name] = Me.txtBusinessName
RST![Telephone] = Me.TelephoneListBox.Column(0, i)
RST.Update
Next i
Adds the value of 'txtBusinessName' to the table 'Business Telephone', under the field specified (Business Name), for each item that is in the listbox.
Also adds all items in the listbox (TelephoneListBox) to the same table under the field specified (Telephone).

Prevent merged cells splitting between pages

I am trying to write a program to create a Microsoft Word document from an Oracle table.
The document has tables with the left hand column which represents group field name and the next column has some fields associated with that group. I don't want the groups to split across pages. My code for doing this doesn't appear to work - the groups are still split across pages.
Does anyone know how to do this?
'output table data - data gets loaded into the display table starting at row 3
'(row 1 and 2 are the headers)
For row = 3 To maxrows + 2
Dim dataRow = dsHDTabCols.Tables(0).Rows(row - 3) 'dataset has rows to output
If dataRow("KEEP_WITH_NEXT_FLAG") & "" = "K" Then
oTable.Cell(row, 1).Range.ParagraphFormat.KeepWithNext = True
End If
If dataRow("GROUP_NAME") & "" = "#ditto#" Then
VerticalMergeWithPriorRow(oTable, row, 1)
Else
oTable.Cell(row, 1).Range.Text = dataRow("GROUP_NAME") & ""
End If
oTable.Cell(row, 2).Range.Text = dataRow("COLUMN_NAME") & ""
Note that I am vertically merging cells, so I am limited to using the table.cell references.
Table.rows(nnn)` gives an exception.
The data processed by the code above starts with a data row with the keep_with_next_flag set to "K", so the code sets the cell paragraph format keepwithnext = true.
The next data row in a group would come with the group name = "#ditto#" and a keep_with_next_flag set to "K". As above, the code sets the cell paragraph format with keepwithnext = true. Since it's a ditto, the code will execute the VerticalMergeWithPriorRow function which just merges the current cell with the cell in the same column, but prior row.