CODE ANSWER (thanks to karma)
Private Sub UserForm_Initialize()
Call PopLB
End Sub
Sub PopLB()
With Sheets("helper")
.Cells.Clear
Master.UsedRange.Copy Destination:=.Range("B1")
addr = .UsedRange.Columns(1).Offset(0, -1).Address
.Range("A1").Value = Split(addr, ":")(0)
.Range("A1").AutoFill Destination:=.Range(addr), Type:=xlFillSeries
.Range(addr).Offset(0, 1).SpecialCells(xlBlanks).EntireRow.Delete '0, 1 is Request ID; 0, 2 is CTC File Number; 0, 3 is Work Order
End With
With listboxRequestsETR
.ColumnCount = 27
.ColumnWidths = "00,28,00,00,28,28,208,28,28,28," & _
"28,28,28,28,28,28,28,28,28,28," & _
"28,28,28,28,28,28,28"
LastRow = Range("A" & Rows.Count).End(xlUp).row
.RowSource = "helper!A2:AA" & LastRow
.ColumnHeads = True
End With
End Sub
I am hoping to create a UserForm that pulls data from certain columns in a main sheet Master (Sheet1) based on if there is any data within the specified column.
Ideally, the ListBox listboxRequestsETR would check if there is a Request ID available Column A, and display the data in the yellow and blue columns. In this case, Row 1 would be shown as the column heads for the ListBox, and the only row that would not transfer over to the ListBox would be Row 4.
On a separate note, I am hoping to apply the same logic to separate ListBoxes with Columns B and C, such that the condition of populating the ListBox would be based on whether there is any data in the specified cell (regardless of whether the data is General or Number).
Any help would be appreciated!
I am able to populate the ListBox with data, however when I attempt to filter the data I come up with errors. Below is the code I have so far that brings up the ListBox with all the data.
NEW CODE
Private Sub UserForm_Initialize()
Call AddDataToListBoxETR
End Sub
Private Sub AddDataToListBoxETR()
' Dim rg As Range
' Set rg = GetRangeETR
' With listboxRequestsETR
' .RowSource = rg.Address(external:=True)
' .ColumnCount = rg.Columns.Count
' .ColumnWidths = "75;90;100;110;75;125;125;100;100;100;100;100"
' .ColumnHeads = True
' .ListIndex = 0
' End With
Dim i As Long
For i = 2 To Master.Range("A100000").End(xlUp).Offset(1, 0).row
If Master.Cells(i, "A").Value <> 0 Then
Me.listboxRequestsETR.AddItem Master.Cells(i, 1).Value
Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 2) = Master.Cells(i, "D").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 3) = Master.Cells(i, "E").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 4) = Master.Cells(i, "F").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 5) = Master.Cells(i, "G").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 6) = Master.Cells(i, "H").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 7) = Master.Cells(i, "I").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 8) = Master.Cells(i, "J").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 9) = Master.Cells(i, "K").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 10) = Master.Cells(i, "L").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 11) = Master.Cells(i, "M").Value
'Me.listboxRequestsETR.List(listboxRequestsETR.ListCount - 1, 12) = Master.Cells(i, "O").Value
End If
Next i
End Sub
DESIRED OUTCOME
I recognize there is a column limit of 10, so the ability to display columns in the ListBox filtered by the condition (if Request ID is available in Row i) is what I am looking for
OLD CODE
Private Sub UserForm_Initialize()
Call AddDataToListBoxETR
End Sub
Private Sub AddDataToListBoxETR()
Dim rg As Range
Set rg = GetRangeETR
With listboxRequestsETR
.RowSource = rg.Address(external:=True)
.ColumnCount = rg.Columns.Count
.ColumnWidths = "75;90;100;110;75;125;125;100;100;100;100;100"
.ColumnHeads = True
.ListIndex = 0
End With
End Sub
Module
Option Explicit
Public Function GetRangeETR() As Range
Set GetRangeETR = Master.Range("A1").CurrentRegion
Set GetRangeETR = GetRangeETR.Offset(1).Resize(GetRangeETR.Rows.Count - 1)
End Function
I'm still not sure if I understand you correctly. Anyway, below is just my guess about what you want .....
The LB (ListBox) in the userform will show only the row with value in column A, hide column B and C, then show column D to Z. So, in the LB, there is H01 and then H04 to H26 while the row is coming from row 2,3,5 and 6. The LB doesn't show row 4 and 7 because in column A those rows are blank/no-value.
In the Userform there are 5 textbox to update/edit the row(N) of data for H04,H05,H06,H11 and H12.
Example:
The user click one item in the LB.
Then the textbox (tb) 1 to 5 show the corresponding column value which is clicked.
Then the user update/change the value in each tb, then click UPDATE button. The DATA is updated and the LB also updated.
Private Sub UserForm_Initialize()
Call PopLB
End Sub
Sub PopLB()
With Sheets("helper")
.Cells.Clear
Sheets("DATA").UsedRange.Copy Destination:=.Range("B1")
addr = .UsedRange.Columns(1).Offset(0, -1).Address
.Range("A1").Value = Split(addr, ":")(0)
.Range("A1").AutoFill Destination:=.Range(addr), Type:=xlFillSeries
.Range(addr).Offset(0, 1).SpecialCells(xlBlanks).EntireRow.Delete
End With
With LB
.ColumnCount = 27
.ColumnWidths = "00,28,00,00,28,28,28,28,28,28," & _
"28,28,28,28,28,28,28,28,28,28," & _
"28,28,28,28,28,28,28"
.RowSource = "helper!" & Sheets("helper").UsedRange.Address
End With
End Sub
Private Sub LB_Click()
tb1.Value = LB.List(LB.ListIndex, 4)
tb2.Value = LB.List(LB.ListIndex, 5)
tb3.Value = LB.List(LB.ListIndex, 6)
tb4.Value = LB.List(LB.ListIndex, 11)
tb5.Value = LB.List(LB.ListIndex, 12)
End Sub
Private Sub bt_Click()
If LB.ListIndex = -1 Then Exit Sub
With Sheets("DATA")
r = Range(LB.List(LB.ListIndex, 0)).Row
.Cells(r, 4).Value = tb1.Value
.Cells(r, 5).Value = tb2.Value
.Cells(r, 6).Value = tb3.Value
.Cells(r, 11).Value = tb4.Value
.Cells(r, 12).Value = tb5.Value
End With
Call PopLB
End Sub
In PopLB sub, first it clear the whole cells in sheet "helper".
Then it copy the data in sheet "DATA" to sheet "helper" cell B1.
Within sheet "helper":
it get the address of the usedrange as addr variable, then put the first split value of addr in cell A1, fill series the range of addr, then finally it delete the blank row of H01
within the LB:
It make 27 columns and set each column width. Please note that there are three zero value for the column width. One is to hide the id/row in column A, the other two is to hide H02 and H03. Finally it use the sheet helper used range as the row source for the LB.
The sub LB_Click will be triggered when the user click any item in the LB. It will populate textbox (tb) 1 to 5.
The bt_Click sub will be triggered when the user click the UPDATE button. It will update the corresponding value in the sheet DATA from the tb1 to tb5 value in the userform, then it call back the PopLB sub.
so, as you said :
this UF is meant to connect with an additional UF that can edit /
delete data in selected rows.
Although maybe it's not exactly what you mean, but this UF still can update/edit the data in sheet DATA although it use a helper sheet.
I am struggling with partial Match, the idea is to add a comment on each line if there is a match or not with the below row, result should be as on below picture
my struggle is with the part with Part Match, ex with B4 Value"87032610" and B5 "Payment 87032610", results which I want to have is txt in column C4 and C5 "Part Match"
so far my code :
Sub testRes()
Dim i As Integer
i = 2
Do While ThisWorkbook.Worksheets("test").cells(i, 1) <> ""
If ThisWorkbook.Sheets("test").cells(i, 1) Like "*" & ThisWorkbook.Sheets("test").cells(i + 1, 1) Then
ThisWorkbook.Sheets("test").cells(i, 1).Offset(0, 1).Value = "Yes"
ThisWorkbook.Sheets("test").cells(i + 1, 1).Offset(0, 1).Value = "Yes"
Else
ThisWorkbook.Sheets("test").cells(i, 1).Offset(0, 1).Value = "No"
ThisWorkbook.Sheets("test").cells(i + 1, 1).Offset(0, 1).Value = "No"
End If
i = i + 1
Loop
End Sub
Thank you :-)
Check variable payment texts against invoice number
It's less time consuming to loop through an array than cells by means of VBA. In order to check for partial findings just change the direction of Like comparisons (completed by surrounding wildcards *), as the invoice number represents the smaller part than variable payment texts (of commercial clients).
Sub testRes()
'[0]get variant 1-based 2-dim data field array
Dim rng As Range
Set rng = Sheet1.Range("B2:B9") ' << change to wanted range reference
Dim v
v = rng.Value
'[1]check invoice number against changing payment texts
Dim i As Long
Dim invoice, pmt
For i = 1 To UBound(v) - 1 Step 2
invoice = v(i, 1)
pmt = v(i + 1, 1)
If invoice = pmt Then
v(i, 1) = "Yes"
ElseIf pmt Like "*" & invoice & "*" Then
v(i, 1) = "Part Match"
Else
v(i, 1) = "No"
End If
v(i + 1, 1) = v(i, 1)
Next i
'[2]write results
rng.Offset(0, 1) = v
End Sub
I am trying to create a listbox with the column headers of my data to use that as an input from the user on which columns the user wants displayed in the final result. So far I've been able to divide the listbox into two columns and populate the relevant data in it, but on selecting the items, it is selecting the complete row and not individual items.
Can you please let me know how can I select individual items from a multicolumn listbox.
Here's the code :
Private Sub ListBox1_Enter()
Dim firstrow As Range
Dim c_no As Integer
Dim Arr() As String
Dim i As Integer
Dim j As Integer
Set firstrow = ThisWorkbook.Sheets("Tag Dump").Range("A1:AR1")
With firstrow
c = .Cells.Count
End With
Application.ScreenUpdating = False
ReDim Preserve Arr(c, 2)
'If WorksheetFunction.IsEven(c) = True Then
For i = 1 To c / 2
Arr(i, 1) = Sheets("Tag Dump").Cells(1, i).Value
Arr(i, 2) = Sheets("Tag Dump").Cells(1, i + (c / 2)).Value
'ElseIf WorksheetFunction.IsEven(c) = False Then
'End If
With ListBox1
.ColumnCount = 2
.Additem
.List(i - 1, 0) = Arr(i, 1)
.List(i - 1, 1) = Arr(i, 2)
End With
Next
With ListBox1
.ListStyle = fmListStyleOption
.Font = "Arial"
.MultiSelect = fmMultiSelectExtended
End With
Application.ScreenUpdating = True
End Sub
Here's an image of the result I'm getting:
Listbox selection
Thanks in advance.
Hello I am looking for help, I have one textbox and one listbox in an Excel Userform, it works flawlessly except for one small Detail: as soon as the results appear in the listbox they represent the search within all columns. The first column, however is hidden when I type in the textbox, how can I make sure the column remains visible during search?
Thanks in advance
Here is the code:
Private Sub UserForm_Initialize()
End Sub
Private Sub TextBox1_Change()
With Sheets("Sheet1")
lr = .Range("A" & Rows.Count).End(xlUp).Row
ReDim arr(1 To lr - 1)
ReDim sn(1 To lr - 1, 1 To 13)
For i = 1 To UBound(arr)
arr(i) = .Range("A" & i + 2) & " " & .Range("B" & i + 2) & " " & .Range("C" & i + 2) & " " & .Range("D" & i + 2) & " " & .Range("E" & i + 2) & " " & .Range("F" & i + 2)
If InStr(1, arr(i), TextBox1) > 0 Then
j = j + 1
For X = 2 To 8
sn(j, X - 1) = .Cells(i + 2, X)
Next
End If
Next
ListBox1.List = sn
End With
End Sub
Consistent Array Approach
Your original code shows a mixture of array and range loops when creating a filtered listbox list. In order to be more consistent here by looping through arrays only *) , you could refine your code as follows (e.g. using the same match check via Instr):
Userform Event procedure TextBox1_Change()
Private Sub TextBox1_Change()
Const STARTROW = 3
Dim i&, iCnt&, r&, c& ' array counters for "rows" and "columns"
Dim sn, tmp ' variant 2-dim 1-based arrays
With Sheets("Sheet1")
iCnt = .Range("A" & Rows.Count).End(xlUp).Row - STARTROW + 1 ' items counter
ReDim sn(1 To iCnt, 1 To 13) ' provide for filtered data array
For i = 1 To iCnt
'assign current data row to 2-dim 1-based temporary array
tmp = .Range("A" & (i + 2) & ":F" & (i + 2)) ' current data row (c.f. OP)
'compare search string with concatenated data string from current row
If InStr(1, concat(tmp), TextBox1.Text) > 0 Then ' check occurrence e.g. via Instr
r = r + 1 ' new rows counter
For c = 1 To UBound(tmp, 2) ' col counter
sn(r, c) = tmp(1, c) ' collect found row data
Next
End If
Next
ListBox1.List = sn ' assign array to .List property
End With
End Sub
Helper function concat() called by above event procedure
Private Function concat(ByVal arr, Optional ByVal delim$ = " ") As String
' Purpose: build string from 2-dim array row, delimited by 2nd argument
' Note: concatenation via JOIN needs a "flat" 1-dim array via double transposition
concat = Join(Application.Transpose(Application.Transpose(arr)), delim)
End Function
Notes
*) Looping through a range by VBA is always time consuming, so do this with arrays instead.
You might be also interested in the following solution demonstrating the use of the listbox Column property. By playing around this could help you to remove the superfluous blank rows in the listbox.
I have 2 adjacent listboxes that transfer items back and forth. Each listbox has a respective worksheet. Between each listbox and each worksheet, each selection transfers properly from the first item down until the last item. If the last item in either ListBox is selected to transfer to its adjacent listbox, the item transfers to its adjacent list (and sheet), however the rest of its originating list (and sheet data) disappear (UPDATE: only if one uses MultiSelect code for SingleSelect Property). I'm wondering if someone can see something in the code that I'm obviously overlooking. Below is my transfer code.
EDIT: ListBox1 was a MultiSelect and ListBox2 was a SingleSelect and the code was for purely MultiSelect ListBoxes. My working example (i.e. ListBox1 Properties) did not take that into account so I've updated the code below to reflect a transfer between MultiSelect an SingleSelect ListBoxes. I know it's a lot of code for such a simple procedure, but it's a necessity for my application, so I hope this can help someone.
Tested and works.
Private Sub MultiListToSingleList()
Set ws = Sheets(1)
With ListBox2 'SingleSelect ListBox
.ColumnCount = 7
.ColumnWidths = "0;0;150;20;0;0;0" 'contains different columns and
End with 'indexing than ListBox1
' can insert error handling and message boxes here
With ListBox1
For n = 0 To .ListCount - 1
If .Selected(n) Then
With ListBox2
.AddItem Me.ListBox1.List(n)
.List(ListBox2.ListCount - 1, 2) = ListBox1.List(n, 1)
.List(ListBox2.ListCount - 1, 3) = ListBox1.List(n, 2)
End With
End If
Next n
For n = .ListCount - 1 To 0 Step -1
If .Selected(n) Then
.RemoveItem n 'removes the item from ListBox1
ws.Rows(n + 2).EntireRow.Delete 'removes the row from the
End if 'ListBox1 source in Sheet 1
Next n
End With
SheetTransfer
End Sub
Private Sub SingleListToMultiList ()
Set ws = Sheets(2)
With ListBox1 'MultiSelect ListBox
.ColumnCount = 3
.ColumnWidths = "0;140;20"
End With
' can insert error handling and message boxes here
With ws
With ListBox2
For n = 0 To .ListCount - 1
If Me.ListBox2.Selected(n) Then 'adds ListBox2 item to
'ListBox1
Me.ListBox1.AddItem .List(n)
Me.ListBox1.List(ListBox1.ListCount - 1, 0) = .List(n, 0)
Me.ListBox1.List(ListBox1.ListCount - 1, 1) = .List(n, 2)
Me.ListBox1.List(ListBox1.ListCount - 1, 2) = .List(n, 3)
End If
Next n
For n = 0 To .ListCount - 1
If .Selected(n) Then
.RemoveItem n 'removes the ListBox2 item
ws.Rows(n + 2).EntireRow.Delete 'removes the row from the
End if 'ListBox2 source in Sheet 2
Next n
End With
End With
SheetTransfer
End Sub
Private Sub SheetTransfer() 'moves the ListBox items to respective sheet sources
Set ws = Sheets(1)
With ws
For n = 0 To ListBox1.ListCount - 1
.Cells(n + 2, 1).Value = Me.ListBox1.List(n, 0)
.Cells(n + 2, 2).Value = Me.ListBox1.List(n, 1)
.Cells(n + 2, 3).Value = Me.ListBox1.List(n, 2)
Next n
FillListBox1
For n = 0 To ListBox2.ListCount - 1
wb.Sheets(2).Cells(n + 2, 3).Value = Me.ListBox2.List(n, 2)
wb.Sheets(2).Cells(n + 2, 4).Value = Me.ListBox2.List(n, 3)
Next i
End With
CheckLists
End Sub
Private Sub CheckLists() 'addtnl routine to check if listbox is truly
'empty...otherwise header row will show up if listbox has no items
Set ws = Sheets(2)
Set rng = ws.Range("A2")
With ws
ListBox1.Clear
ListBox2.Clear
If WorksheetFunction.CountA(rng) <> 0 Then
FillListBox2 'use List Property not RowSource
If WorksheetFunction.CountA(Sheets(1).Range("A2")) <> 0 Then
FillListBox1 'use List Property not RowSource
Else
Me.ListBox1.Clear
End If
Else
Me.ListBox2.Clear
FillListBox1 'in my application, ListBox1 fills from a lookuplist
End If
End With
End Sub