Variable Range not recognized as a property of Worksheets - excel

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.

Related

Sum values from one Worksheet in another Worksheet

I am trying to sum values from my original worksheet in specific cells in my newly created worksheet, which has a template to fill out.
When I used macro recorder, it references the worksheet name, which would not be useful as the worksheet name changes depending on which worksheet I am working in when I run the code.
So I tried changing the worksheet name to a variable "XCXX".
The first argument works so I thought everything was okay, however, on the second argument, it keeps trying to open a file, when it should simply go back to XCXX and pull the values.
Is it a problem with my activesheet changing?
Sub AddWorkbooks()
Dim ChangeOrder As Range
Dim XCXX As Worksheet
Dim CoForm As Worksheet
Set XCXX = ActiveSheet
Set CoForm = Worksheets("+CO Form+")
'Set wbNew = Workbooks.Add
CoForm.Copy After:=Sheets(ActiveSheet.Index)
With CoForm
Range("A6:D6").Select
ActiveCell.FormulaR1C1 = XCXX.Range("D2").Value
Range("AD81").Select
ActiveCell.FormulaR1C1 = "='XCXX'!R[-64]C[-24]+'XCXX'!R[-64]C[-23]"
End With
End Sub
This should be close:
Sub AddWorkbooks()
Dim ChangeOrder As Range
Dim XCXX As Worksheet, wb As Workbook
Dim CoForm As Worksheet, CoFormCopy As Worksheet
Set wb = ActiveWorkbook
Set XCXX = ActiveSheet
Set CoForm = wb.Worksheets("+CO Form+")
CoForm.Copy After:=XCXX
Set CoFormCopy = XCXX.Next 'the copy of "+CO Form+"
With CoFormCopy 'assuming you want to work with the copy?
.Range("A6:D6").Value = XCXX.Range("D2").Value
.Range("AD81").FormulaR1C1 = _
Replace("='<nm>'!R[-64]C[-24]+'<nm>'!R[-64]C[-23]", "<nm>", XCXX.Name)
End With
End Sub
Note when using With you need to use a period to link (eg) Range() with the object used in the With statement, otherwise it defaults to the active sheet.
Also generally there's no need to select a range to do something with it.

Why am I getting a Subscript Out of Range Error 9 when referencing another Workbook/Worksheet in VBA?

I have a Macro (within a Master Workbook) that is getting data from another Workbook/Worksheet using .value2.
I've tried different changes, within the code. I double checked that both workbooks are open. However, I keep getting the Subscript out of range (Error 9).
Sub NielsenScorecard_DataPaste()
Dim WbNielsenScorecard As Workbook
Set WbNielsenScorecard = Workbooks("Nielsen Scorecard_Template.xlsm")
TotalUS_DataPaste
End Sub
Sub TotalUS_DataPaste()
**Subscript out of range (Error 9)**
With Workbooks("Power Query - Meijer_Walmart_Total US xAOC.xlsm").Worksheets("PQTotalUS")
Dim Data(0) As Variant
'Copy Data Range
Data(0) = .Range(.Cells(.Rows.Count, "A").End(xlUp), "AA2").Value2
End With
'Worksheet Code Name within this Workbook
With wsTotalUS
Debug.Print wsTotalUS.Name
.AutoFilter.ShowAllData
.Range("A2:AA" & .Cells(.Rows.Count, "A").End(xlUp).Offset(1).Row).ClearContents
With .Cells(.Rows.Count, "A").End(xlUp).Offset(1).Resize(UBound(Data(0)))
.Resize(ColumnSize:=UBound(Data(0), 2)).Value2 = Data(0)
End With
End With
End Sub
You can reference a sheet by its codename, however it is a different format and must be in ThisWorkbook. A drawback is that you cannot reference a sheet in another workbook by its codename. Worksheets("PQ Total US").Activate versus PQTotalUS.Activate. If your goal is to shorten the code and not have to repeat a long name, then another option is to do the following:
Dim wb1 as Workbook
Dim ws1 as Worksheet
Set wb1 = Workbooks("Power Query Meijer_Walmart_Total US xAOC.xlsm")
Set ws1 = wb1.Worksheets("PQ Total US")
With ws1
'Do something
End with

How to restrict VBA code to a specific worksheet?

I am trying to restrict the macro to a specific the Test! worksheet When I activate the macro pasted below and I am within the Test! worksheet, the macro works. However, when I try activating the macro on a different sheet, I receive an error. Any idea on what I need to do to modify the VBA code in order for it to be work any other worksheet within the workbook? Thanks
Sub Test ()
' Test Macro
'
' Keyboard Shortcut: Ctrl+Shift+B
'
Range ("Test!B1").Select
Selection.ClearContents
Range ("Test!B2").Select
Selection.ClearContents
Range ("Test!B3").Select
Selection.ClearContents
End Sub
You must reference the worksheet directly:
Dim ws as worksheet
set ws = Thisworkbook.Worksheets("Test")
with ws
.Range("B1:B3").ClearContents
end with
Other notes:
Don't use .Select or Selection. Simply operate on the objects directly.
You have String issues in your original code that would cause compile-time errors (fixed in my code)
You can clear the entire range in one line of code, rather than cell by cell
If the worksheet exists at compile-time in ThisWorkbook (i.e. the same file that's hosting the VBA code), then you don't need to retrieve the sheet at all - not by name, not by index.
VBA is already declaring a global Worksheet object variable for that sheet (and every sheet in ThisWorkbook). Verify the sheet's (Name) property; change it to TestSheet, then you can use TestSheet as an identifier anywhere in your code to refer to that sheet.
TestSheet.Range("B1:B3").ClearContents
And this code will work regardless of whether the user moved the sheet to another index/position in the workbook, or whether the user renamed the sheet's "tab" to something else.
ThisWorkbook.Worksheets(1).Range("B1:B3").ClearContents ' breaks if sheet is moved
ThisWorkbook.Worksheets("Test").Range("B1:B3").ClearContents ' breaks if sheet/tab is renamed
The Basics
If you want to learn something you should study versions 1 and 2, which are elaborate versions of versions 3 and 4 respectively.
Use Option Explicit to quickly find mistakes.
Use constants to be able to quickly change values.
Use object references to not have to type names on and on.
It is assumed that you will copy these codes in any module in the workbook where the worksheet 'Test' resides.
Option Explicit
Sub Test1()
Const cStrWs As String = "Test" 'Worksheet Name
Const cStrRng As String = "B1:B3" 'Range to 'DEL'
Dim oWs As Worksheet 'Worksheet Object
Dim oRng As Range 'Range Object
Set oWs = ThisWorkbook.Worksheets(cStrWs) 'Create a reference to the worksheet
Set oRng = oWs.Range(cStrRng) 'Create a reference to the range
oRng.ClearContents
End Sub
Sub Test2()
Const cStrWs As String = "Test" 'Worksheet Name
Const cStrCell As String = "B1" 'Cell to 'DEL'
Const cLngCells As Long = 3 'Number of cells
Dim oWs As Worksheet 'Worksheet Object
Dim oRng As Range 'Range Object
Set oWs = ThisWorkbook.Worksheets(cStrWs) 'Create a reference to the worksheet
Set oRng = oWs.Range(cStrCell) 'Create a reference to the cell range
oRng.Resize(3, 1).ClearContents
End Sub
Sub Test3()
ThisWorkbook.Worksheets("Test").Range("B1:B3").ClearContents
End Sub
Sub Test4()
ThisWorkbook.Worksheets("Test").Range("B1").Resize(3, 1).ClearContents
End Sub

Function to get Usedrange gets error 91

Trying to write a Union of Ranges Function
I get `Object variable or with block not set"
I am not getting this right (I think):
With Rng
UnionRange = Intersect(ws.UsedRange, Rng.EntireColumn)
End With
Sub iUnionRange()
Dim R As Range
'Check to see if the Function is working
Set R = UnionRange("Elements", Range("A1:D1, G1:G1, I1:K1"))
R.Select
End Sub
The Function
Function UnionRange(shtName As String, Rng As Range) As Range
Set ws = ThisWorkbook.Sheets(shtName)
If Rng Is Nothing Then Exit Function
With ws.Rng
UnionRange = Intersect(ws.UsedRange, .EntireColumn)
End With
End Function
First of all, use Set keyword to assign an object to a variable, so UnionRange = should be Set UnionRange =. Specify a sheet object when you are retrieving a range, doing so it's not necessary to pass sheet name to the function since Rng.Parent returns the sheet object.
There is example below:
Sub test()
Dim Q As Range
Dim R As Range
Set Q = Sheets("Elements").Range("A1:D1, G1:G1, I1:K1")
Q.Select
Set R = UnionRange(Q)
R.Select
End Sub
Function UnionRange(Rng As Range) As Range
If Rng Is Nothing Then Exit Function
Set UnionRange = Intersect(Rng.Parent.UsedRange, Rng.EntireColumn)
End Function
Your function is returning an object so you need to use 'Set', ie:
Set UnionRange = Intersect(ws.UsedRange, .EntireColumn)
I think your code might also also throw an error if 'R.Select' is called when the "Elements" worksheet isn't active (ie the user has activated another sheet). I wonder too if you're using the Range parameter as simply an address of cells when it can do a lot more for you.
If it were me, I'd change the code to the following:
Sub iUnionRange()
Dim ws As Worksheet
Dim r As Range
' Define the worksheet
Set ws = ThisWorkbook.Worksheets("Elements")
' Call the cell selection function
Set r = UnionRange(ws.Range("A1:D1, G1:G1, I1:K1"))
' Note, if you go to the properties of the "Elements"
' worksheet, you can change its name property to,
' say, ElementsSht and simply refer to the object by that name.
' As well as being easier to code, it does protect you
' from an error if a user changes the sheet name in
' Excel.
' So you could just uncomment the following line:
'Set r = UnionRange(ElementSht.Range("A1:D1, G1:G1, I1:K1"))
' Select the target range
SafeSelect r
End Sub
Function UnionRange(target As Range) As Range
If target Is Nothing Then Exit Function
Set UnionRange = Intersect(target.Worksheet.UsedRange, target.EntireColumn)
End Function
Sub SafeSelect(target As Range)
' Check that the range object is not nothing
' and the worksheet to be selected is active
If Not target Is Nothing Then
target.Worksheet.Activate
target.Select
End If
End Sub
If you're intending to call this routine a lot then perhaps define the UsedRange outside the scope of the function as you only need to process that command once to have the range defined. And finally, be aware that you could have some empty cells selected, especially at the bottom of your used range if some columns are shorter than others.
Good luck with your project.

VBA to delete multiple RangeNames for single Range

I have searched for an answer for hours, and can't search anymore. Have Seen lots of discussions about deleting all range names from a workbook or a worksheet. However, I need to delete multiple Range Names from a single Range while leaving other Range Names for other ranges on the same sheet and/or within the same workbook alone. Might the code look something like this?:
Sub Delete_My_Named_Ranges()
Dim nName As Name
Dim wbk As Workbook
Dim Sht As Worksheet
Dim rgNm As Range, aCell As Range
Set wbk = Workbooks("testRgNmDelete.xlsm")
Set Sht = wbk.Worksheets("Sheet1")
Set rgNm = Sht.Range("$A$1")
For Each nName In ThisWorkbook.Names
Set aCell = Range(nName)
If Not Intersect(aCell, rgNm) Is Nothing Then
nName.Delete
End If
Next
End Sub
OK, the above code works for a fixed range ("$A:$1"). But I need to be able to set rgNm as a variable instead of as a fixed range. here is an example, the error now is on the statement "Set aCell = Range(nName)."
Private Sub cboProductType_Change()
Dim wbSKUM As Workbook
Dim ws As Worksheet, wsLUL As Worksheet, wsLU As Worksheet
Dim rgPTL As Range, rgTable1 As Range, rgA1 As Range, rgA1LU As Range
Dim rgNm As Range, rgFormula As Range, aCell As Range
Dim sFormula As String
Dim nName As Name
Set wbSKUM = Workbooks("XBS_SKU_Master.xlsm")
Set ws = wbSKUM.Worksheets("SKUMaster")
Set wsLUL = wbSKUM.Worksheets("LookupLists")
Set wsLU = wbSKUM.Worksheets("Lookup")
Set rgPTL = wsLUL.Range("ProdTypeLookUp")
Set rgTable1 = ws.Range("Table1")
sFormula = "=SUBSTITUTE(SUBSTITUTE(F2,"" "",""_""),""-"","""")"
'clear Product Type Lookup List (Column D) to be sure no data remains
wsLUL.Activate
Range(Range("F2"), Range("F2").End(xlDown)).Select
Selection.Cells.Value = vbNullString
Set rgNm = Selection
For Each nName In ThisWorkbook.Names
Set aCell = Range(nName)
If Not Intersect(aCell, rgNm) Is Nothing Then
nName.Delete
End If
Next
Thanks again!
You are getting that error becuase you have not set rgName after declaring it.
Here is my understanding of your question.
Lets say there is a Range A1:A10 in Sheet1 and Cell A2 has a name NM1 and Cell A5 has a name NM2 and cell D10 has a name NM3
And you want a piece of code which deletes the Names in Range A1:A10 i.e NM1 and NM2 and not NM3
If the above is what you want then try this
Option Explicit
Sub Sample()
Dim rgName As Range, aCell As Range
Dim nName As Name
Set rgName = Sheets("Sheet1").Range("A1:A10")
For Each nName In ThisWorkbook.Names
Set aCell = Range(nName)
If Not Intersect(aCell, rgName) Is Nothing Then nName.Delete
Next
End Sub
And if I have misunderstood your question then you might want to rephrase it?
FOLLOWUP
This has been an extremely useful site to me as a new VBA user, but I have ABSOLUTELY no idea how to add to this site, beyond these little notes. Please try to imagine the Name Manager in Excel 2010 - in Name Manager there are say 10 unique names, all for =Sheet1!$A$1. I want all of these names which pertain to Sheet1!$A$1 to be deleted by VBA code. I DO NOT want other names to be deleted anywhere. – LostInData 3 mins ago
Based on your above comment try this
Option Explicit
Sub Sample()
Dim nName As Name
For Each nName In ThisWorkbook.Names
If nName.RefersTo = "=Sheet1!$A$1" Then nName.Delete
Next
End Sub
I think there is something missing in the solution given above.
In order to refer to the range of a named range with the range object you must use the name property of your named range. Therefore, not Set aCell = Range(nName) but rather Set aCell = Range(nName.Name).
Like this:
Option Explicit
Sub Sample()
Dim rgName As Range, aCell As Range
Dim nName As Name
Set rgName = Sheets("Sheet1").Range("A1:A10")
For Each nName In ThisWorkbook.Names
Set aCell = Range(nName.Name)
If Not Intersect(aCell, rgName) Is Nothing Then nName.Delete
Next
End Sub

Resources