Loop Through 1st cell of each column in used range Excel VBA - vba

I have some sample data in a sheet, I want to get headers of each column in used range, Here is the sample
I never know the exact number of columns used, I need to get all headers (Customers, Managers, Managers-2....)from this sheet to show it to user.
I can loop through each cell in a used range like
For Each cell In ActiveWorkbook.Worksheets(SheetName).UsedRange
Next
but how can I loop though each column, and only read values from their 1st cell? as number of these lists can be one or more than one.

Replace your code by this one iterate over the first row of used range:
For Each cell In ActiveWorkbook.Worksheets(SheetName).UsedRange.Rows(1).Cells
...
Next

'Get a 2D array of header values
Dim aHeaders() As Variant
aHeaders = Sheet1.UsedRange.Rows(1).Value

It all depends on your data quality. Come across this numerous times.
If your headers are consistent, then you just need to resize to the first row. Something like:
Dim r as range, r1 as range
Set r = Range("A1").CurrentRegion.Resize(1)
Then do a for each for the r range.
For Each r1 in r
Next
You could also use an integer variable....
Dim i as integer
For I = 1 to r.Count
Next

Related

how to combine cell vertically in excel

It might be the most silly question in planet. how can I merge two cell values vertically in a repeated manner. as like this:
Column A and B has 400+ cells therefore it is impossible to do what I want to achieve manually.
Note: I want to merge B into A.
You can create a simple loop in VBA that runs through each cell in the data range then adds it to the output column
Sub Merge()
Dim data As Range
Dim cell As Range
Dim output As Range
Dim i As Integer
Set data = Range("A2:B4")
Set output = Range("D2")
i = 0
For Each cell In data
output.Offset(i, 0) = cell
i = i + 1
Next
End Sub
You can use the INDEX function to refer to each cell. If data is in A2:B4, this formula works in any column but must start in row 2 and can then be filled down:
=INDEX($A$2:$B$4,ROW()/2,MOD(ROW(),2)+1)
The formula uses the current row as a counter. On every even row it gets a value from the first column of data and on every odd row it gets a value from the second column of data. After every 2 rows it gets values from the next row of data.

i have a list of values mentioned in a column. i want to use vba to pick x number of values from that list

I have a list of values mentioned in a column. i want to use vba to pick x number of values from that list.the number x is mentioned in another cell. can you help me?
i have tried various formulas but no solution.
assuming myColumnRng is your range of cells in a columns containing your list of values, you can get its first N elements in a Variant array as follows:
myElements = Application.Transpose(myColumnRng .Resize(nElements).Value)
to give a little bit more of context:
Option Explicit
Sub main()
Dim myColumnRng As Range
Dim myElements As Variant
Dim iEl As Long
Set myColumnRng = Range("A1", Cells(Rows.count, "A").End(xlUp)) '<--| set your range as the column "A" one from row 1 down to last not empty row
myElements = Application.Transpose(myColumnRng .Resize(nElements).Value)
For iEl = 1 To UBound(myElements)
Debug.Print myElements(iEl)
Next
End Sub
Pick x values on random, or pick first x values in the list?

How do I Count Cells in Columns of a non-rectangular range

So I have a range that will be selected by a user. It will be two columns, usually not next to each other. I need to count the number of cells in each column of the selected range to determine if the number of cells in each column is equal. (If it's not I will need to adjust the range.)
For example, a User may select B5:B10 and D6:D9. So I need the code to return 6 and 4 respectively.
I've tried:
Set rng = Selection
rng.Columns(1).Count
this returns 1, which obviously isn't the number I need.
Thanks in advance!
You can use the Areas method of the Range object to get the areas of the range. Areas are groups of contiguous ranges within a non-contiguous range.
Set rng = Selection
For i = 1 to rng.Areas.Count
debug.print rng.Areas(i).Cells.Count
Next
There is caveat here that you may need to test for, and that is if the user selects, for example, A1:B10, with one mouse drag. Since this is a contiguous range, it will only have one Area and you will not get two distinct numbers. If you need to test for this, you can do something like the below.
Set rng = Selection
'non-contiguous ranges will always return one column, if there are mutiple columns both cell counts are equal by default
If rng.Columns.Count = 1 Then
For i = 1 to rng.Areas.Count
debug.print rng.Areas(i).Cells.Count
Next
End If
Dammit #Scott - just beat me to it.
Although I'm using the Rows property - if the user selects A1:B19 it will return 19 in a single element of the array, if they select A1:A19 and then B1:B19 it will return 19 in two elements of the array.
Using Cells it will return 38 in a single element, or 19 in two elements.
Sub Test()
Dim rRange As Range
Dim lRows() As Long
Dim x As Long
Set rRange = Selection
With rRange
ReDim lRows(1 To .Areas.Count)
For x = 1 To .Areas.Count
lRows(x) = .Areas(x).Rows.Count
Next x
End With
End Sub

Best way to return data from multiple columns into one row?

I have a sheet with just order numbers and another with order numbers and all of the data associated with those order numbers. I want to match the order numbers and transfer all of the available data into the other sheet. I've been trying to use loops and VLOOKUP but I'm having problems (plus I have 116 columns I want to transfer data from so my vlookup expression doesn't look very nice). Any advice would be appreciated!
this is what I have so far and I'm getting an object error.
I don't think it's the right way to go about it in general though.
Dim LookUpRange As Range
Dim row As Range
Set LookUpRange = Worksheets("batches").Range("B4:B1384")
Set row = Worksheets("batches").Range("C:DL")
For Each row In LookUpRange
row.Select
Selection.FormulaArray ="=VLOOKUP(RC[-1],OrderLvl!RC[-1]:R[1380]C[113],{2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,207,108,109,110,111,112,113,114,115},FALSE)"
Next row
End Sub
Please consider this VBA script to resolve your inquiry:
Sub LookupOuput()
Dim OrderNumberColumn As Range
Set OrderNumberColumn = Worksheets("batches").Range("B2:B1384")
Dim LookUpRange As Range
Set LookUpRange = Worksheets("OrderLvl").Range("C:DL")
Dim cell As Range
Dim FindResult As Range
For Each cell In OrderNumberColumn
If Not cell.Value2 = Empty Then
Set FindResult = LookUpRange.Find(what:=cell.Value2)
If Not FindResult Is Nothing Then
cell.Range("A1:DJ1").Value2 = LookUpRange.Rows(FindResult.row).Value2
End If
End If
Next cell
End Sub
Basically searches for each Order Number in the first sheet on the second sheet. This outputs (if search term exists) the cell that that string is found which we later refer to its row number to output the whole row to the first sheet. Cheers,
A regular VLOOKUP may be able to give you what you need, if you use a small trick...
Insert a row above the data table, and put sequential numbers in
each cell of that row. (ie, A1 = 1, B1 = 2, C1 = 3, etc...)
Do the same thing on your blank table.
Assuming that your first order number is in cell A2, put the following formula into B2: =VLOOKUP($A2,[other sheet name]!$A$1:$DZ$5000,B$1,0)
Drag this formula across all 116 columns, then down all however many rows you've got.
You'll need to adjust the ranges, obviously, but make sure that your lookup array starts in column A. (or alternatively, that your numbers start in the same column as the first column in your array.) Adding the numbers along the top allows you to change what column of the array you're referencing, just by dragging the cell formula.

Excel Range Reference

Let me preface this question by saying I am not super technical so much of my verbiage may seem obscure..
On sheet1 I have three seperate horizontal ranges of cells (3 seperate series of steps):
A1:D1
A2:C2
A3:E3
On sheet two, I'd like to link to create live links to these ranges, such that if I change information on sheet1, it will be automatically reflected in sheet2.
The catch is, that on sheet2, I want the ranges to be listed after one another in one row, to create one long series of steps.
Range1-->Range2-->Range3 (all on one row)
How do I ensure that if I add an additional step to, say, the first range on sheet1, that on sheet 2, the new cell will be added and the following cells will all be pushed over to the right by one cell?
To accommodate ranges that might grow, start from the first cell and then find the last occupied cell with End(xlToRight). Once you've found all the range extents, you can combine them with an array UDF:
Function ConcatRanges(ParamArray ranges()) As Variant()
Application.Volatile
Dim ret() As Variant
ReDim ret(1 To 1, 1 To (Application.Caller.Columns.Count))
Dim RetIdx&, i&, cell As Range
RetIdx = 1
For i = 0 To UBound(ranges)
For Each cell in Application.Range(ranges(i), ranges(i).End(xlToRight))
ret(1, RetIdx) = cell.Value
RetIdx = RetIdx + 1
Next
Next
For RetIdx = RetIdx To UBound(ret, 2)
ret(1, RetIdx) = vbNullString
Next
ConcatRanges = ret
End Function
For your example, you'd call it like this:
=ConcatRanges(Sheet1!A1, Sheet1!A2, Sheet1!A3)