How to get selected value in multicolumn listbox - vba

I have a multicolumn listbox in my userform and I would like to get all the values of the elements which are in the selected row in the listbox.Here is my userform:
Just like in the photo, I want to select one line then I will click button Associer and I could get the information of this row. I can just get the first column which is CAN20168301436 I want to get the information from the whole line. How can I do it? Here is my button clicked event:
Private Sub CommandButton3_Click()
a = ListBoxResultatFind.Text
End Sub

you can use this code
Private Sub CommandButton3_Click()
Dim strng As String
Dim lCol As Long, lRow As Long
With Me.ListBox1 '<--| refer to your listbox: change "ListBox1" with your actual listbox name
For lRow = 0 To .ListCount - 1 '<--| loop through listbox rows
If .selected(lRow) Then '<--| if current row selected
For lCol = 0 To .ColumnCount - 1 '<--| loop through listbox columns
strng = strng & .List(lRow, lCol) & " | " '<--| build your output string
Next lCol
MsgBox "you selected" & vbCrLf & Left(strng, (Len(strng) - 1)) '<--| show output string (after removing its last character ("|"))
Exit For '<-_| exit loop
End If
Next lRow
End With
End Sub

No need to loop the entire list - in order to get the selected item row you can use the ListIndex property. Then you can use the List(Row, Column) property to retreive the data, as in the examples by #DragonSamu and #user3598756:
'***** Verify that a row is selected first
If ListBoxResultatFind.ListIndex > -1 And ListBoxResultatFind.Selected(ListBoxResultatFind.ListIndex) Then
'***** Use the data - in my example only columns 2 & 3 are used
MsgBox ListBoxResultatFind.List(ListBoxResultatFind.ListIndex, 1) & ":" & ListBoxResultatFind.List(ListBoxResultatFind.ListIndex, 2)
End If

With a single column you can retrieve the value as below:
Dim str as String
str = me.ListBox1.Value
With a multicolumn you can retrieve the value like this:
Dim strCol1 as String
Dim strCol2 as String
Dim strCol3 as String
strCol1 = ListBox1.List(0, 1)
strCol2 = ListBox1.List(0, 2)
strCol3 = ListBox1.List(0, 3)
or you can add all the data into 1 String:
Dim strColumns as String
strColumns = ListBox1.List(0, 1) + " " + ListBox1.List(0, 2) + " " + ListBox1.List(0, 3)

It's a 6column list box and the 3rd column would be the multiplier hence the "(x)". You may also rearrange the list to how you like it.
Private Function selList() As String
Dim i As Long
For i =LBound(lstListBox1.List) To UBound(lstListBox1.List)
If lstListBox1.Selected(i) Then
selList = selList & lstListBox1.List(i) & " " & lstListBox1.List(i, 1) _
& "(x" & lstListBox1.List(i, 3) & ")" & " " & lstListBox1.List(i, 2) & " " & lstListBox1.List(i, 4) & ", "
End If
Next i
If selList= "" Then
selList= ""
Else
selList= Left(selList, Len(selList) - 2)
End If
MsgBox selList
End Function

Related

Format pasted rows within userforum-textbox into concatenation or borderline?

I get a mismatch error in this line :
row_str = Join(cell_rng, Chr(10))
Thank you. I am intermediate.
I attached a piece of the code below:
Dim last_row As String
Dim last_col As String
Dim office_str As String
Dim lookupVal As String
Dim i As Long
Dim seperate_cells, cell_rng As Range
Dim r As Range
Dim row_str As String
With Contacts
For i = 2 To last_row
Set cell_rng = Rows(i & ":" & i + 1)
For Each r In cell_rng.Rows
seperate_cells = cellsSeparator(r.SpecialCells(xlCellTypeConstants))
If row_str = "" Then
row_str = Join(cell_rng, Chr(10))
Else
row_str = row_str & vbLf & Join(cell_rng, Chr(10))
End If
Next
Debug.Print row_str
Client_Finder.result.Text = Client_Finder.result.Text & vbLf & row_str
Next i
End With
````
Please try the next way. It will place the values of the necessary specific row in the text box, each value separated by " | ":
Sub testSeparatorsBetweenRowCells()
'your existing code...
Dim arr, rngR As Range
For i = 2 To last_row
lookupVal = cells(i, office_str)
' Compare ComboBox with the range from the spreadsheet
If lookupVal = Office_Code Then
Set rngR = rows(i & ":" & i).SpecialCells(xlCellTypeConstants) 'Set a range which will return all cells value in the row, except the empty ones
arr = arrCells(rngR) 'call a function able to make an array from the range set in the above line
Client_Finder.result.Text = Client_Finder.result.Text & vbLf & Join(arr, " | ") 'add the text obtained by joining the array to the next line of existing text
End If
Next i
End Sub
Function arrCells(rng As Range) As Variant
Dim arr, Ar As Range, i As Long, C As Range
ReDim arr(rng.cells.count - 1) 'ReDim the array to be filled as the range cells number.
'- 1, because the array is 0 based...
For Each Ar In rng.Areas 'iterate between the range areas
For Each C In Ar.cells 'iterate between cells of each area
arr(i) = C.value: i = i + 1 'put each cell value in the array
Next
Next
arrCells = arr 'make the function returning the arr
End Function
If the text in the text box still goes on the next line, try making the text box property WordWrap False. If you cannot see all the text, make the textbox wider or decrease its font size.
Please, test it and send some feedback.
Edited:
Please, try understanding the next piece of code, able to deal with copying more rows at once:
Sub testCopyingMoreRows()
Dim sh As Worksheet, i As Long, rng As Range, r As Range, arr, strRow As String
Set sh = ActiveSheet
i = 9
Set rng = sh.rows(i & ":" & i + 1)
'you ca select cells, rows (even not consecutive) and use:
'Set rng = Selection.EntireRow 'just uncomment this code line...
'extract rows and paste their contents (exept the empty cells) in Imediate Window
For Each r In rng.rows
arr = arrCells(r.SpecialCells(xlCellTypeConstants))
If strRow = "" Then
strRow = Join(arr, " | ")
Else
strRow = strRow & vbLf & Join(arr, " | ")
End If
Next
Debug.Print strRow
'instead returning in Imediate Window, you can do it in your text box (uncomment the next line):
'Client_Finder.result.Text = Client_Finder.result.Text & vbLf & strRow
End Sub
The code uses the same function arrCells...

Apply vba to multiple cells

I have a code that can generate page number on cells.
But I want it apply to mutiple cells in one time instead of single cells.
Sub pagenumber()
'updateby Extendoffice 20160506
Dim xVPC As Integer
Dim xHPC As Integer
Dim xVPB As VPageBreak
Dim xHPB As HPageBreak
Dim xNumPage As Integer
xHPC = 1
xVPC = 1
If ActiveSheet.PageSetup.Order = xlDownThenOver Then
xHPC = ActiveSheet.HPageBreaks.Count + 1
Else
xVPC = ActiveSheet.VPageBreaks.Count + 1
End If
xNumPage = 1
For Each xVPB In ActiveSheet.VPageBreaks
If xVPB.Location.Column > ActiveCell.Column Then Exit For
xNumPage = xNumPage + xHPC
Next
For Each xHPB In ActiveSheet.HPageBreaks
If xHPB.Location.Row > ActiveCell.Row Then Exit For
xNumPage = xNumPage + xVPC
Next
ActiveCell = "Page " & xNumPage & " of " & Application.ExecuteExcel4Macro("GET.DOCUMENT(50)")
End Sub
What can i do for this? Is it also possible for apply the code to highlighted cells?
At the end write this:
Range("A1:B10")="Page "&xNumPage&" of "& Application.ExecuteExcel4Macro("GET.DOCUMENT(50)")
Instead of:
ActiveCell = "Page "&xNumPage& " of " & Application.ExecuteExcel4Macro("GET.DOCUMENT(50)")
Making sure that Range("A1:B10") is the range to which you want to apply the numbers.
How to avoid using Select in Excel VBA

Sort a listbox with click on a button

I need some help with sorting a listbox in my form.
I have a listbox (LstPlanung) that lists all entries of a table.
HID SID DATUM ZEIT
AAA AA 20.02.2017 15:00
BBB BB 16.02.2017 17:00
... .. .......... .....
Is there a chance to sort the listbox with a button by "DATUM" ?
Listbox columns are text only, so even if the listbox would have in-built sorting, it wouldn't work with dd.mm.yyyy dates.
To sort correctly by dates (or numbers), the sorting must be done in the RowSource property.
I suggest to use the following code by John Spencer to sort by any column via right-click.
It's super-useful and I use it in many listboxes.
Source: http://www.utteraccess.com/forum/index.php?showtopic=1953978
Public Sub sSortListBox(anyListbox As Control, Button As Integer, Shift As Integer, X As Single)
'Purpose: Sort list box by column when column is right-clicked
'Author: Copyright by John Spencer
'Version Date: 04-14-2004
'Limitations:
' No Horizontal scroll bar in listbox
' RowSource must be query
' Uses DAO code; not tested with ADP
'Permission to use in applications is granted to all
'with the understanding that credit is given to the author.
'No warrantee or guaranty is given - use at your own risk.
'
'Code to sort list in ascending/descending order
'depending on which column is right-clicked
'and whether shift key is pressed.
'Uses the SQL syntax of specifying a column number as the sort column -
' SELECT ... FROM ... ORDER BY N
'- where N is integer reflecting the position of a field in SELECT clause.
'Install call to this code in the Mouse Down event of a listbox.
'Example -
' sSortListBox Me.SomeListbox, Button, Shift, X
'---------------------------------------------------------------------
'---------------------------------------------------------------------
'In the listbox's Mouse Up event add code to cancel the Mouse up event.
' If Button = acRightButton Then DoCmd.CancelEvent
'That line will stop any popup menu from appearing.
'---------------------------------------------------------------------
'---------------------------------------------------------------------
Dim strSQL As String
Dim vGetWidths As Variant
Dim vArWidths() As Variant
Dim iColCount As Integer, iColNumber As Integer
Dim i As Integer
Dim iColWidthSum As Integer
Dim iUndefined As Integer
Dim iDefaultWidth As Integer
Dim strOrderBy As String
Dim xStr As Long
Const strListSeparator As String = ";" 'list Separator
On Error GoTo ERROR_sSortListBox
If Button <> acRightButton Then
'only sort based on right button being clicked
ElseIf anyListbox.RowSourceType <> "table/query" Then
'only sort listbox based on queries
MsgBox "List box must use a query as it's row source"
ElseIf Len(anyListbox.RowSource) = 0 Then
'Nothing there, so ignore the click
ElseIf Not (InStr(1, Trim(anyListbox.RowSource), "Select", vbTextCompare) = 1 _
Or InStr(1, Trim(anyListbox.RowSource), "Parameters", vbTextCompare) = 1) Then
'If rowsource does not start with SELECT or PARAMETERS then
'assume it is a table not a query
MsgBox "List box must use a query as its row source"
ElseIf anyListbox.columnCount > DBEngine(0)(0).CreateQueryDef("", anyListbox.RowSource).Fields.Count Then
'Column count must be correctly set, otherwise this routine
'could cause errors. Column count set less than actual field count
'will cause subscript errors. Column count set higher than actual
'field count can cause listbox to display nothing if "Extra" column
'is clicked.
MsgBox "List box column count does not match query field count!"
Else 'passed the error checks
With anyListbox
iColCount = .columnCount
ReDim vArWidths(iColCount - 1, 0 To 1)
'Parse the column widths into an array.
vGetWidths = Split(.ColumnWidths, strListSeparator, -1, vbTextCompare)
'Assign values to array that holds length and running sum of length
For i = 0 To UBound(vGetWidths)
iColWidthSum = iColWidthSum + Val(vGetWidths(i))
vArWidths(i, 1) = iColWidthSum
vArWidths(i, 0) = vGetWidths(i)
Next i
'Adjust any colwidths that are unspecified:
'The minimum is the larger of 1440
'or the remaining available width of the list box
'divided by number of columns with unspecified lengths.
For i = 0 To iColCount - 1
If Len(vArWidths(i, 0) & vbNullString) = 0 Then
iUndefined = iUndefined + 1
End If
Next i
If iUndefined <> 0 Then
iDefaultWidth = (.Width - iColWidthSum) / iUndefined
End If
If iDefaultWidth > 0 And iDefaultWidth < 1440 Then
MsgBox "Sorry! Can't process listboxes with horizontal scrollbars!"
Exit Sub 'Horizontal scroll bar present
Else
'recalculate widths and running sum of column widths
iColWidthSum = 0
For i = 0 To iColCount - 1
If Len(vArWidths(i, 0) & vbNullString) = 0 Then
vArWidths(i, 0) = iDefaultWidth
End If
iColWidthSum = iColWidthSum + Val(vArWidths(i, 0))
vArWidths(i, 1) = iColWidthSum
Next i
End If
'Set right edge of last column equal to width of listbox
vArWidths(iColCount - 1, 1) = .Width
'Determine which column was clicked
For i = 0 To iColCount - 1
If X <= vArWidths(i, 1) Then
iColNumber = i
Exit For
End If
Next i
iColNumber = iColNumber + 1 'adjust since i is 0 to n-1
'rebuild sql statement
If iColNumber > 0 And iColNumber <= iColCount Then
strSQL = Trim(.RowSource)
If right(strSQL, 1) = ";" Then strSQL = Left(strSQL, Len(strSQL) - 1)
xStr = InStr(1, strSQL, "Order by", vbTextCompare)
If xStr > 0 Then
strOrderBy = Trim(Mid(strSQL, xStr + Len("Order by")))
strSQL = Trim(Left(strSQL, xStr - 1))
End If
'Build the appropriate ORDER BY clause
If Shift = acShiftMask Then
'If shift key is down force sort to desc on selected column
strOrderBy = " Order By " & iColNumber & " Desc"
ElseIf Len(strOrderBy) = 0 Then
'If no prior sort then sort this column ascending
strOrderBy = " Order by " & iColNumber & " Asc"
ElseIf InStr(1, strOrderBy, iColNumber & " Asc", vbTextCompare) > 0 Then
'If already sorted asc on this column then sort descending
strOrderBy = " Order By " & iColNumber & " Desc"
ElseIf InStr(1, strOrderBy, iColNumber & " Desc", vbTextCompare) > 0 Then
'If already sorted desc on this column then sort Ascending
strOrderBy = " Order By " & iColNumber & " Asc"
Else
strOrderBy = " Order by " & iColNumber & " Asc"
End If
strSQL = strSQL & strOrderBy
Debug.Print strSQL
.RowSource = strSQL
End If 'Rebuild SQL if col number is in range 1 to number of columns
End With 'current list
End If 'Passed error checks
EXIT_sSortListBox:
Exit Sub
ERROR_sSortListBox:
Select Case Err.Number
Case 9 'Subscript out of range
MsgBox Err.Number & ": " & Err.Description & _
vbCrLf & vbCrLf & "Check column count property of list box.", vbInformation, "ERROR: sSortListBox"
Case Else 'unexpected error
MsgBox Err.Number & ": " & Err.Description, vbInformation, "ERROR: sSortListBox"
End Select
Resume EXIT_sSortListBox
End Sub
and in the form:
Private Sub myList_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Call sSortListBox(Me.myList, Button, Shift, X)
End Sub
Private Sub myList_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = acRightButton Then DoCmd.CancelEvent
End Sub
You have to use VBA to manage the RowSource of LstPlanung.
In the simplest scenario where LstPlanung does not already have an ORDER BY, you could just use:
Me.LstPlanung.RowSource=Me.LstPlanung.RowSource & " ORDER BY Datum"
Me.LstPlanung.Requery
If it already has an ORDER BY then you will have to re-create the RowSource (probably by copy paste the existing one in your code and replacing whatever is in the ORDER BY part with 'Datum').

vba excel sort combobox items by cell value and auto select the corresponding one

Been trying to find a way to populate a combobox by reading a range and only choosing the cells that have some value.
I have some code that creates a button every row at column S to open a user form with a combobox.
in column "H" from row 5 down, I have cells filled with colors (text)
My objective is that the itemlist of the combobox shows by default not the 1st item from the range (starting at H5) but the corresponding item from each cell
Here's my piece of code for populating the combobox1:
Sub testingcombo()
Dim c As Range
Dim index As Integer
ComboBox1.Clear
index = ComboBox1.ListIndex
With Worksheets("sheet1")
For Each c In .Range(.Range("H5"), .Range("H" & .Rows.Count).End(xlUp))
If c.Value <> vbNullString Then ComboBox1.AddItem c.Value
Next c
End With
Me.ComboBox1.ListIndex = 0 '(this only chooses by default the 1st entry of the range)
Thks,
Edgar
In the code associated with the buttons, write this (not my code. Look here):
Public rs As Integer
Sub MyButton()
Dim b As Object
Dim cs As Integer
Dim ss, ssv As String
Set b = ActiveSheet.Buttons(Application.Caller)
With b.TopLeftCell
rs = .Row
cs = .Column
End With
ss = Left(Cells(1, cs).Address(False, False), 1 - (ColNumber > 26)) & rs
ssv = Range(ss).Value
'MsgBox "Row Number " & rs & " Column Number " & cs & vbNewLine & _
'"Cell " & ss & " Content " & ssv
UserForm1.Show
End Sub
And then in the UserForm this:
Public Sub UserForm_Initialize()
Dim c As Range
Dim index As Integer
ComboBox1.Clear
index = ComboBox1.ListIndex
With Worksheets("sheet1")
For Each c In .Range(.Range("H5"), .Range("H" & .Rows.Count).End(xlUp))
If c.Value <> vbNullString Then ComboBox1.AddItem c.Value
Next c
End With
Me.ComboBox1.ListIndex = rs - 5
End Sub

inputting multiple rows in a textbox and displaying each value in a different row of a single column

I am trying to input multiple rows in a textbox and display each value in a different row of a single column in excel, My code inputs all values in different rows of the column. Code is as follows
Private Sub CommandButton1_Click()
Dim i As Variant
For Each i In Split(TextBox1.Text, vbCrLf)
With Range("A1")
lastrow = ThisWorkbook.Worksheets("sheet1").Range("A" & Rows.Count).End(xlUp).Row + 1
ThisWorkbook.Worksheets("sheet1").Range("A" & lastrow).Value = TextBox1.Value
End With
Next
TextBox1.Text = ""
End Sub
Any suggestions please? your response will be highly appreciated
if I understand it correctly you want to have each line in the text box in its own row so this would work
Private Sub CommandButton1_Click()
Dim i As Variant
Dim rowCounter As Long
rowCounter = 1
For Each i In Split(TextBox1.Text, vbCrLf)
'start at row 1 column A
Cells(rowCounter, 1).Value = i
rowCounter = rowCounter + 1
Next
TextBox1.Text = ""
End Sub
There is no need to iterate. Split returns an array that you can use to fill all the rows at once.
Private Sub CommandButton1_Click()
Dim Target As Range
Dim Data As Variant
If TextBox1.Text = "" Then Exit Sub
Data = Split(TextBox1.Text, vbCrLf)
With Worksheets("sheet1")
Set Target = .Range("A" & .Rows.Count).End(xlUp)
If Target.Value <> "" Then Set Target = Target.Offset(1)
Target.Resize(UBound(Data) + 1).Value = Application.Transpose(Data)
End With
TextBox1.Text = ""
End Sub