will fail in VBA because you can only use
Select on an object which is
Active. I understand this is the case.
What element of the Excel datamodel causes this to be the case? I would think there is an implicit intent from a user/coder to
Activate any object immediately prior to using
Select – I do not understand why VBA would not make this assumption, and, I am assuming there is a reason this distinction exists.
- What part of Excel’s datamodel prevents selection without activation?
As brettdj pointed out, you do not have to activate the sheet in order to select a range. Here’s a reference with a surprisingly large amount of examples for selecting cells/ranges.
Now as for the why do I have to active the sheet first? I do not believe it is a fault of the datamodel, but simply a limitation of the select method for Ranges.
From experimentation, it looks like there are two requirements to select a range in Excel.
- Excel must be able to update the UI to indicate what is selected.
- The ranges parent (I.E. the sheet) must be active.
To support this claim, you also cannot select a cell from a hidden sheet.
Sheets(1).Visible = False Sheets(1).Activate 'The next line fails because the Range cannot be selected. Sheets(1).Range("A1").Select
Simply put, when it comes to Ranges, you cannot select one you cannot see.
I would have claimed this is a limitation of select all together, except that you can actually select an object in a hidden sheet. Silly Excel.
I know that this is a bit late to the party, but I discovered a hack to do this…
Try this code:
Sheets(1).Activate Sheets(2).Range("A1").Copy Sheets(2).Range("A1").PasteSpecial xlPasteFormulas Application.CutCopyMode = False
Note that it is a hack, but it does the trick!!
@Daniel Cook: thanks for your response, but unfortunately Excel itself doesn’t play by the same rules imposed on Excel Macros…
To illustrate, I’ll briefly present my current problem…
I’m attempting to re-set a table’s contents to a common state. This method will be applied to multiple tables across various sheets:
Public Sub restoreTable() Dim myTableSheet As Worksheet: Set myTableSheet = Range("Table1").Parent Dim myTable As ListObject: Set myTable = myTableSheet.ListObjects("Table1") ' --- Clear Table's Filter(s) If myTable.ShowAutoFilter Then ' table has auto-filters enabled Call myTable.Range.AutoFilter ' disables autofilter End If myTable.Range.AutoFilter ' re-apply autofilter ' --- Sort by Sequence number Call myTable.Sort.SortFields.Clear ' if not cleared, sorting will not take effect myTable.Sort. _ SortFields.Add Key:=Range("Table1[[#Headers],[#Data],[Column1]]"), _ SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal myTable.Sort.Header = xlYes myTable.Sort.Orientation = xlTopToBottom myTable.Sort.SortMethod = xlPinYin Call myTable.Sort.Apply myTable.Sort.SortFields.Clear End Sub
For each use-case below,
Table1 is found in
Sheet1, select range
- observe: range
Sheet1, select range
- observe: range
A1is not selected, instead the range
It’s absolutely terrible, but this is the best solution I could find
Public Sub resotreTable_preserveSelection() Dim curSheet As Worksheet: Set curSheet = ActiveSheet Dim tableSheet As Worksheet: Set tableSheet = Range("Table1").Parent ' Change Sheet tableSheet.Activate ' Remember Selection / Active Ranges Dim originalSelection As Range: Set originalSelection = Selection Dim originalActiveCell As Range: Set originalActiveCell = ActiveCell ' Restore Table Call restoreTable ' Restore Old Selection originalSelection.Select originalActiveCell.Activate ' Change Back to old sheet curSheet.Activate End Sub
Note: in this case, the
original* ranges are not necessary, but you get the point: you can buffer the original selection and restore it when you’re finished
I really don’t like excel
Of course you don’t have to select or activate the sheet to select/activate the cell. My way is to use “On Error Resume Next” and “On Error GoTo 0”. Code below selects first cell in every worksheet of a workbook without selecting it. The worksheets are even very hidden on this stage.
On Error Resume Next For i_wks = 1 To wb_macro.Worksheets.Count wb_macro.Worksheets(i_wks).Cells(1).Select Next i_wks On Error GoTo 0