Excel VBA range select - vba

I have a macro in which I need to select the range R2:last row in sheet. However the last row in my sheet might be blank in column R. At the moment I am using this
Dim t As Range
Set t = Range("R2", Range("R1000").End(xlUp))
For Each Cell In t
If IsEmpty(Cell) Then
Cell.Activate
ActiveCell.Value = "To Be Picked Up"
End If
Next
However if the last row has a blank in column R then it gets ignored. I am hoping to pull the range using column A, as the last row of data always has column A. So something like,
Dim t As Range
Set t = Range("R2", Range("A1000").End(xlUp).ActiveCell.Offset(0, 17))
For Each Cell In t
If IsEmpty(Cell) Then
Cell.Activate
ActiveCell.Value = "To Be Picked Up"
End If
Next
It seems so simple but I'm sure im missing something stupid. Any help or alternative methods would be helpful thank you.

This should do the trick in one line:
Sub SO()
Range("R2:R" & Range("A" & Rows.Count).End(xlUp).Row).SpecialCells(xlCellTypeBlanks).Value = "To Be Picked Up"
End Sub
But in answer to your question specifically
Set t = Range("R2:R" & Range("A" & Rows.Count).End(xlUp).Row)
The Range() method will accept a string as an argument to obtain a range.So we can build this string any way we want:
"A1000" '// A1000
"A" & 1000 '// A1000
"A" & "10" & "00" '// A1000
"A" & CStr(1001 - 1) '// A1000
"A" & Rows.Count will return A65536 or A1048576 depending on the type of worksheet.
Range("A1048576").End(xlUp) as you know, will retrieve the last cell in that area, or the first cell in the next area on the direction specified.
Range("A1048576").End(xlUp).Row will return the row number of that cell (let's say it's A1000 for argument's sake) so the return value is 1000.
"R2:R" & Range("A" & Rows.Count).End(xlUp).Row therefore makes the string R2:R1000.
So finally, Range("R2:R" & Range("A" & Rows.Count).End(xlUp).Row) is the same as Range("R2:R1000")

Related

Check cell values in two different sheets

I have two sheets in an excel file namely bank_form and Pay_slip.
I am trying to write a vba to check whether value/text in cell B5 of sheet Pay_slip is equal to value/text in cell B8 of sheet Bank_form. Similary it will check all values till the last row of sheet Pay_slip.
But my code is not working it always comes true i.e. it always flash the message "All employees found."
Please find my mistake(s).
Sub CommandButton1_Click()
Dim LastRow As Long
LastRow = Worksheets("Bank_form").Range("B" & Rows.Count).End(xlUp).Row
LR = Worksheets("Pay_slip").Range("B" & Rows.Count).End(xlUp).Row
If Worksheets("Pay_slip").Range("B5" & LR).Value = Worksheets("Bank_form").Range("B8" & LastRow) Then
MsgBox "All Employees Found."
Worksheets("Bank_form").Range("F" & LastRow + 1).Formula = "=SUM(F8:F" & LastRow & ")"
Else: MsgBox "Employee(s) missing Please check again!"
End If
End Sub
you will need a loop something like this
Dim i as Long
For i = 5 to LastRow 'start at B5
If Worksheets("Pay_slip").Range("B" & i).Value = Worksheets("Bank_form").Range("B" & i + 3) Then
' ... your other stuff here
next i
If Worksheets("Pay_slip").Range("B5").Value = Worksheets("Bank_form").Range("B8").Value Then MsgBox "The values are the same"
I have no idea why you involved the number of rows in your code but they are useless in order to check the equivalence in the values in a specific cell only

VBA Macro - I want to change each cell value to a new one in a specific range... how to do it? Excel

I have a range that is B3:B500
I want to change the value in each cell in that range
The range however, is dynamic so I need to look from B3 to last row
First:
How do I get it to change the range to work to last row rather than preset range?
Second:
I want to change each individual cell value to something like this:
myCell.Value = "=" & Chr(34) & Chr(61) & myCell.Value & Chr(34)
How do I get it to go through cell by cell to make change to each cell in the "dynamic" range we just created?
Appreciate all the help I can get... pretty new at VBA so please bear that in mind and keep it simple :)
I.e. Cell b3 contains: "ASP" (Text only)
Change to: ="="ASP" (formula instead giving result =ASP)
Dim lastRow As Integer: lastRow = 3
Dim myCell As Range
'determine last row of current region
Do While(Not IsEmpty(Cells(lastRow + 1, 2)))
lastRow = lastRow + 1
Loop
'loop through the range
For Each myCell In Range(Cells(2, 2), Cells(lastRow, 2))
myCell.Value = "=" & Chr(34) & Chr(61) & myCell.Value & Chr(34)
Next myCell
In this code, first you determine last row using While loop, which loops until the last row in column is found. Then use For Each loop, where you loop through the range, from third row to last row in B column.

Macro - IF value meets condition copy paste to another sheet

Can I get some help with this macro. I want to go through all values in column P of a table in 'Sheet1'. Here is a picture of the table:
First Table
If value is <1 I want to copy paste the values in columns with the headings in the picture to a table in an 'explanation' sheet in the following format:
Second Table
Any help with this would be appreciated
On the sheet you want the data to go into (table 2) and under your header (in table 2) set the cell equal to the cell you want from table 1. Do this by entering pressing "=" and then clicking to the sheet with table 1 and click on the cell on the first row. Repeat this for the Name, Identifier, Sector, Rate... Once you have the first row done, highlight the cells on the second row and click and hold the bottom right of the black out line and drag down to the same number of rows from table 1.
If you want the values pasted there, then highlight the range and copy and right click paste > paste special (click on paste special) and select values.
Then you can sort the data based on the explanation sheet by the column that's value you need to be less than 1 and delete the rows that are greater than 1.
I have no idea what columns you want copied as they are not named in the first table image you have, so I just did up a macro that you can adjust the ranges yourself as you need copied and to what sheet you need.
The below code loops through your data, checks if the data in Column P for each row is less than 1 and puts the data into a variable where you can copy and paste to where ever you need that data,
The code,
Sub d()
Dim i As Long
Dim lastrow As Long
Dim rng As Range
lastrow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastrow
If Range("P" & i).Value < 1 Then
If Not rng Is Nothing Then
Set rng = Union(rng, Range("B" & i), Range("C" & i), Range("D" & i), Range("Q" & i), Range("H" & i), Range("I" & i), Range("P" & i))
Else
Set rng = Union(Range("B" & i), Range("C" & i), Range("D" & i), Range("Q" & i), Range("H" & i), Range("I" & i), Range("P" & i))
End If
End If
Next
rng.Copy Sheets("explanation").Range("A2")
End Sub
See if this does not help any?

How to pause macro, then do my stuff and continue/resume from where I left?

I got data in one sheet form B2:ZY191, and I want to copy each row (B2:ZY2,B3:ZY3, and so on till B191:ZY191) to another workbook worksheet for analysis. Now while doing so I sometimes need to stop and mark my results in between and then continue from where I left. For example, I started the macro and it copied from B2:ZY2 to B52:ZY52 then I pause the macro & mark my results. Now I want to continue from B52:ZY52 onwards then again if I want to stop after copying data till B95:ZY95 I should be able to pause the macro, mark my result and continue from B95:ZY95 thereon. I should be able to do this as many times as I want.
If provided with buttons like start, pause and resume would be very helpful.
you could adopt the following workaround:
choose the "sets" you want to virtually divide your data range into
let's say:
set#1 = rows 1 to 20
set#2 = rows 21 to 30
... and so on
mark with any character in column "A" the final rows of all chosen sets
so you'd put a "1" (or any other character other than "|I|" or "|E|" - see below) in the following cells of column "A" (i.e. the one preceding your data range):
A21
A31
..., and so on
(since your data starts at row 2 then its ith row is in worksheet row I+1)
then you put the following code in any module of your data range workbook:
Option Explicit
Sub DoThings()
Dim dataRng As Range, rngToCopy As Range
'assuming Analysis.xlsx is already open
Set dataRng = Worksheets("BZ").Range("B2:ZY191") '<--| this is the whole data range. you can change it (both worksheet name and range address) but be sure to have a free column preceeding it
Set rngToCopy = GetCurrentRange(dataRng) '<--| try and set the next "set" range to copy
If rngToCopy Is Nothing Then '<--| if no "set" range has been found...inform the user and exit sub!
MsgBox "There's an '|E|' at cell " _
& vbCrLf & vbCrLf & vbTab & dataRng(dataRng.Rows.Count, 1).Offset(, -1).Address _
& vbCrLf & vbCrLf & " marking data has already been entirely copied" _
& vbCrLf & vbCrLf & vbCrLf & "Remove it if you want to start anew", vbInformation
Exit Sub
End If
With rngToCopy
Workbooks("Analysis").Worksheets("Sheet1").Range(.Address).value = .value
End With
End Sub
Function GetCurrentRange(dataRng As Range) As Range
Dim f As Range
Dim iniRow As Long, endRow As Long
With dataRng
With .Offset(, -1)
Set f = .Resize(, 1).Find(what:="|E|", lookat:=xlWhole, LookIn:=xlValues) '<--| look for the "all copied" mark ("|E|")
If Not f Is Nothing Then Exit Function '<--| if "all copied" mark was there then exit function
Set f = .Resize(, 1).Find(what:="|I|", lookat:=xlWhole, LookIn:=xlValues) '<--| look for any "initial" mark put by a preceeding sub run
If f Is Nothing Then '<--|if there was no "initial" mark ...
iniRow = 1 '<--| ...then assume first row as initial one
Else
iniRow = f.row - .Cells(1).row + 1 '<--| ... otherwise assume "marked" row as initial one
f.ClearContents '<--| and clear it not to found it the next time
End If
endRow = .Cells(iniRow, 1).End(xlDown).row - .Cells(1).row + 1 '<--| set the last row as the next one with any making in column "A"
If endRow >= .Rows.Count Then '<--| if no mark has been found...
endRow = .Rows.Count '<--| ...set the last row as data last row...
.Cells(endRow, 1).value = "|E|" '<--|... and put the "all copied" mark in it
Else
.Cells(endRow, 1).ClearContents '<--| ...otherwise clear it...
.Cells(endRow + 1, 1).value = "|I|" '<--| ... and mark the next one as initial for a subsequent run
End If
End With
Set GetCurrentRange = .Rows(iniRow).Resize(endRow - iniRow + 1) '<--| finally, set the range to be copied
End With
End Function
and make it run as many times as you need: after each time it ends and you can mark your result and then make it run again and it'll restart form where it left
you can use Stop and Debug.Print to achieve the desired results when placed within your code. For example if you're looping through a range, add the statement of choice with an if statement:
for a = 1 to 150
if a = 20 or a = 40 then
debug.Print "The value of a is: " & a.value 'or whatever you want to see
end if
next
This will print to the immediates window, or use stop to pause your code in a strategic place in the same manner.
I dont understand what you mean by buttons? They surely aren't a good idea as the code will run too fast?

Change a cell's format to boldface if the value is over 500

I am using Excel 2010 and trying to add a bunch of rows placing the sum of columns A and B in column C. If the sum is over 500 I would then like to boldface the number in column C. My code below works works mathematically but will not do the bold formatting. Can someone tell me what I am doing wrong? Thank you.
Public Sub addMyRows()
Dim row As Integer 'creates a variable called 'row'
row = 2 'sets row to 2 b/c first row is a title
Do
Cells(row, 3).Formula = "=A" & row & "+B" & row 'the 3 stands for column C.
If ActiveCell.Value > 500 Then Selection.Font.Bold = True
row = row + 1
'loops until it encounters an empty row
Loop Until Len(Cells(row, 1)) = 0
End Sub
Pure VBA approach:
Public Sub AddMyRows()
Dim LRow As Long
Dim Rng As Range, Cell As Range
LRow = Range("A" & Rows.Count).End(xlUp).Row
Set Rng = Range("C2:C" & LRow)
Rng.Formula = "=A2+B2"
For Each Cell In Rng
Cell.Font.Bold = (Cell.Value > 500)
Next Cell
End Sub
Screenshot:
An alternative is conditional formatting.
Hope this helps.
Note: The formula in the block has been edited to reflect #simoco's comment regarding a re-run of the code. This makes the code safer for the times when you need to re-run it. :)