Having trouble with vba using range Union method. I have resolved it, at the end. But could not find the proper explanation, why it is so?
Set ws = ThisWorkbook.ActiveSheet
Set rng00 = Range("A1:C3")
Set rng01 = Range("F1:G3")
ws.Union(rng00,rng01).Copy 'the error giving line
When I have changed the line with below one strangely it has started to work. But as I remember I have used union method of range before with ThisWorkbook(or maybe Workbooks(name))
Worksheets("Sheet1").Activate
Application.Union(rng00,rng01).Copy
Application.Union feat. Qualifying Object References
Your 1st Code
Set ws = ThisWorkbook.ActiveSheet
Set rng00 = Range("A1:C3")
Set rng01 = Range("F1:G3")
ws.Union(rng00,rng01).Copy 'the error giving line
Your 2nd Code
Worksheets("Sheet1").Activate
Application.Union(rng00,rng01).Copy
Application.ThisWorkbook property
ThisWorkbook is (a reference to) the workbook containing this code. It is an exact workbook and there can only be one of it.
Dim wb As Workbook: Set wb = ThisWorkbook
Qualifying Worksheets
When referencing the sheets in a workbook, you want to qualify them (note the wb.):
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
This can be only one worksheet, the worksheet named Sheet1 in the wb - workbook. It can't be the wrong worksheet unless you have incorrectly referenced the workbook.
When you do Set ws = ThisWorkbook.ActiveSheet, it creates a reference to any sheet (worksheet, chart) that is currently active (selected, you're looking at), yet in the line Worksheets("Sheet1").Activate you are activating Sheet1˛ of the ActiveWorkbook, the workbook which is the currently active (could be ThisWorkbook, but may not).
Qualifying Ranges
When referencing the ranges in a worksheet, you want to qualify them (note the ws.):
Dim rg1 As Range: Set rg1 = ws.Range("A1:C3")
Dim rg2 As Range: Set rg2 = ws.Range("F1:G3")
These are ranges in the ws - worksheet. They can't be the wrong ones unless you have incorrectly referenced the worksheet.
When you do Set rng00 = Range("A1:C3"): Set rng01 = Range("F1:G3"), you are creating references to ranges of the ActiveSheet (could be a worksheet, could be a chart), of the ActiveWorkbook (could be ThisWorkbook, but may not). It would have worked correctly only by chance in case your ActiveWorkbook was ThisWorkbook and your ActiveSheet was a worksheet named Sheet1 in the ActiveWorkbook.
Application.Union method
Its 'full name' says it all: it's a member of the Application object, not the Worksheet object. You can omit the Application. part from some of the Application object members: Union is such a member.
Union(rng1, rng2).Copy
Alltogether
Option Explicit
Sub CopyRange()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
Dim rg1 As Range: Set rg1 = ws.Range("A1:C3")
Dim rg2 As Range: Set rg2 = ws.Range("F1:G3")
Union(rng1, rng2).Copy
End Sub
Of course, if there is no worksheet named Sheet1 in the workbook, an error will occur. But that's another story.
Union is a function of the Application Object, not of a Worksheet Object. Which means that ws.Union would not work because there is no member with the name Union as a member of ws. The correct parent is Application.Union but since it would be tedious to write Application. for every function, most of the time the Application. is not written.
The arguments of Union must be Range Objects that are from the same Worksheet. When declaring Ranges, it is important to explicitly declare their parent sheet, to avoid issues later with functions like Union. Adding ws in front of Range like ws.Range is how you can declare that the range is a member of that sheet.
So the full corrected code would be
Set ws = ThisWorkbook.ActiveSheet
Set rng00 = ws.Range("A1:C3")
Set rng01 = ws.Range("F1:G3")
Application.Union(rng00, rng01).Copy
Related
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.
I have an object located on a different sheet, which I would like to copy to the last active sheet. Unfortunately, the code I have throws an error:
Object doesn't support this property or method
Sub AddCabinet()
Dim MooSheet, CurrentSheet As Worksheet
Set CurrentSheet = ThisWorkbook.ActiveSheet
Set MooSheet = ThisWorkbook.Sheets("Cab Templates")
MooSheet.Shapes.Range(Array("VHPOPA")).Select
Selection.Copy
CurrentSheet.Range("A1").Paste
End Sub
How can I copy an object to my previous current sheet? I have a few sheets with the same buttons.
.paste is a worksheet method, not a range method, that is where the error is coming from.
We can remove all the Selects to make this a bit cleaner.
Dim MooSheet As Worksheet, CurrentSheet As Worksheet
Set CurrentSheet = ThisWorkbook.ActiveSheet
Set MooSheet = ThisWorkbook.Sheets("Cab Templates")
MooSheet.Shapes("VHPOPA").Copy
CurrentSheet.Paste
Copy Shapes
Can you even get rid of Select and Activate when copying multiple shapes? I couldn't.
My idea was to copy the shape(s) and restore the worksheets initial selections.
The array is useful to copy multiple shapes. Note that if you don't explicitly use the array function as the parameter for the Shape.Range property, you need to evaluate the array by putting it into parentheses, if its variable is declared as a variant without parentheses i.e.:
Dim shpArr() As Variant... sws.Shapes.Range(shpArr).Select
' or:
Dim shpArr As Variant ... sws.Shapes.Range((shpArr)).Select
The Flow
Exit if the workbook containing this code (ThisWorkbook) is not the active workbook (ActiveWorkbook). Exit if the active sheet (ActiveSheet) is not a worksheet. Reference the active sheet i.e. the destination worksheet.
Reference the source worksheet. Exit if it's the destination worksheet.
Reference the destination Selection to restore after the job is done. Reference the destination cell. Activate it, if it's not active.
Select the source worksheet. Reference its Selection to restore it after the job is done. Select all shapes whose names are in the array and copy them using Selection.
Activate the destination worksheet and paste. Restore its initial selection using Select.
Select the source workbook to restore its initial selection using Select.
Select the destination worksheet.
Sub AddCabinet()
' Define constants.
Const sName As String = "Cab Templates"
Const dFirstCellAddress As String = "A1"
Dim shpArr() As Variant: shpArr = Array("VHPOPA")
'Dim shpArr() As Variant: shpArr = Array("Oval 1", "Oval 2")
' Reference ThisWorkbook's active sheet, the destination worksheet ('dws').
Dim wb As Workbook: Set wb = ThisWorkbook
If Not wb Is ActiveWorkbook Then Exit Sub ' another workbook is active
If Not TypeOf ActiveSheet Is Worksheet Then Exit Sub ' not a worksheet
Dim dws As Worksheet: Set dws = wb.ActiveSheet ' or 'ActiveSheet'
' Reference the source worksheet ('sws')
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
If sws Is dws Then Exit Sub ' source and destination are the same
'Application.ScreenUpdating = False
' Reference the destination cell ('dCell') and activate if not active.
Dim dSel As Object: Set dSel = Selection ' store
Dim dCell As Range: Set dCell = dws.Range(dFirstCellAddress)
If Not dCell Is ActiveCell Then dCell.Activate ' ensure it's active
' Copy.
sws.Select
Dim sSel As Object: Set sSel = Selection ' store
sws.Shapes.Range(shpArr).Select
Selection.Copy
' Paste.
With dws
.Activate
.Paste
End With
If Not dSel Is Nothing Then dSel.Select ' restore
sws.Select
If Not sSel Is Nothing Then sSel.Select ' restore
dws.Select
'Application.ScreenUpdating = True
End Sub
Before copying the object need to be there in that sheet, solve the problem...
try this...
Sub AddCabinet()
Dim MooSheet, CurrentSheet As Worksheet
Set CurrentSheet = ThisWorkbook.ActiveSheet
Set MooSheet = ThisWorkbook.Sheets("Cab Templates")
MooSheet.Select
MooSheet.Shapes.Range(Array("VHPOPA")).Select
Selection.Copy
CurrentSheet.Select
Range("A1").Select
ActiveSheet.Paste
End Sub
Hope it Helps...
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 trying to execute a macro on a workbook that is downloaded from the web daily.
It has only one worksheet that changes names accordingly with the date downloaded (say: "vendas 201709294524455").
I need to set this worksheet as a variable. How can I do that with this dynamic name change?
I tried:
Dim Sh1 As Worksheet
Dim Sh2 As Worksheet
Dim FindCell As Range
Set Sh2 = ThisWorkbook.Worksheets("book1")
Set Sh1 = Workbooks("vendas.xlsm").Worksheets("*vendas*")
LastRow = Sh2.Range("d65536").End(xlUp).Row
'...rest of the code
As it only has one worksheet just use:
Set Sh1 = Workbooks("vendas.xlsm").Worksheets(1)
The Worksheets() allows for the index or a string name. With only one sheet the index is always 1 of that one sheet. See: https://msdn.microsoft.com/en-us/vba/excel-vba/articles/worksheet-object-excel
This will set Sh1 to the first worksheet in the workbook regardless of the name.
Scott Craner's solution is perfect for you. But just for anyone in future -- this is how you would do it if you want to avoid using the worksheet index (which changes if you change the order of the worksheets). Only worth using this method if you have more than one worksheet.
Sub SetWorksheet()
Dim ws As Worksheet, targetWorksheet As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name Like "*test*" Then
Set targetWorksheet = ws
Exit For
End If
Next ws
'use targetWorksheet
MsgBox targetWorksheet.Name
End Sub
If there are multiple sheets like "test" (in this example), you will get the first one.
I know this might come off as a trivial question, but I can't seem to declare a workbook or a worksheet as a variable in VBA. I have the following code, but I can't figure out what I am doing wrong, it should be straight forward. Normally I don't have any problems declaring variables such as Dim i As Integer etc.
sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheet("name")
wb.ws.Select
End Sub
When I run the above code, I receive a type missmatch error.
Use Sheets rather than Sheet and activate them sequentially:
Sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheets("Sheet1")
wb.Activate
ws.Select
End Sub
If the worksheet you want to retrieve exists at compile-time in ThisWorkbook (i.e. the workbook that contains the VBA code you're looking at), then the simplest and most consistently reliable way to refer to that Worksheet object is to use its code name:
Debug.Print Sheet1.Range("A1").Value
You can set the code name to anything you need (as long as it's a valid VBA identifier), independently of its "tab name" (which the user can modify at any time), by changing the (Name) property in the Properties toolwindow (F4):
The Name property refers to the "tab name" that the user can change on a whim; the (Name) property refers to the code name of the worksheet, and the user can't change it without accessing the Visual Basic Editor.
VBA uses this code name to automatically declare a global-scope Worksheet object variable that your code gets to use anywhere to refer to that sheet, for free.
In other words, if the sheet exists in ThisWorkbook at compile-time, there's never a need to declare a variable for it - the variable is already there!
If the worksheet is created at run-time (inside ThisWorkbook or not), then you need to declare & assign a Worksheet variable for it.
Use the Worksheets property of a Workbook object to retrieve it:
Dim wb As Workbook
Set wb = Application.Workbooks.Open(path)
Dim ws As Worksheet
Set ws = wb.Worksheets(nameOrIndex)
Important notes...
Both the name and index of a worksheet can easily be modified by the user (accidentally or not), unless workbook structure is protected. If workbook isn't protected, you simply cannot assume that the name or index alone will give you the specific worksheet you're after - it's always a good idea to validate the format of the sheet (e.g. verify that cell A1 contains some specific text, or that there's a table with a specific name, that contains some specific column headings).
Using the Sheets collection contains Worksheet objects, but can also contain Chart instances, and a half-dozen more legacy sheet types that are not worksheets. Assigning a Worksheet reference from whatever Sheets(nameOrIndex) returns, risks throwing a type mismatch run-time error for that reason.
Not qualifying the Worksheets collection is an implicit ActiveWorkbook reference - meaning the Worksheets collection is pulling from whatever workbook is active at the moment the instruction is executing. Such implicit references make the code frail and bug-prone, especially if the user can navigate and interact with the Excel UI while code is running.
Unless you mean to activate a specific sheet, you never need to call ws.Activate in order to do 99% of what you want to do with a worksheet. Just use your ws variable instead.
Third solution:
I would set ws to a sheet of workbook wb as the use of Sheet("name") always refers to the active workbook, which might change as your code develops.
sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
'be aware as this might produce an error, if Shet "name" does not exist
Set ws = wb.Sheets("name")
' if wb is other than the active workbook
wb.activate
ws.Select
End Sub
Just coming across the same problem.
What you need to do is to declare ws as Object
Also it should be:
Set ws = wb.Sheets("Sheet1")
And should not be:
Set ws = Sheet("Sheet1")
The code below are working to me.
sub kl()
Dim wb As Workbook
Dim ws As Object
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
MsgBox ws.Name
End Sub
Try changing the name of the variable as sometimes it clashes with other modules/subs
Dim Workbk As Workbook
Dim Worksh As Worksheet
But also, try
Set ws = wb.Sheets("name")
I can't remember if it works with Sheet
to your surprise, you do need to declare variable for workbook and worksheet in excel 2007 or later version. Just add single line expression.
Sub kl()
Set ws = ThisWorkbook.Sheets("name")
ws.select
End Sub
Remove everything else and enjoy.
But why to select a sheet? selection of sheets is now old fashioned for calculation and manipulation.
Just add formula like this
Sub kl()
Set ws = ThisWorkbook.Sheets("name")
ws.range("cell reference").formula = "your formula"
'OR in case you are using copy paste formula, just use 'insert or formula method instead of ActiveSheet.paste e.g.:
ws.range("your cell").formula
'or
ws.colums("your col: one col e.g. "A:A").insert
'if you need to clear the previous value, just add the following above insert line
ws.columns("your column").delete
End Sub
I had the same issue. I used Worksheet instead of Worksheets and it was resolved. Not sure what the difference is between them.
Dim ws as Object
Set ws = Worksheets("name")
when declaring the worksheet as worksheet instead of an ojbect I had issues working with OptionButtons (Active X) in this worksheet (I guess the same will be with any Active-X element. When declared as object everything works fine.
Lots of answers above! here is my take:
Sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set ws = Sheets("name")
Set wb = ThisWorkbook
With ws
.Select
End With
End Sub
your first (perhaps accidental) mistake as we have all mentioned is "Sheet"... should be "Sheets"
The with block is useful because if you set wb to anything other than the current workbook, it will ececute properly