Excel VBA Range object Error in Looping Through Worksheet - vba

I am trying to loop through different sheets in my workbook. I have tried searching through stackoverflow but still stuck with the error. The error showed "Method 'Range' of object'_Worksheet' failed.
The purpose of this code is to standardise all formats in the worksheets.
Sub formatting()
Dim ws as Worksheet
Dim lastRow as long, lastColumn as long
lastRow = Range("A" & Rows.Count).End(xlUp).Row
lastColumn = (Cells(1, Columns.Count).End(xlToLeft).Column)
For each ws in Activeworkbook.Worksheets
With ws.Range(cells(lastRow, 1), cells(1, lastColumn))
'rest of the actions I want to perform'
.font.bold = true
End With
Next ws
End Sub
I just got started on Excel vba, please enlighten me! Thank you!

Few changes to be made:
1. You have to redefine the last row and last column for each sheet. With that said, place the variable assignment inside the loop.
Instead of ws.Range(cells...), the proper syntax is Range(ws.cells...)
See below:
Sub formatting()
Dim ws As Worksheet
Dim lastrow As Long, lastcolumn As Long
For Each ws In ActiveWorkbook.Worksheets
lastrow = ws.Range("A" & Rows.Count).End(xlUp).Row
lastcolumn = (Cells(1, Columns.Count).End(xlToLeft).Column)
With Range(ws.Cells(1, 1), ws.Cells(lastrow, lastcolumn))
'rest of the actions I want to perform'
.Font.Bold = True
End With
Next ws
End Sub

You have to qualify the Cells calls as well as the Range call:
With ws.Range(ws.cells(lastRow, 1), ws.cells(1, lastColumn))

If you just got started in VBA I'd learn about setting ranges using .currentregion this will greatly help you in the future.
The code snippet makes all fields bold. If you are applying to all then currentregion can save code and possible errors on one condition "that all the fields are connected."
Sub formattingWithCurrentRegion()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
ws.Range("A1").CurrentRegion.Font.Bold = True
Next ws
End Sub
By setting the area as a range you can get greater control over ranges to set different formatting without having to deal with loops in loops.
See below
Sub formattingWithCurrentRegion()
Dim ws As Worksheet
Dim rSheet As Range
For Each ws In ActiveWorkbook.Worksheets
'' sets the CurrentRegion as a range. Use the immediate window rSheet.Select to see what CurrentRegion does.
Set rSheet = ws.Range("A1").CurrentRegion
'' now you can work with it
rSheet.Font.Bold = True
'' make the 2 column font.color to Red
rSheet.Resize(rSheet.Rows.Count, 1).Offset(0, 1).Font.Color = vbRed
''now clean up. Always set ranges to nothing when done with them.
Set rSheet = Nothing
Next ws
End Sub

Related

Copy Excel formula to last row on multiple work sheets

I have a workbook which has multiple worksheets that vary in name but the content structure of each sheet remains the same. There is only one sheet name that is always constant pie.
I am trying to apply a formula in cell N2 and then copy the formula down to the last active row in all the worksheets except the one named pie
The code I have so far is works for one loop but then i get an error "AutoFill method of Range Class failed"
I have used
Lastrow = Range("M" & Rows.Count).End(xlUp).Row
to determine the last row as column M is always complete.
Any help to complete this would be very much appreciated
Code i have is:
Sub ConcatForm()
Dim wSht As Worksheet
Lastrow = Range("M" & Rows.Count).End(xlUp).Row
Application.ScreenUpdating = False
For Each wSht In Worksheets
If wSht.Name <> "Pie" Then
wSht.Range("N2").FormulaR1C1 = "=CONCATENATE(RC[-3],RC[-2],RC[-1])"
wSht.Range("N2").AutoFill Destination:=Range("N2:N" & Lastrow)
End If
Next wSht
Application.ScreenUpdating = True
End Sub
You don't need to use Autofill to achieve this.
Just apply your formulas directly to your range and use relative references, i.e. K2, rather than absolute references, i.e. $K$2. It will fill down and update the formula for you.
Make sure you are fully qualifying your references. For example, see where I have used ThisWorkbook and the update to how lastrow is initialized. Otherwise, Excel can get confused and throw other errors.
Your lastrow variable hasn't been dimensioned so it is an implicit Variant. You'd be better off dimensioning it explicitly as a Long.
Sub ConcatForm()
Application.ScreenUpdating = False
Dim wSht As Worksheet
Dim lastrow As Long
With ThisWorkbook.Worksheets("Sheet1") 'which worksheet to get last row?
lastrow = .Range("M" & .Rows.Count).End(xlUp).Row
End With
For Each wSht In ThisWorkbook.Worksheets
If wSht.Name <> "Pie" Then
wSht.Range("N2:N" & lastrow).Formula = "=CONCATENATE(K2,L2,M2)"
End If
Next wSht
Application.ScreenUpdating = True
End Sub
you were just one wSht reference away from the goal:
Sub ConcatForm()
Dim wSht As Worksheet
lastRow = Range("M" & Rows.count).End(xlUp).row '<--| without explicit worksheet qualification it will reference a range in the "active" sheet
Application.ScreenUpdating = False
For Each wSht In Worksheets
If wSht.Name <> "Pie" Then
wSht.Range("N2").FormulaR1C1 = "=CONCATENATE(RC[-3],RC[-2],RC[-1])"
wSht.Range("N2").AutoFill Destination:=wSht.Range("N2:N" & lastRow) '<--| this will reference a range in 'wSht' worksheet
End If
Next
Application.ScreenUpdating = True
End Sub
Use following sub...
Sub ConcatForm()
Dim wSht As Worksheet
Lastrow = Range("A" & Rows.Count).End(xlUp).Row
Application.ScreenUpdating = False
For Each wSht In Worksheets
With wSht
If .Name <> "Pie" Then
.Select
.Range("N2").FormulaR1C1 = "=CONCATENATE(RC[-3],RC[-2],RC[-1])"
.Range("N2").AutoFill Destination:=Range("N2:N" & Lastrow)
End If
End With
Next wSht
Application.ScreenUpdating = True
End Sub

Copy a range and shift it down one row on the same sheet

I am fairly new in excel VBA and would really appreciate any help on this matter.
The workbook includes data from range A5:AZ1000 (new client info is inputted in new rows, but some cells may be empty depending on the nature of the case). When a user inputs new client info (begins a new row) I would like the existing data (range A5:AZ1000) to shift down one row, and a blank row to appear in range A5:AZ:5. I would like users to be able to click a macro "New Client" for this to happen.
It should be noted that this is a shared workbook and therefore I cannot have macro that adds a new row.
Here is the code I'm working with:
Sub shiftdown()
' shiftdown Macro
Dim lastRow As Long
Dim lastColumn As Long
Dim rngToCopy As Range
Dim rng As Range
Set rng = ActiveSheet.Range("A1").Value
lastColumn = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column
lastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
If rng > 0 Then
ActiveSheet.Range("A5" & lastRow).Select
Selection.Copy
PasteSelection.Offset(1, 0).PasteSpecial xlPasteValues
'Error Object Required
End If
End Sub
Normally I wouldn't answer if the question doesn't include any code to show effort, but I started writing the below while the question actually did show code so I may as well provide it. It may achieve what you are after.
Sub shiftdown()
' shiftdown Macro
Dim rng As Range
With ActiveSheet
If .Range("A1").Value > 0 Then
Set rng = .Range(.Cells(5, 1), _
.Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, _
.Cells(4, .Columns.Count).End(xlToLeft).Column))
rng.Offset(1, 0).Value = rng.Value
.Rows(5).EntireRow.ClearContents
End If
End With
End Sub
Set rng = ActiveSheet.Range("A1").Value ???
if rng is a range, then replace it by :
Set rng = ActiveSheet.Range("A1")
or if rng is a variable, replace
Dim rng As Range
by
Dim rng As variant
rng = ActiveSheet.Range("A1").Value
another error :
you declared rng as range and then you test if it is > 0
If rng > 0 Then ...
it is not possible

cutting from one page to another without select

I am trying to copy from one worksheet to another, and the .End property should work with the Range value, but the error saying it isn't! The developer docs haven't helped, so I'm not sure what to do.
Code below, the .End(xlup) is what's throwing the error.
Dim inputcells As Range
Sheets(1).Range("B8:F8").Cut
With Worksheets(2).Range("C1000")
.End (xlUp)
.Offset(1, 0).PasteSpecial xlPasteValues
End With
This will do it,
Sheets(1).Range("B8:F8").Cut Destination:=Sheets(2).Cells(Sheets(2).Rows.Count, "C").End(xlUp).Offset(1)
If you are trying to paste special values with "Cut" it will not work, you can only paste special with "Copy"
One way to get around that is to set the ranges then make the range equal the other range.
Sub Button1_Click()
Dim sh1 As Worksheet
Dim sh2 As Worksheet
Dim CrNg As Range
Dim LstRw As Long
Dim PrNg As Range
Set sh1 = Sheets(1)
Set sh2 = Sheets(2)
Set CrNg = sh1.Range("B8:F8")
With sh2
LstRw = .Cells(.Rows.Count, "C").End(xlUp).Row + 1
Set PrNg = .Range(.Cells(LstRw, "C"), (.Cells(LstRw, "G")))
End With
PrNg.Value = CrNg.Value
End Sub
You can clear CrNg at the end if you want.
Use Copy rather than Cut:
Sub ljsh()
Sheets(1).Range("B8:F8").Copy
Sheets(2).Range("C1000").End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
End Sub

VBA: looping through worksheets using nested For Each having worksheet as variable

Newbie at vba here. I'm trying to apply a simple For Each loop (which nullifies cells < 0) to all worksheets in the workbook by nesting this inside another For Each loop.
When I try and run my code below I get an error and I'm not sure if it has anything to do with having worksheet as a variable within a Set statement.
Can't seem to figure this out/find a solution.
Thanks
Sub deleteNegativeValue()
Application.DisplayAlerts = False
Dim lastRow As Long
Dim ws As Worksheet
Dim cell As Range
Dim res As Range
For Each ws In Workbooks(1).Worksheets
Set res = ws.Range("1:1").Find("Value", lookat:=xlPart)
lastRow = ws.Range("A" & Rows.Count).End(xlUp).Row
For Each cell In Range(ws.Cells(1, res.Column), ws.Cells(lastRow, res.Column))
If cell < 0 Then cell = ""
Next
Next
End Sub
Try this:
Sub deleteNegativeValue()
Dim lastRow As Long
Dim ws As Worksheet
Dim cell As Range
Dim res As Range
For Each ws In ThisWorkbook.Worksheets
Set res = ws.Range("1:1").Find("Value", lookat:=xlPart)
lastRow = ws.Range("A" & Rows.Count).End(xlUp).row
If Not res Is Nothing Then
For Each cell In ws.Range(ws.Cells(1, res.Column), ws.Cells(lastRow, res.Column))
If cell < 0 Then cell = ""
Next
Else
MsgBox "No Value found on Sheet " & ws.Name
End If
Next
End Sub
There needs to be a check on the Find method, to ensure that something was found
you could try this
Option Explicit
Sub deleteNegativeValue()
Dim ws As Worksheet
Dim res As Range
For Each ws In ThisWorkbook.Worksheets
Set res = Intersect(ws.Rows(1), ws.UsedRange).Find("value", LookAt:=xlPart)
If Not res Is Nothing Then
ws.Columns(res.Column).SpecialCells(xlCellTypeConstants, xlNumbers).Replace What:="-*", Replacement:="", SearchOrder:=xlByColumns, MatchCase:=False, LookAt:=xlWhole
Else
MsgBox "No Value found on Sheet " & ws.Name
End If
Next
End Sub
which should run faster since it doesn't iterate through every cell of each column and restrict the Find method range to the used one instead of the entire row.
the only warning is that the first row of all searched in sheets must not be empty...
Try the second for-each this way:
ws.Range(ws.Cells(1, res.Column), ws.Cells(lastRow, res.Column))

Issue Creating Autofill Macro with a VBA Function

I am having an issue creating a macro that will autofill a VBA function named "FindMyOrderNumber". Every time I run a macro to Autofill "FindMyOrderNumber" only the first cell in the column is populated.
This function will look up an order number in column A (A1) and return the name of the worksheet it can be found B (B1).
Option Explicit
Function FindMyOrderNumber(strOrder As String) As String
Dim ws As Worksheet
Dim rng As Range
For Each ws In Worksheets
If ws.CodeName <> "Sheet3" Then
Set rng = Nothing
On Error Resume Next
Set rng = ws.Cells.Find(What:=strOrder, LookAt:=xlWhole)
On Error GoTo 0
If Not rng Is Nothing Then
FindMyOrderNumber = ws.Name
Exit For
End If
End If
Next
Set rng = Nothing
Set ws = Nothing
End Function
I created this macro to enter my VBA function "=findmyordernumber(a1)" in cell B1 then to Autofill column B.
Sub AutofillVBAFunction()
Range("B1").Select
ActiveCell.FormulaR1C1 = "=FindMyOrderNumber(RC[-1])"
Selection.Autofill Destination:=Range("B1:B68")
Range("B1:B68").Select
End Sub
After I run this macro only B1 is populated.
Sorry if this has been discussed I am new and I tried How to fill-up cells within a Excel worksheet from a VBA function? and other questions and I could not apply it to my issue.
Please help
Add application.volatile to the function, that way it will calculate as the sheet changes.
Function FindMyOrderNumber(strOrder As String) As String
Dim ws As Worksheet
Dim rng As Range
Application.Volatile
For Each ws In Worksheets
If ws.CodeName <> "Sheet3" Then
Set rng = Nothing
On Error Resume Next
Set rng = ws.Cells.Find(What:=strOrder, LookAt:=xlWhole)
On Error GoTo 0
If Not rng Is Nothing Then
FindMyOrderNumber = ws.Name
Exit For
End If
End If
Next
Set rng = Nothing
Set ws = Nothing
End Function
It also wouldn't hurt to calculate the sheet when You add the formula to the range.
Sub Button1_Click()
Dim Rws As Long, Rng As Range
Rws = Cells(Rows.Count, "A").End(xlUp).Row
Set Rng = Range(Cells(1, 2), Cells(Rws, 2))
Rng = "=FindMyOrderNumber(RC[-1])"
End Sub