For loop with range of cells within another range - vba

Trying to figure out what the code below is doing, but cannot figure it out:
For Each c In Sheets("Control").Range("y3:y" & Range("y" &
Rows.Count).End(xlUp).Row).Cells
Sheets("forecast").Range("a5") = c
What I think is happening:
Below c is set to a certain cell, this contains a name. In the upper part for every cell, in sheet control, for the range from y3 till the end, .... and then the confusion starts. What happens next:
Range(".." & Range(".." & Rows.Count).End(x1Up).Row).Cells
How do I read this?
This is the table from Sheets("Control"):

Range(".." & Rows.Count).End(x1Up).Row - you have a typo here, it is xlUp (l, for lemonade, instead of 1). Use Option Explicit to avoid such mistakes!
Anyhow, it means something like that: in column "..", in your case y, go to the very last row at the bottom. Then go up, until first non-blank cell is met and get its Row.
So if you have values in range Y1:Y20, then going up from the bottom will end in 20th row, giving you 20 as the row number.

There are two ways. You can do this by importing it as a range object or by saving it as an array.
First: as Range
Sub test()
Dim Ws As Worksheet
Dim rngDB As Range, c As Range
Set Ws = Sheets("Control")
With Ws
Set rngDB = .Range("y3", "y" & .Range("y" & Rows.Count).End(xlUp).Row)
End With
For Each c In rngDB
Sheets("forecast").Range("a5") = c
Sheets("forecast").Range("b5") = c.Offset(0, 1)
End Sub
Second: as Variant Array
Sub test2()
Dim Ws As Worksheet
Dim rngDB As Range, c As Range
Dim vDB
Dim i As Long
Set Ws = Sheets("Control")
With Ws
Set rngDB = .Range("y3", "z" & .Range("y" & Rows.Count).End(xlUp).Row)
vDB = rngDB '<~~ get data from rngdb to array vDB
End With
For i = 1 To UBound(vDB, 1)
Sheets("forecast").Range("a" & i + 4) = vDB(i, 1)
Sheets("forecast").Range("b" & i + 4) = vDB(i, 2)
End Sub

Related

How to find value of cell above each cell

I want to screen all sheets for values that starts with "D"
In the sheets I formed blocks (1 column, 4 rows) with
- owner
- area
- parcel (that is allways starting with a "D")
- year of transaction (blocks of 1 column and 4 rows).
I want to make a summary in sheet "Test".
I'm able to find the parcel, but how can I get the info from the cell above?
Sub Zoek_kavels()
Dim ws As Worksheet
Dim rng As Range
Dim Area
Dim Kavel As String
rij = 1
For Each ws In ActiveWorkbook.Sheets
Set rng = ws.UsedRange
For Each cell In rng
If Left(cell.Value, 1) = "D" Then 'Starts with D
Sheets("Test").Cells(rij, 1) = cell.Value 'Kavel D..
Cells(cell.row - 1, cell.Column).Select
Area = ActiveCell.Value
Sheets("Test").Cells(rij, 2) = Area 'Oppervlakte
Sheets("Test").Cells(rij, 3) = ws.Name 'Werkblad naam
rij = rij + 1
End If
Next
Next
End Sub
A nice simple loop should do the trick, you may have had spaces in the worksheet, that would throw off the used range.
Here is a different approach.
Sub Get_CellAboveD()
Dim LstRw As Long, sh As Worksheet, rng As Range, c As Range, ws As Worksheet, r As Long
Set ws = Sheets("Test")
For Each sh In Sheets
If sh.Name <> ws.Name Then
With sh
LstRw = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rng = .Range("A1:A" & LstRw)
If LstRw > 1 Then
For Each c In rng.Cells
If Left(c, 1) = "D" Then
r = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1
ws.Range("A" & r).Value = c
ws.Range("B" & r).Value = c.Offset(-1).Value
ws.Range("C" & r).Value = sh.Name
End If
Next c
End If
End With
End If
Next sh
End Sub
There are two important points (and two not so important) to take care of your code:
start from row 2, because you are using .row - 1. Thus, if you start at row 1, row-1 would throw an error;
try to avoid Select, ActiveCell, etc.;(How to avoid using Select in Excel VBA);
write comments in English, not in Dutch (also good idea for variable names as well, rij or kavel do not help a lot);
declare the type of your variables, e.g. dim Area as String or as Long or anything else;
Option Explicit
Sub ZoekKavels()
Dim ws As Worksheet
Dim rng As Range
Dim Kavel As String
Dim rij As Long
Dim cell As Range
rij = 2 'start from the second row to avoid errors in .Row-1
For Each ws In ActiveWorkbook.Worksheets
Set rng = ws.UsedRange
For Each cell In rng
If Left(cell, 1) = "D" Then
With Worksheets("Test")
.Cells(rij, 1) = cell
.Cells(rij, 2) = ws.Cells(cell.Row - 1, cell.Column)
.Cells(rij, 3) = ws.Name
End With
rij = rij + 1
End If
Next
Next
End Sub
Or you can use .Cells(rij, 2) = cell.Offset(-1, 0) instead of Cells(cell.Row - 1, cell.Column), as proposed in the comments by #Shai Rado.

VBA Highlight Cells When Other Value is Present

I am looking to highlight certain cells in a spreadsheet when a value is entered in a different column. I realize this can be done with conditional formatting but, due to circumstances within the company, I must use VBA. (The spreadsheet is passed onto another program that can't read conditional formatting)
I am trying to highlight 11 different columns within my range of values whenever ANYTHING is entered into column L. For example, when a date it entered in L2, then C2, J2, K2, etc. are highlighted yellow.
Below is what I have come up with.. unfortunately, when I run the macro, nothing happens. I see it run, but I get no results - not even an error message. Thanks in advance for the time you take to help me out!
Dim rng As Range, r As Range
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("From GIS")
Set sht2 = wb.Sheets("To MapCall")
Set rng = Intersect(sht2.UsedRange, Range("L:L")).Cells
For Each r In rng
If r.Value = "" Then
Cells(r.Row + 1, "C,J,K,Q,AI,AV,AW,AX,AY,AZ,BR").Interior.Color = RGB(255, 255, 0)
End If
Next r
Please give this a try and change r.Value = "" to r.Value <> "" as you want to apply a color if something is entered in the range not when it is blank. Tweak it as per what you actually need. I am also not sure why have you used r.Row + 1? It that's not what you want, replace i = r.Row + 1 in the below code with i = r.Row.
Also it's a good practice to declare all the variables used in the code.
Dim wb As Workbook
Dim sht1 As Worksheet, sht2 As Worksheet
Dim rng As Range, r As Range, clrRng As Range
Dim i As Long
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("From GIS")
Set sht2 = wb.Sheets("To MapCall")
Set rng = Intersect(sht2.UsedRange, Range("L:L")).Cells
For Each r In rng
If r.Value = "" Then
i = r.Row + 1
Set clrRng = Union(Range("C" & i), Range("J" & i & ":K" & i), Range("Q" & i), Range("AI" & i), Range("AV" & i & ":AZ" & i), Range("BR" & i))
clrRng.Interior.Color = RGB(255, 255, 0)
End If
Next r
One method would be to create a union of ranges.
Sub test()
Dim Rng As Range, r As Range, uRng As Range, row As Long
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("From GIS")
Set sht2 = wb.Sheets("To MapCall")
Set Rng = Intersect(sht2.UsedRange, Range("L:L")).Cells
For Each r In Rng
If r.Value <> "" Then
row = r.row
Set uRng = Union(Cells(row, "C"), Cells(row, "J")) 'Etc... Keep going with each column
uRng.Interior.Color = RGB(255, 255, 0)
End If
Next r
End Sub

Reading Manipulating and Writing Data in VBA

If I have a column of values, how do I read the values into a variable in VBA, perform some operation on it and then write it to the next column? Seems mind numbingly simple but I haven't been able to find a simple guide.
for example:
Column A = 1, 4, 5, 7
without writing formulas into column B
Dim A, B
A = column a
B = log(A)
write the values of B to the next column.
Thanks!
If you want to loop through a whole sheet you can do it like this.
Dim lRow as long
Dim strA as string
Dim strB as string
Dim ws As Excel.Worksheet
Set ws = ActiveWorkbook.Sheets("Sheet1")
lRow = 1
Do While lRow <= ws.UsedRange.Rows.count
'Read the data from columnA
strA = ws.Range("A" & lRow).Value
'do something with the value you got from A
strB = strA & "some other text"
strB = log(strA)
'Write it to C
ws.Range("C" & lRow).Value = strB
lRow = lRow + 1
ws.Range("A" & lRow).Activate
Loop
Or if you just want a certain predefined row it would be more hard coded like this.
'Read the data from columnA
strA = ws.Range("A6").Value
'do something with the value you got from A
strB = strA & "some other text"
strB = log(strA)
'Write it to C
ws.Range("C6").Value = strB
Try this macro:
Sub test()
Dim cel As Range, rng As Range
Dim logCel As Double
Dim lastRow As Integer
lastRow = Cells(1048576, 1).End(xlUp).Row
Set rng = Range(Cells(1, 1), Cells(lastRow, 1)) 'Create a range to search
For Each cel In rng
If Not IsEmpty(cel) Then 'If the cell has a value in it
logCel = Log(cel) 'add the LOG of the value to a variable
cel.Offset(0, 1).Value = logCel 'In the cell to the right of the cell, put the log
End If
Next cel
End Sub
To learn about setting cell values and such, I highly recommend using the macro recorder, then looking through the macro when you're done. Start the recorder, then enter a value into a cell, then in the one next, enter a log of that one, and you'll get some idea of how VBA works.
Rather than looping through cell by cell you would write directly to the worksheet using a LOG formula (no need for an array as the manipulation can be used directly with inserting a formula):
Sub LikeThis()
Dim rng1 As Range
`work on A1:A20 and write to B1:B20
Set rng1 = [a1:a20]
rng1.Offset(0, 1).FormulaR1C1 = "=IF(RC[-1]>0,LOG(RC[-1]),""not valid"")"
End Sub

Row Number reference with VBA

I have searched a bit for a VBA code that will list me a row reference and am not finding results. Perhaps I am missing what the actual term for it is?
I have a list of names in Column A, starting at A2. Then what I would like is a listing of 1,2,3,4,5 going down Column B, starting from B2, until the names stop.
I can do this as a formula but need to have the values set there by a macro in this case.
Can this be done?
If I understand you correctly then this should work:
Sub test()
Dim lastRow As Long, counter As Long
Dim cell As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("NAME_OF_YOUR_WORKSHEET")
lastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
counter = 1
For Each cell In ws.Range("B2:B" & lastRow)
cell.Value = counter
counter = counter + 1
Next cell
End Sub
No need for a loop:
Sub NumberRows()
With Sheets("Sheet Name Here")
With .Range("B2:B" & .Cells(.Rows.Count, 1).End(xlUp).Row)
.Formula = "=ROW()-1"
.Value = .Value
End With
End With
End Sub

Excel VBA - Select a range using variables & COUNTA

Excel VBA - Select a range using variables & COUNTA
Hi Staked VBA Kings & Queens, I'm trying to learn Excel VBA. A simple task I would like to do is select all the contagious cells in a report dump I get from sales. Simple i'm sure, but I am a total beginner at VBA.
Ok Report Info:
The report is a set number of columns (31). Although I would like to build a bit of variability into my code to accommodate a change in column numbers.
The report grows by number of rows each week, some times less, sometimes more. But Always starts at cell [A4].
I though of using COUNTA function to count used number of rows, then set that as a variable. Similar with rows.
This is what I came up with, although I get a "Run-time Error '1004': Method 'Range' of object'_Global failed... can anyone help me out".
For me the key is to learn VBA using task I need getting done. I understand the logic behind my code, but not exactly the write way to write it. If some proposes a totally different code I might get lost.
But I am open minded.
Sub ReportArea()
Dim numofrows As Integer
Dim numofcols As Integer
Dim mylastcell As String
Dim myrange As Range
Worksheets("Sheet1").Select
numofrows = WorksheetFunction.CountA(Range("AE:AE"))
numofcols = WorksheetFunction.CountA(Range("4:4"))
Set myrange = Range(Cells(4, 1), Cells(numofrows, numofcols))
Range(myrange).Select
End Sub
P.S I did try read slimier trends but only got confused as the solution where very involved.
Find last row and last column
Sub Sht1Rng()
Dim ws As Worksheet
Dim numofrows As Long
Dim numofcols As Long
Dim myrange As Range
Set ws = Sheets("Sheet1")
With ws
numofrows = .Cells(.Rows.Count, "AE").End(xlUp).Row
numofcols = .Cells(4, .Columns.Count).End(xlToLeft).Column
Set myrange = .Range(.Cells(4, 1), .Cells(numofrows, numofcols))
End With
MsgBox myrange.Address
End Sub
You can also use this code.
Sub SelectLastCellInInSheet()
Dim Rws As Long, Col As Integer, r As Range, fRng As Range
Set r = Range("A1")
Rws = Cells.Find(what:="*", after:=r, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Col = Cells.Find(what:="*", after:=r, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Set fRng = Range(Cells(2, 1), Cells(Rws, Col)) ' range A2 to last cell on sheet
fRng.Select 'or whatever you want to do with the range
End Sub
Further to my above comment, is this what you are trying?
Sub ReportArea()
Dim ws As Worksheet
Dim Lrow As Long
Dim myrange As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
'~~> Find Last row of COl AE. Change it to the relevant column
Lrow = .Range("AE" & .Rows.Count).End(xlUp).Row
Set myrange = .Range("A4:AE" & Lrow)
With myrange
'
'~~> Do whatever you want to do with the range
'
End With
End With
End Sub
Note: Also you don't need to select a range/worksheet. Work with objects. Interesting Read
alternative solutions to already posted:
1:
Dim LRow&, LColumn&
Lrow = Sheets("SheetName").Cells.SpecialCells(xlCellTypeLastCell).Row
LColumn = Sheets("SheetName").Cells.SpecialCells(xlCellTypeLastCell).Column
MsgBox "Last Row is: " & Lrow & ", Last Column is: " & LColumn
2:
Dim x As Range
Set x = Range(Split(Sheets("SheetName").UsedRange.Address(0, 0), ":")(1))
MsgBox "Last Row is: " & x.Row & ", Last Column is: " & x.Column
output result