I am having issues when trying to use a Range as a variable. Keep getting the "Select Method of Range Class Failed" error. Any idea what I might be doing wrong here?
Dim OnRent As Workbook
Dim MattFile As Workbook
Dim Rng As Range
Set OnRent = Workbooks("On-Rent 09-22-17.xlsx")
Set MattFile = ThisWorkbook
Set Rng = ActiveSheet.Range("B101")
OnRent.Activate
ActiveSheet.PivotTables("PivotTable1").PivotFields("CHKOUT_POOL"). _
ClearAllFilters
ActiveSheet.PivotTables("PivotTable1").PivotFields("CHKOUT_POOL").CurrentPage _
= "LOS ANGELES"
Range("B15:L108").Copy
MattFile.Activate
Sheets("LAX Data").Activate
Rng.Select
ActiveSheet.Paste
Problem: Rng.Select only works, if the Rng.Parent is active
The Range.Select method will only work, if the sheet, where the range belongs, is active.
The Rng range may not be on the Sheets("LAX Data") and by calling Rng.Select while another sheet is active, you run into error.
To further explain:
You set the range to
Set Rng = ActiveSheet.Range("B101") 'Note: this can be any sheet. The range object stores its position along with the sheet it is from, as a file is defined by a full/absolute path.
Later, when you want to Rng.Select you are (can be) on different sheet and the select will not work.
Do not use Range.Select and Sheet.Activate methods if you dont have to
See Mats link! Or some of the MANY MANY advice on the net like Power Excel vba secret, avoid using select
Some code alternative
To demonstrate how this can work, here is some untested code.
Sub refreshOnRentForLosAngeles()
Dim OnRentSheetWithPivots As Worksheet
Dim Pivot As PivotTable
Set OnRentSheetWithPivots = Workbooks("On-Rent 09-22-17.xlsx").Sheets(1) 'change to fit
Set Pivot = OnRentSheetWithPivots.PivotTables("PivotTable1")
Pivot.PivotFields("CHKOUT_POOL").ClearAllFilters
Pivot.PivotFields("CHKOUT_POOL").CurrentPage = "LOS ANGELES" 'Turn the city into input variable for reusability?
'The copy source will always be the same? Can u make it dynamic?
OnRentSheetWithPivots.Range("B15:L108").Copy ThisWorkbook.Sheets("LAX Data").Range("B101")
End Sub
If you want to reference range "B101" on sheet "LAX Data", you should replace Rng.Select with Range("B101").Select. this way you will not try to select range which is not on ActiveSheet (which is the reason for an error).
Related
I am trying to take a sheet like:
A3,B3,C3 are the sum of the 2 values above them.
Copy this entire sheet into another sheet with only static values ie the sum formulas are gone and 5,73,55 are just the values.
Public Sub CopyEntireSheetValues()
Sheets("Static Data").Range("A1:M100").Value = Sheets("MAIN").Range("A1:M100").Value
End Sub
This works but ideally, i wouldn't define this range and copy all values from one sheet to another
Here's commented code for how I'd accomplish this task via .UsedRange
Sub CopyEntireSheetValues()
'Define and declare workbook and worksheet variables
Dim wb As Workbook: Set wb = ThisWorkbook
Dim wsSrc As Worksheet: Set wsSrc = wb.Worksheets("Main")
Dim wsDst As Worksheet: Set wsDst = wb.Worksheets("Static Data")
'Set the range you want to copy values from
Dim rCopy As Range: Set rCopy = wsSrc.UsedRange
'Bring only the values to the destination sheet
wsDst.Range("A1").Resize(rCopy.Rows.Count, rCopy.Columns.Count).Value = rCopy.Value
End Sub
Two ways. The exact method to do what you want is use the pastespecial method which would be as follows:
Public Sub CopyEntireSheetValues()
Sheets("MAIN").Range("A1:C100").Copy
Sheets("Static Data").Range("A1").PasteSpecial (xlPasteValues)
End Sub
The other is as explained in comment just setting values.
Sheets("Static Data").Range("A1:C100").Value = Sheets("MAIN").Range("A1:C100").Value
In general the setting values is probably the best. The only time I've used the pasteValues is sometimes dates don't quite behave the same when using the second method, but the end result should be the same.
You updated your question, but this could be dynamic (I didn't test).
Public Sub CopyEntireSheetValues()
Sheets("MAIN").UsedRange.Copy
Sheets("Static Data").Range(Sheets("MAIN").UsedRange.Address).PasteSpecial (xlPasteValues)
End Sub
I'm trying to use both worksheets and ranges as variables, but I'm having some problems.
If I declare a worksheet as a variable and then use the range property it works just fine.
However, when I declare a variable Range and try to use it reference it, it throws me the error 438, object doesn't have property or method.
Sub try()
Dim ws As Worksheet
Set ws = Worksheets("Code")
ws.Range("A3", "B6").Value = "sheets"
Dim r As Range
Set r = Range("D1", "F3")
Worksheets("DATOS").r.Value = "ranges"
End Sub
My end goal would be to have both the Worksheet and the range as variables, so I could reference it such as
ws.r.Value = "123"
Thanks in advance, I hope my question isn't too basic and you can help me.
When you set a Range object, it is not a universal cell address to be used like what you did, each Range refers to a specific Worksheet that you can see under its Worksheet property. (documentation)
You did not specify the Worksheet in Set r = Range("D1", "F3") so VBA assumes that you are referring to the ActiveSheet which can be anything. (which is also why you are recommended to always fully qualify your range reference)
As mentioned in your comment - Since your objective is to use the same range for multiple worksheets, you can define the range address in a String variable and use that variable as shown below:
Sub try()
Const r As String = "D1:F3"
Worksheets("DATOS").Range(r).Value = "ranges"
Worksheets("Code").Range(r).Value = "ranges"
End Sub
You can't use range variable in this way. Rather qualify range mentioning sheet name. Try below codes.
Try below codes.
Sub try()
Dim ws As Worksheet
Set ws = Worksheets("Code")
ws.Range("A3", "B6").Value = "sheets"
Dim r As Range
Set r = Worksheets("DATOS").Range("D1", "F3")
r = "ranges"
End Sub
It is not possible to refer to the range in the way you want.
If you want to use a VBA variable to refer to ranges, you can do this:
' Get a range
Set Sht1 = ThisWorkbook.Worksheets("Sheet1")
Set Rng1 = Sht.Range("A2:B2")
' Set the contents of another range to the same value
Set Sht2 = ThisWorkbook.Worksheets("Sheet2")
Set Rng2 = Sht2.Range("C2:D2")
Rng2.value = Rng1.Value
You already seem to have a grasp of doing it this way.
If you want to refer to a range by a name, here is a method that creates a named range:
' Delete the named range if it exists and create it again.
Sub CreateNamedRange(Wbk As Workbook, Txt As String, Rng As Range)
On Error Resume Next
Wbk.Names(Txt).Delete
If Err.Number <> 0 Then Err.Clear
On Error GoTo 0
Wbk.Names.Add Txt, Rng
End Sub
Here we create a named range Name1 and retrieve it using Sht.Range("Name1"):
Sub CreateNamedRangeAndUseIt()
Dim Sht As Worksheet
Dim Rng As Range
' Set the value of the range to 42
Set Sht = ThisWorkbook.Worksheets("Sheet2")
Set Rng = Sht.Range("A2")
Rng.Value = 42
' Create a name for the range
CreateNamedRange ThisWorkbook, "Name1", Rng
' Activate some other sheet to make sure it works when the
' sheet with the named range is not active.
ThisWorkbook.Worksheets("Sheet1").Activate
' Get the named range and output the value of the range to the
' immediate window.
Set Rng = Sht.Range("Name1")
' This would also work, even though the named range does not
' exist on Sheet1:
' Set Rng = ThisWorkbook.Worksheets("Sheet1").Range("Name1")
' Or this (provided you don't have several workbooks open and
' another workbook is selected)
' Set Rng = Range("Name1")
Debug.Print Rng.Value
' Then select the range.
' We must activate the sheet first to select ranges in it.
Rng.Worksheet.Activate
Rng.Select
End Sub
The named range will still exist if you close and reopen the workbook, provided you save the workbook before closing it. So you only need to name the range once.
I am struggling with proper syntax for setting variables as ranges...
Specifically, I'm testing a function I want to use in an app that creates new profiles and store the data, I will store that data on a hidden sheet, so they can be recalled at run time.
I'm currently construction a userform in order to create a new profile, the profile data needs to be stored to the first free column on the hidden sheet.
(where I will have to create a dynamic namedRange, so that i can use that range to save the associated data, and update the listbox in the userform)
Right now, I'm stumped by this:
Sub TestFindLastFunctions()
Dim wb As Workbook
Set wb = ThisWorkbook
'wb.activate 'shouldn't be neccesary
Dim ws As Worksheet
Set ws = sh_02CRepStorage
'ws.activate 'shoudn't be neccesary
Dim trgtCol As Long
trgtCol = LastColInSheet(ws) + 2
Debug.Print trgtCol ' so far so good
'Cells(1, trgtCol).Select 'another debug check - only works if sheet activated
Dim trgtCell As Range
Set trgtCell = ws.Cells(1, trgtCol) '<------- problem line
Debug.Print trgtCell '<----- prints "" to the immediate window.
End Sub
The LastColInSheet function is copied form Ron de bruin's page: https://www.rondebruin.nl/win/s9/win005.htm it simply returns a column number, in this case: 4.(One problem with it is if the sheet is empty, it returns an error, wondering if this can be fixed with an if statement in the function.)
I've tried many iterations of the problem line, some work but only if the storage sheet is activated, and give an error if not activate or selected, as the sheet will be hidden, I need this to work without activating the sheet, (although I could switch off screen activation?).
But I understand that it is best practice to avoid extraneous selects and activates, how can I just point directly to what I want and save that range into a variable?
It just doesn't seem like it should be so difficult, I must be missing something obvious.
It also seems like it shouldn't need so many lines of code to do something so simple.
I tried some more iterations of the "problem line" after some more searching...
-The real problem was with the debug.print line
Sub TestFindLastFunctions()
Dim wb As Workbook
Set wb = ThisWorkbook
'wb.activate 'shouldn't be neccesary
Dim ws As Worksheet
Set ws = sh_02CRepStorage
'ws.activate 'shoudn't be neccesary
Dim trgtCol As Long
trgtCol = LastColInSheet(ws) + 2
Debug.Print trgtCol ' so far so good
'Cells(1, trgtCol).Select 'debug Only works if already on sheet
Dim trgtCell As Range
'Set trgtCell = ws.Range _
(ws.Cells(1, trgtCol), ws.Cells(1, trgtCol))
' unnecessarily complex, but correct if using .range?
'but works if insisting on range
Set trgtCell = ws.Cells(1, trgtCol) 'back to original
Debug.Print trgtCell.Address '<---problem was here?
End Sub
Using the Range.Find Method doesn't work for the file name.
The Range DocPresent is always "Nothing"
I am processing multiple Excel Sheets and want to track which ones I already processed. To make sure I don't process the Sheet again when I rerun the Macro
Dim wbname1 As String
wbname1 = ActiveWorkbook.Name
Range("A1").End(xlDown).Offset(1, 0) = wbname1
Dim DocPresent As Range
Set DocPresent = Range("A1:A1000").Find(What:=wbname1)
I am expecting the range to return the correct range if it finds the respective cell.
Note that Range("A1").End(xlDown) might end up below A1000 but your .Find is only looking before A1000.
So either use the whole column Range("A:A").Find… or find the last used cell Range("A1", Cells(Rows.Count, "A").End(xlUp)).Find…
And specify a workbook and worksheet for all your ranges!
Dim wbname1 As String
wbname1 = ActiveWorkbook.Name
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("MySheet")
ws.Range("A1").End(xlDown).Offset(1, 0) = wbname1
Dim DocPresent As Range
Set DocPresent = ws.Range("A1", ws.Cells(ws.Rows.Count, "A").End(xlUp)).Find(What:=wbname1, LookAt:=xlWhole)
Note that ThisWorkbook points to the workbook this code is running in. But ActiveWorkbook points to the workbook that has focus (is on top) at the moment the code is running. ActiveWorkbook can easily change by a user's click but ThisWorkbook is always the same.
Also note that the Range.Find method has a LookAt parameter that should always be specified xlWhole or xlPart. Otherwise VBA uses the one that was used last either by VBA or by user interface. So you never know which one VBA is going to use, therefore always specify it.
According to the comment below you should check if your Find method was successfull before you use DocPresent so you don't run into an error:
If Not DocPresent Is Nothing Then
'do your stuff using DocPresent
Else
MsgBox "'" & wbname1 & "' was not found.", vbCritical
Exit Sub
End If
I'm pretty new to VBA and I'm trying to hide some columns in workbooks.
I have to do it in VBA because the workbook is an Analysis for Office workbook, so I have to hide some columns that the final users don't have to see.
My problem is that I can't point to a specific letter of the columns, because, since the workbook is modifiable like a pivot with other dimensions in respect of the default ones with which it opens, if I point to a specific column in the code, it won't be the same when an user add new dimensions. So I have to find the column with its name ad hide it.
So for now I tried this:
Sub Hide_Columns()
'Dim Sourcecell As Range
Dim wb As Workbook
Dim ws As Worksheet
'Set Sourcecell = Nothing
'Set Sourcecell = ThisSheet.Range("SapCrosstab1").Find("Colonna di calcolo", LookIn:=xlFormulas)
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Demand Planning")
wb.Sheets("Demand Planning").Range("Colonna di calcolo").EntireColumn.Hidden = True
End Sub
The problem here is that I'm having the
"Run-time error 1004: Application-defined or object-defined error"
and I don't know how to fix it.
I commented that 3 lines because I'm not so sure they could help.
Your current attempt fails because Range("Colonna di calcolo") will not search for a column with that header. Instead, it want to access a Named Range with that name, and if you don't define this, it will throw exactly this error 1004.
I think your attempt with SourceCell was not bad - issue a Find command and hide the EntireColumn of the found cell. Your mistake was that there is no object ThisSheet. There are objects ThisWorkbook which refers to the entire workbook where the code is stored, or ActiveWorkbook which is the Workbook that is currently shown (not necessarily the workbook where the macro is stored).
You can solve your issue either by defining a Named Range for the column - in that case your code should work.
Or change the code to something like
Dim ws as Worksheet
Set ws = ThisWorkbook.Sheets("Demand Planning")
Dim Sourcecell as Range
Set Sourcecell = ws.Range("1:1").Find("Colonna di calcolo", LookIn:=xlFormulas)
If Not Sourcecell Is Nothing Then
Sourcecell.EntireColumn.Hidden = True
End If