I am adding more than 10 columns to my listbox in Excel VBA. I keep getting run-time error '380'-Invalid property value. It works properly until column 9 in listbox. I couldn`t find any proper solution for this anywhere else. Does anyone know a workaround for this issue?
Private Sub txtSearch_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal
Shift As Integer)
Dim rng As Range
Set rng = Range("Lookup")
Dim rw
Dim strText As String
strText = LCase(txtSearch.Text)
With ListBox1
.RowSource = ""
.ColumnCount = 12
For Each rw In rng.Rows
If InStr(LCase(Cells(rw.Row, 4)), strText) Then
.AddItem Cells(rw.Row, 1).Value
.List(ListBox1.ListCount - 1, 1) = Cells(rw.Row, 2).Value
.List(ListBox1.ListCount - 1, 2) = Cells(rw.Row, 3).Value
.List(ListBox1.ListCount - 1, 3) = Cells(rw.Row, 4).Value
.List(ListBox1.ListCount - 1, 4) = Cells(rw.Row, 5).Value
.List(ListBox1.ListCount - 1, 5) = Cells(rw.Row, 6).Value
.List(ListBox1.ListCount - 1, 6) = Cells(rw.Row, 7).Value
.List(ListBox1.ListCount - 1, 7) = Cells(rw.Row, 8).Value
.List(ListBox1.ListCount - 1, 8) = Cells(rw.Row, 9).Value
.List(ListBox1.ListCount - 1, 9) = Cells(rw.Row, 10).Value
.List(ListBox1.ListCount - 1, 10) = Cells(rw.Row, 11).Value
.List(ListBox1.ListCount - 1, 11) = Cells(rw.Row, 12).Value
.List(ListBox1.ListCount - 1, 12) = Cells(rw.Row, 13).Value
End If
Next
End With
End Sub
I don't know if this will fix everything, but it will definitely clean it up a bit. Also, I am not sure what worksheet you are pulling Cells(rw.Row, 2).value from. But they may have something to do with why it stops part way through. Also, to clean it up a bit, try an additional For Statement.
Private Sub txtSearch_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Dim rng As Range: Set rng = Range("Lookup")
Dim rw
Dim strText As String: strText = LCase(txtSearch.Text)
With ListBox1
.RowSource = ""
.ColumnCount = 21
For Each rw In rng.Rows
If InStr(LCase(Cells(rw.Row, 4)), strText) Then
.AddItem Cells(rw.Row, 1).Value
For x = 1 To 12 '''Change Worksheet to your Worksheet name
.List(ListBox1.ListCount - 1, x) = Worksheets("Sample").Cells(rw.Row, x + 1).Value2
Next x
End If
Next
End With
End Sub
If this doesn't help, try what #Cyril said with the array.
Just came back to you... a bit long, but here's the general thoughts...
This all goes in the code for the ActiveX Control:
Option Explicit
Sub ListBox1_Click()
Dim rw As Range, strtext As String
Dim arr As Variant, ai As Long, aj As Long
Dim brr As Variant, bi As Long, bj As Long
strtext = "a" 'I used this when i did my testing
ReDim arr(11, 0)
For Each rw In Range("rng")
If InStr(LCase(rw.Value), strtext) Then
aj = findaj(arr)
If Not IsEmpty(arr(1, aj)) Then
aj = aj + 1
ReDim Preserve arr(11, aj)
End If
For ai = 1 To 11
arr(ai, aj) = Cells(rw.Row, ai + 1).Value
Next ai
End If
Next rw
ReDim brr(aj, 11)
For bi = 0 To aj
For bj = 1 To 11
brr(bi, bj) = arr(bj, bi)
Next bj
Next bi
ListBox1.ColumnCount = 11
ListBox1.List = brr
End Sub
Private Function findaj(ByVal brr As Variant)
Dim j As Long, meow As String
j = 0
Do While True
On Error GoTo toll
j = j + 1
meow = brr(1, j)
Loop
toll:
findaj = j - 1
End Function
So there's a lot going on here... I use two separate arrays, due to how redimming arrays works in VBA. You can only update the second element of the array, so arr(ai,aj) can only have aj updated when I redim preserve while adding a new row to my array.
So we make an array (arr) that captures the data based on VBA's limitations. Within that array, we use a function, findaj, which intentionally traps an error to determine the appropriate last column in arr (i italicized the use of column, as it's not truly the case, but it makes sense spatially when thinking about it).
You then convert the array arr to brr in the appropriate order of columns/rows.
Afterwards, you make your .list = brr.
Related
I have a problem with displaying multiple columns in a ListBox in my UserForm.
Everything is working until my numbers of column is max 10.
My code:
Private Sub FindButton_Click()
ListBoxResult.Clear
ListBoxResult.ColumnCount = 14
Dim RowNum As Long
RowNum = 1
Do Until Sheets("db").Cells(RowNum, 1).Value = ""
If InStr(1, Sheets("db").Cells(RowNum, 2).Value, FindDMC.Value, vbTextCompare) > 0 Then
On Error GoTo next1
ListBoxResult.AddItem Sheets("db").Cells(RowNum, 1).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 2) = Sheets("db").Cells(RowNum, 2).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 3) = Sheets("db").Cells(RowNum, 3).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 4) = Sheets("db").Cells(RowNum, 4).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 5) = Sheets("db").Cells(RowNum, 5).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 6) = Sheets("db").Cells(RowNum, 6).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 7) = Sheets("db").Cells(RowNum, 7).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 8) = Sheets("db").Cells(RowNum, 8).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 9) = Sheets("db").Cells(RowNum, 9).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 10) = Sheets("db").Cells(RowNum, 10).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 11) = Sheets("db").Cells(RowNum, 11).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 12) = Sheets("db").Cells(RowNum, 12).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 13) = Sheets("db").Cells(RowNum, 13).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 14) = Sheets("db").Cells(RowNum, 14).Value
ListBoxResult.List(ListBoxResult.ListCount - 1, 15) = Sheets("db").Cells(RowNum, 15).Value
End If
next1:
RowNum = RowNum + 1
Loop
End Sub
ListBoxResult.ColumnCount and properties is 14, also Column widths is ok.
After runing my code the failure code is Run-time error '380': Could not set the List property. Invalid property value. At first, I was thinking that maybe ListBoxes have limits for columns, but I found ListBoxes with 60 columns on the Internet.
I am trying also this, but still doesn't work:
Private Sub Browser_RMA_Initialize()
ListBoxResult.RowSource = "db!a1:z1"
ListBoxResult.ColumnCount = 14
ListBoxResult.ColumnWidths = "50;50;50;50;50;50;50;50;50;50;50;50;50;50;"
ListBoxResult.ColumnHeads = True
End Sub
Could you support me, please?
Assigning to .Columnproperty avoids transposing
As late addition to #Dy.Lee 's valid and already accepted array approach (see my comment), I demonstrate a way how to avoid both repeated redimming [4] and transposing [5]:
Option Explicit ' declaration head of UserForm code module
Private Sub FindButton_Click()
'[0] where to search
Const SearchCol As Long = 2 ' get search items from 2nd column
'[1] define data set
Dim data As Variant
data = Tabelle1.Range("A1").CurrentRegion ' << change to your project's sheet Code(Name)
Dim ii As Long: ii = UBound(data, 1) ' row count
Dim jj As Long: jj = UBound(data, 2) ' column count
'[2] provide for sufficient result rows (array with converted row : columns order)
Dim results() As Variant
ReDim Preserve results(1 To jj, 1 To ii) ' redim up to maximum row count ii
'[3] assign filtered data
Dim i As Long, j As Integer, n As Long
For i = 1 To ii
If InStr(1, data(i, SearchCol), FindDMC.Value, vbTextCompare) > 0 Then
'' If data(i, SearchCol) = FindDMC.Value Then ' exact findings
n = n + 1
For j = 1 To jj
results(j, n) = data(i, j)
Next
End If
Next i
'[4] fill listbox with results
With ListBoxResult
.Clear
.ColumnCount = 14
.ColumnWidths = "50;50;50;50;50;50;50;50;50;50;50;50;50;50;"
If n Then
'[4] redimension only a 2nd time (& last time)
ReDim Preserve results(1 To jj, 1 To n)
'[5] assign results to listbox'es .Column property
.Column = results ' << .Column property avoids unnecessary transposing
End If
End With
End Sub
The column index of the listbox also starts at 0. The index number of additem should be 0, and you specified 15 at the end, then the number of columns becomes 16, so an error occurs because column 14 is exceeded.
It would be convenient to use an array.
Private Sub FindButton_Click()
Dim Ws As Worksheet
Dim vDB As Variant, vResult()
Dim i As Long, j As Integer, n As Long
Set Ws = Sheets("db")
vDB = Ws.Range("a1").CurrentRegion
For i = 1 To UBound(vDB, 1)
If InStr(1, vDB(i, 2), FindDMC.Value, vbTextCompare) > 0 Then
n = n + 1
ReDim Preserve vResult(1 To 14, 1 To n)
For j = 1 To 14
vResult(j, n) = vDB(i, j)
Next
End If
Next i
With ListBoxResult
.Clear
.ColumnCount = 14
.ColumnWidths = "50;50;50;50;50;50;50;50;50;50;50;50;50;50;"
If n Then
If n = 1 Then
.Column = vResult
Else
.List = WorksheetFunction.Transpose(vResult)
End If
End If
End With
End Sub
I am trying to fill a series from a higher number in cell G2 (e.g "512") down to a lower number in Cell H2 (e.g "500"). I need the VBA code to run in Column J, producing the following this series as an example 512, 511, 510, 509, 508 ... down the column.
Here's a screenshot that describes what I need
Most examples I've found seems to be built for an increasing series (512, 513, 514....)
Any help to get this right will be helpful
For a VBA general solution, try this
Sub CreateSequence(StartValue As Long, EndValue As Long, OutputStart As Range, Optional ByVal StepBy As Long = 1)
Dim NumValues As Long
Dim dat As Variant
Dim i As Long
StepBy = Abs(StepBy)
If StepBy <= 0 Then Exit Sub
NumValues = Abs(StartValue - EndValue) \ StepBy + 1
ReDim dat(1 To NumValues, 1 To 1)
For i = 0 To NumValues - 1
dat(i + 1, 1) = StartValue + i * IIf(StartValue > EndValue, -StepBy, StepBy)
Next
OutputStart.Resize(UBound(dat, 1), 1).Value = dat
End Sub
Use it like this
Sub Demo()
CreateSequence Range("G2").Value, Range("H2").Value, Range("K2")
End Sub
A formula solution (Excel version 365)
=SEQUENCE(G2-H2+1,1,G2,-1)
hlRange = Sheets(2).Cells(2, 7).Value - Sheets(2).Cells(2, 8).Value + 1
' Fill series from max to min value
For j = 1 To hlRange
Sheets(2).Cells(j + 1, 10).Value = Sheets(2).Cells(2, 7).Value - j + 1
Next j
You can use the following code, it lets you add a a values to specify the steps you want to have.
https://i.stack.imgur.com/vSan5.jpg
Sub createNumList()
Dim i As Integer
Dim count As Integer
Dim cellValue As Integer
count = (ActiveSheet.Cells(2, 1).Value - ActiveSheet.Cells(2, 2).Value) / ActiveSheet.Cells(2, 3).Value
For i = 1 To count + 1
If i = 1 Then
ActiveSheet.Cells(i + 2, 5).Value = ActiveSheet.Cells(2, 1).Value
Else
ActiveSheet.Cells(i + 2, 5).Value = ActiveSheet.Cells(i + 1, 5).Value - ActiveSheet.Cells(2, 3).Value
End If
Next i
End Sub
I have some "multidimensional" data in an Excel spreadsheet that currently look like this below:
I'd like to transform this into rows with multiple columns:
I have tried multiple macros but still can't handle all dimensions to transpose correctly to rows, would be extremely grateful for any help :)
P.
Here's the code which works well without 3rd dimension (sales type):
Sub test()
Dim inputRange As Range, inputRRay As Variant
Dim outputRange As Range, outputRRay() As Variant
Dim outRow As Long, inCol As Long, inRow As Long
Set inputRange = ThisWorkbook.Sheets("Sheet1").Range("A1:AA150")
Set outputRange = ThisWorkbook.Sheets("Sheet2").Range("A1")
inputRRay = inputRange.Value
ReDim outputRRay(1 To (UBound(inputRRay, 1) * UBound(inputRRay, 2)), 1 To 3)
outRow = 0
For inCol = 2 To UBound(inputRRay, 2)
For inRow = 2 To UBound(inputRRay, 1)
If inputRRay(inRow, inCol) <> vbNullString And inputRRay(inRow, inCol) <> 0 Then
outRow = outRow + 1
outputRRay(outRow, 1) = inputRRay(1, inCol)
outputRRay(outRow, 2) = inputRRay(inRow, 1)
outputRRay(outRow, 3) = inputRRay(inRow, inCol)
End If
Next inRow
Next inCol
With outputRange.Resize(1, 3)
.EntireColumn.Clear
.Value = Array("Store", "Product", "QTY")
.Font.FontStyle = "Bold"
End With
With outputRange.Offset(1, 0).Resize(UBound(outputRRay, 1), UBound(outputRRay, 2))
.Value = outputRRay
End With
With outputRange.Parent
With Range(outputRange.Range("a1"), .Cells(.Rows.Count, outputRange.Column).End(xlUp)).Resize(, 3)
.Borders(xlEdgeLeft).LineStyle = xlContinuous
.Borders(xlEdgeTop).LineStyle = xlContinuous
.Borders(xlEdgeBottom).LineStyle = xlContinuous
.Borders(xlEdgeRight).LineStyle = xlContinuous
.Borders(xlInsideVertical).LineStyle = xlContinuous
.Borders(xlInsideHorizontal).LineStyle = xlContinuous
.Columns.AutoFit
End With
End With
End Sub
If you're specifically after a VBA solution, then I think you might be over-complicating your code.
Your range definition looks odd. I don't quite see why you're selecting columns "A" to "AA" when the data is only in the first 7 columns. And the data transfer should simply be a case of looping the rows and then each column to transfer into the output array. The desired code would look something like the below. I've left all the formatting bits out as you can tailor that to however you want it.
It does seem as if this code has been lifted from somewhere else and you've tried to adjust it. That's fine, but it does require you to understand what the original code is doing, and it's nor obvious to me that you have that understanding. You might get more success if you write your code from scratch so that you know where the loops are taking you.
Dim data As Variant
Dim fmt As String
Dim output() As Variant
Dim r As Long, x As Long, i As Long
'Define your range
With Sheet1
data = .Range(.Range("A1"), _
.Range("A" & .Rows.Count).End(xlUp)) _
.Resize(, 7) _
.Value2
End With
'Redim output array based on range size.
'Note the + 1 for a header.
ReDim output(1 To UBound(data, 1) * 6 + 1, 1 To 4)
'Write the header.
output(1, 1) = "Product"
output(1, 2) = "Store"
output(1, 3) = "Sales Type"
output(1, 4) = "Qty"
'Transfer the data to output array.
i = 2 'index of ouput array
For r = 3 To UBound(data, 1)
For x = 0 To 5 'loops the 5 columns in each row
output(i + x, 1) = data(r, 1) 'product
output(i + x, 2) = data(1, IIf(x < 3, 2, 5)) 'store
output(i + x, 3) = data(2, x + 2) 'type
output(i + x, 4) = data(r, x + 2) 'qty
Next
i = i + 6 'increment output index by 6 rows
Next
'Write output to sheet.
Sheet2.Range("A1") _
.Resize(UBound(output, 1), _
UBound(output, 2)) _
.Value = output
I have a small range of cells, C6:C10. I'm trying to apply an if statement to this range of cells using VBA code. Currently, my code takes the output of the if statement for the first cell (C6), and replicates that value for cells C7:C10. The if statement is correct, I'm just not sure how to apply it to a range of cells in a column.
Sub Cleanup()
Dim Segment As String
Dim i As Integer
Segment = ActiveCell(6, 3).Value
For i = 6 To 10
If Right(Left(Segment, 6), 1) = "/" Then
ActiveCell(i, 3).Value = Left(Segment, 5)
Else
ActiveCell(i, 3).Value = Left(Segment, 6)
End If
Next i
End Sub
It should be fine if you use Cells instead of ActiveCell, except that you'll have to change your loop to go from 7 to 10 or else it will over-write the original cell as well as C7:C10.
Sub Cleanup()
Dim Segment As String
Dim i As Integer
Segment = Cells(6, 3).Value
For i = 7 To 10
If Right(Left(Segment, 6), 1) = "/" Then
Cells(i, 3).Value = Left(Segment, 5)
Else
Cells(i, 3).Value = Left(Segment, 6)
End If
Next i
End Sub
Sub Cleanup()
Dim Segment As String
Dim i As Integer
Segment = Cells(i, 3).Value
For i = 7 To 10
If Right(Left(Segment, 6), 1) = "/" Then
cells(i, 3).Value = Left(Segment, 5)
Else
Cells(i, 3).Value = Left(Segment, 6)
End If
Next i
End Sub
here three (out of many other) possible codes, in simplicity order (the last being more simple than the first):
Option Explicit
Sub Cleanup()
Dim Segment As String
Dim i As Integer
For i = 6 To 10
Segment = Cells(i, 3).Value '<== Cells(i, 3) is the current cell as per the current row (i)
If Mid(Segment, 6, 1) = "/" Then
Cells(i, 3).Value = Left(Segment, 5)
Else
Cells(i, 3).Value = Left(Segment, 6)
End If
Next i
End Sub
Sub Cleanup2()
Dim i As Integer
For i = 6 To 10
With Cells(i, 3) 'avoid repetitions (and a variable, too) by using 'With' keyword and implying 'Cells(i, 3)' preceeds every dot (".") till next 'End With" statement
If Right(Left(.Value, 6), 1) = "/" Then
.Value = Left(.Value, 5)
Else
.Value = Left(.Value, 6)
End If
End With
Next i
End Sub
Sub Cleanup3()
Dim i As Integer
For i = 6 To 10
With Cells(i, 3)
.Value = Left(.Value, IIf(Mid(.Value, 6, 1) = "/", 5, 6)) ' use Iif function to avoid multiple lines. Also use 'Mid' function in lieu of 'Right(Left(..))'
End With
Next i
End Sub
I'm trying to make a loop that will go thru this data set.
This is how the output should look.
Im still getting the hang of loops, but this is what i have so far:
Private Sub CommandButton1_Click()
Dim i As Long, j As Long, k As Byte, iLines As Long
j = 1
For i = 1 To 25
For k = 1 To 8
If k = 1 Then
Cells(j, 10).Value = Len(Cells((j + 2), 1).Value) - Len(Replace(Cells((j + 2), 1).Value, ",", "")) + 1
Cells(i, 11).Value = "SET"
Cells(i, 12).Value = Cells(i, 1).Value
End If
Next k
Next i
End Sub
My problem is on my loop output at the moment. It only counts the commas in the first data set and not the other ones. Also where it outputs SET it copies down instead of just putting it in one cell. See Below.
I will probably have more question as i progress along. Thanks in advance for the help!
Try this:
Whenever possible get rid of the loop. I replaced it with a find to find the next cell with "HW" in it. It will automatically step from one "HW" to the Next.
When using steps anchor everything on the one row and expand selection using resize.
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Dim i As Long
Dim k As Long
Set ws = ActiveSheet
With ws
For i = 1 To 200
If Left(.Cells(i, 1).Value, 2) = "HW" Then
On Error Resume Next
k = .Range(.Cells(i + 1, 1), .Cells(200, 1)).Find("HW").Row
On Error GoTo 0
If k <= i Then k = 200
.Cells(i, 10).Value = Len(Cells((i + 2), 1).Value) - Len(Replace(Cells((i + 2), 1).Value, ",", "")) + 1
.Cells(i, 11).Value = "SET"
.Cells(i, 12).Resize(k - i).Value = .Cells(i, 1).Resize(k - i).Value
i = k - 1
End If
Next i
End With
End Sub