Populate Variable with all values in Row - excel

I am trying to create a variable with all the cell values in used columns in Row 1.
Dim vaData As Variant
With wsSheet
vaData = .Range("B1:" & .Range(.Columns.Count & "1").End(xlRight).Column).Value
End With
I am getting a range failed error.
I have successfully done this for getting values in a column, BK.
vaData = .Range(.Range("BK2"), .Range("BK100").End(xlUp)).Value

Try this:
Dim vaData As Variant
With wsSheet
vaData = .Range("B1", .Cells(1, .Columns.Count).End(xlToLeft))
End With
The thing is you might have been confused between Range Object and Cells Property.
Refer to below Range Object Syntax I frequently use:
Range("Cell1", "Cell2") e.g. Range("A1", "A10")
Range("Cell1:Cell2") e.g. Range("A1:A10")
Range(Cells(1),Cells(2)) e.g. Range(Cells(1, 1), Cells(10, 1))
Above all evaluates to Range A1:A10. Now how to make it dynamic?
Examples:
Dynamic Last Row
With Sheet1
.Range("A1", .Range("A" & .Rows.Count).End(xlUp)) '~~> dynamic last row
.Range("A1:A" & .Range("A" & .Rows.Count).End(xlUp).Row) '~~> same as above
.Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)) '~~> same as above
End With
Dynamic Last Column
With Sheet1
.Range("A1", .Cells(1, .Columns.Count).End(xlToLeft)) '~~> same as my answer
.Range(.Cells(1, 1), .Cells(1, .Columns.Count).End(xlToLeft)) '~~> same as above
End With
Btw, another more complex approach is found here using Find Method.
The same approach was used here to find the last column.
Also you might want to check different ways on using Cells Property.

My first guess is that in the first example you are missing the column letter i.e. the formula will evaluate to something like
vaData =.Range("B1:10").Value 'Error!
Instead of
vaData =.Range("B1:B10").Value 'Ok!
Hope this helps...

Related

How can I turn a Range ("A1:A11") into (A"1: until empty cell")

I have tried to just set the range to ("A:A") but that makes the table too large and my computer freezes up, I have also tried to input a line like Range("A" & Rows.Count).End(xlUp).Offset(1) but that is not recognized by VBA.
Any help would be appreciated!
You need to first define your last row by referencing the last cell in the column then use .End(xlUp).row to find the last row number. You can then use that row number to build cell references, or even save the range as a range variable like I did:
Sub Last_Row_Example()
Dim LastRow As Long 'Last Row as a long integer
Dim RG As Range 'A range we can reference again and again very easily
'Consider renaming it to something more descriptive.
'for your particular situation
LastRow = Range("A" & Rows.Count).End(xlUp).Row ' Here we store the "LastRow" Number
Set RG = Range("A1:A" & LastRow) ' Here we build a range using the LastRow variable.
RG.Select
Application.CutCopyMode = False
ActiveSheet.ListObjects.Add(xlSrcRange, RG, , xlYes).Name = _
"Table3"
Range("Table3[[#All],[Ticker Name]]").Select
Selection.ConvertToLinkedDataType ServiceID:=268435456, LanguageCulture:= _
"en-US"
End Sub

Paste (dynamic) lookup formula in dynamic number of columns

I have a sheet "2018" and "2019" which i created previously. 2019 only differs from 2018 in that it may have some rows added and/or some deleted.
Form Cell "A3" and downwards i have skills listed and a "X" in the columns after if the person the column belongs to has this skill.
Now i need to fill the columns of 2019 with known X with formula below, first a bit of context code for the range selection part:
Dim rng As Range
Dim rngbegin As Range
Dim rngend As Range
Dim newrng As Range
Sheets("2018").Activate
Set rng = Application.InputBox '...and rest of the code
rng.Copy
Sheets("2019").Range("B:B").Insert Shift:=xlToRight
Sheets(2019).Activate
Set rngbegin = rng.Cells(3, 1)
Set rngend = rng.Cells(3000, rng.Columns.Count)
Set newrng = Range(rngbegin.Address & ":" & rngend.Address)
newrng.ClearContents 'To clear everything in the difined range but the headder rows
Here is a formula i could use if the columns wouldn't be varying.
Range("B3").Select
ActiveCell.Formula = "=IFERROR(LOOKUP(2,1/($A3='2018'!$A$3:D$5000),'2018'!$B$3:$B$5000),"")"
Range("B2").AutoFill Destination:=Range("B2:B" & Range("A" & Rows.Count).End(xlUp).Row)
The Formula works but i have the following problems:
1 - Required) I can't hardcode the formula for every column because the number of colums may change. (I store the number of columns as range var selected from the user via application.inputbox - that's how i inserted the colums in the new 2019 sheet)
2 - optional) I hardcoded the rows to a much higher number than are used because i didn't thnk of counting Column A and then use the range.count.Address(?) as end of the search vector. Just came into my mind lol
You will probably need to tweak a few addresses. I left much of your code unchanged so you can easily adapt what I have came up with for your purposes.
Sub Whatever()
With Sheets("2018")
' Get the address of the old range, not used later in the macro
iRows = .Cells(Rows.Count, 1).End(xlUp).Row
iCols = .Cells(3, Columns.Count).End(xlToLeft).Column
Set rngOld = Range(.Cells(3, 2), .Cells(iRows, iCols))
End With
With Sheets("2019")
' Get the address of the new range
iRows = .Cells(Rows.Count, 1).End(xlUp).Row
iCols = .Cells(2, Columns.Count).End(xlToLeft).Column
Set rngNew = Range(.Cells(3, 2), .Cells(iRows, iCols))
'Clear the new range
rngNew.Clear
' Populate the formula
' Not very elegant, VBA solution would probably look nicer
.Range("B3").Formula = "=IFERROR(if(LOOKUP(2,1/('2018'!$A$3:$A$" & iRows & " =$A3),'2018'!B$3:B$" & iRows & ")=""X"",""X"",""""),"""")"
'Fill the formula
Set rngTemp = .Range(.Cells(3, 2), .Cells(3, iCols))
rngTemp.FillRight
Set rngTemp = .Range(.Cells(3, 2), .Cells(iRows, iCols))
rngTemp.FillDown
End With
End Sub

VBA sorting a range with no hardcoding

I am trying to sort a range of cells without hardcoding the starting and stopping points. My range will always start in column A and span to column M, however the rows it stops and starts on will vary. I figured out how to set a variable and incorporate it into the Range function for the last-row, but I can't figure out how to do that for the row the range should start on. Here is my code so far:
Range("A6:M" & lastRow).Sort Key1:=Range("A6"), Order1:=xlAscending, Header:=xlNo
This works only if I start my range on row 6. What I can't figure out is how to tell excel to start my range on the first row that is not blank in column A.
Thanks!
Determine if A1 is blank. Use A1 if not blank and the [ctrl]+[down] if it is blank.
dim startRow as long, lastRow as long
With worksheets("sheet1")
lastRow = .cells(.rows.count, "M").end(xlup).row
if isempty(.cells(1, "A") then
startrow = .cells(1, "A").end(xldown).row
else
startRow = 1
end if
with .range(.cells(startrow, "A"), .cells(lastrow, "M"))
.cells.Sort Key1:=.cells(1), Order1:=xlAscending, Header:=xlNo
end with
end with

Copy data up to last used column with vba

I was successfully able to copy data up to the last used row using VBA. I am trying to do the same thing but copy data from A1 to LastColumn2. Here is the code I have put together thus far:
Sheets("Results").Select
LastColumn = Cells(1, Columns.Count).End(xlToLeft).Column
Range("A1:" & LastColumn & "2").Select
Selection.Copy
The debugger highlights the third line. This is just a portion of the code - All of the variables have been dimensioned properly.
You are getting the error because LastColumn is number. You want the string equivalent of it i.e the column name. For Further Reading
Avoid the use of .Select and fully qualify your objects. INTERESTING READ
Is this what you are trying?
Sub Sample()
Dim ws As Worksheet
Dim rng As Range
Dim LastCol As Long
Dim LastColumn As String
Set ws = ThisWorkbook.Sheets("Results")
With ws
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
'~~> Return column name from number
LastColumn = Split(.Cells(, LastCol).Address, "$")(1)
Set rng = .Range("A1:" & LastColumn & "2")
Debug.Print rng.Address
rng.Copy
End With
End Sub
The problem is that the range you are passing is wrong because it is wating simething like:
Range("A1:C2").Select
and you are passing:
Range("A1:32").Select
So what you can do is:
Range(cells(1,1),cells(2,lastcolumn)).Select
Cell(1,1) = A1 beacuse its is row number 1 column number 1
As mentioned it is better if you just
Range(cells(1,1),cells(lastcolumn,2)).copy
Hope it helps

Trying to find unique IDs with all of the values it qualifies for in excel

To be quite honest I am not entirely sure how to describe what it is I am trying to accomplish? But, here it goes anyway. I have an excel sheet containing one column of IDs and a second column of values that need to be associated to the first column. The problem is that the IDs in column A contain duplicates, which is okay because one ID can qualify for multiple values. What I need is to have a third column pull back the unique id, and a fourth column pull back a semi-colon delimited list of all of the values the id qualifies for. Hopefully the attached image makes sense? For what it's worth I have tried every formula I can think of, and I really know nothing about macros, which is what I am thinking needs to be implemented.
Try below code :
Sub sample()
Dim lastRowA As Long, lastRowC As Long
lastRowA = Range("A" & Rows.Count).End(xlUp).Row
lastRowC = Range("C" & Rows.Count).End(xlUp).Row
Dim rng As Range, cell As Range
Set rng = Range("C2:C" & lastRowC)
Dim rngSearch As Range
Set rngSearch = Range("A1:A" & lastRowA)
Dim rngFind As Range
Dim firstCell As String
For Each cell In rng
Set rngFind = rngSearch.Find(What:=cell, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows)
If Not rngFind Is Nothing Then
temp = rngFind.Offset(0, 1)
firstCell = rngFind.Address
Do While Not rngFind Is Nothing
Set rngFind = rngSearch.FindNext(After:=rngFind)
If rngFind.Address <> firstCell Then
temp = temp & ";" & rngFind.Offset(0, 1)
Else
Set rngFind = Nothing
End If
Loop
End If
cell.Offset(0, 1) = temp
Next
End Sub
Here's an alternative approach, that has several advantages
it builkds the list of unique sku's
it clear old data from columns C:D
it will run much faster than looping over a range
Sub Demo()
Dim rngA As Range, rng as Range
Dim datA As Variant
Dim i As Long
Dim sh As Worksheet
Dim dic As Object
Set sh = ActiveSheet ' can change this to your worksheet of choice
Set dic = CreateObject("Scripting.Dictionary")
With sh
' Get data from columns A:B into a variant array
Set rngA = .Range(.Cells(2, 2), .Cells(.Rows.Count, 1).End(xlUp))
datA = rngA
' Create list of unique sku's and built value strings
For i = 1 To UBound(datA)
If dic.Exists(datA(i, 1)) Then
dic(datA(i, 1)) = dic(datA(i, 1)) & ";" & datA(i, 2)
Else
dic.Add datA(i, 1), datA(i, 2)
End If
Next
' Clear exisating data from columns C:D
Set rng = .Range(.Cells(2, 4), .Cells(.Rows.Count, 3).End(xlUp))
If rng.Row > 1 Then
rng.Clear
End If
' Put results into columns C:D
.Range(.Cells(2, 3), .Cells(dic.Count + 1, 3)) = Application.Transpose(dic.Keys)
.Range(.Cells(2, 4), .Cells(dic.Count + 1, 4)) = Application.Transpose(dic.Items)
End With
End Sub
How to add this:
Start the VBS editor (Alt+F11 from excel)
show project explorer, if its not already visible (Ctrl+R)
add a Module (right click on your workbook, Insert, Module)
open the module (dbl click)
Add Option Explicit as the first line, if not already there
copy paste this code into module
How to run it, from Excel
activate the sheet with your data
open macro dialog (Alt+F8)
select Demo from list and run

Resources