Как избежать использования Select в Excel VBA
Я много слышал о понятном отвращении к использованию .Select
в Excel VBA, но я не уверен, как избежать его использования. Я обнаружил, что мой код был бы более пригодным для повторного использования, если бы я мог использовать переменные вместо Select
функции. Тем не менее, я не уверен, как относиться к вещам (например, ActiveCell
и т. д.) если не используете Select
,
Я нашел эту статью о диапазонах и этот пример о преимуществах неиспользования выбора, но не могу найти что-нибудь о том, как?
13 ответов
Некоторые примеры того, как избежать выбора
использование Dim
переменные
Dim rng as Range
Set
переменная до необходимого диапазона. Есть много способов обратиться к диапазону с одной ячейкой
Set rng = Range("A1")
Set rng = Cells(1,1)
Set rng = Range("NamedRange")
или многосотовый диапазон
Set rng = Range("A1:B10")
Set rng = Range("A1", "B10")
Set rng = Range(Cells(1,1), Cells(10,2))
Set rng = Range("AnotherNamedRange")
Set rng = Range("A1").Resize(10,2)
Вы можете использовать ярлык для Evaluate
метод, но это менее эффективно и, как правило, следует избегать в производственном коде.
Set rng = [A1]
Set rng = [A1:B10]
Все приведенные выше примеры относятся к ячейкам на активном листе. Если вы специально не хотите работать только с активным листом, лучше затемнить Worksheet
переменная тоже
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
Set rng = ws.Cells(1,1)
With ws
Set rng = .Range(.Cells(1,1), .Cells(2,10))
End With
Если вы хотите работать с ActiveSheet
для ясности лучше всего быть явным. Но будьте осторожны, так как некоторые Worksheet
методы меняют активный лист.
Set rng = ActiveSheet.Range("A1")
Опять же, это относится к активной книге. Если вы специально не хотите работать только с ActiveWorkbook
или же ThisWorkbook
Дим, лучше Workbook
переменная тоже.
Dim wb As Workbook
Set wb = Application.Workbooks("Book1")
Set rng = wb.Worksheets("Sheet1").Range("A1")
Если вы хотите работать с ActiveWorkbook
для ясности лучше всего быть явным. Но позаботьтесь, как многие WorkBook
методы меняют активную книгу.
Set rng = ActiveWorkbook.Worksheets("Sheet1").Range("A1")
Вы также можете использовать ThisWorkbook
объект для ссылки на книгу, содержащую исполняемый код.
Set rng = ThisWorkbook.Worksheets("Sheet1").Range("A1")
Обычный (плохой) кусок кода - открыть книгу, получить некоторые данные и снова закрыть
Это плохо:
Sub foo()
Dim v as Variant
Workbooks("Book1.xlsx").Sheets(1).Range("A1").Clear
Workbooks.Open("C:\Path\To\SomeClosedBook.xlsx")
v = ActiveWorkbook.Sheets(1).Range("A1").Value
Workbooks("SomeAlreadyOpenBook.xlsx").Activate
ActiveWorkbook.Sheets("SomeSheet").Range("A1").Value = v
Workbooks(2).Activate
ActiveWorkbook.Close()
End Sub
И было бы лучше, как:
SUb foo()
Dim v as Variant
Dim wb1 as Workbook
Dim wb2 as Workbook
Set wb1 = Workbooks("SomeAlreadyOpenBook.xlsx")
Set wb2 = Workbooks.Open("C:\Path\To\SomeClosedBook.xlsx")
v = wb2.Sheets("SomeSheet").Range("A1").Value
wb1.Sheets("SomeOtherSheet").Range("A1").Value = v
wb2.Close()
End Sub
Передайте диапазоны на ваш Sub
и Function
в качестве переменных диапазона
Sub ClearRange(r as Range)
r.ClearContents
'....
End Sub
Sub MyMacro()
Dim rng as Range
Set rng = ThisWorkbook.Worksheets("SomeSheet").Range("A1:B10")
ClearRange rng
End Sub
Вы также должны применять методы (такие как Find
а также Copy
) к переменным
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = ThisWorkbook.Worksheets("SomeSheet").Range("A1:A10")
Set rng2 = ThisWorkbook.Worksheets("SomeSheet").Range("B1:B10")
rng1.Copy rng2
Если вы циклически изменяете диапазон ячеек, часто лучше (быстрее) сначала скопировать значения диапазона в вариантный массив и выполнить цикл по нему.
Dim dat As Variant
Dim rng As Range
Dim i As Long
Set rng = ThisWorkbook.Worksheets("SomeSheet").Range("A1:A10000")
dat = rng.Value ' dat is now array (1 to 10000, 1 to 1)
for i = LBound(dat, 1) to UBound(dat, 1)
dat(i,1) = dat(i,1) * 10 'or whatever operation you need to perform
next
rng.Value = dat ' put new values back on sheet
Это небольшой дегустатор для того, что возможно.
Две основные причины, почему .Select
/ .Activate
/ Selection
/ Activecell
/ Activesheet
/ Activeworkbook
и т.д... следует избегать
- Это замедляет ваш код.
- Обычно это основная причина ошибок во время выполнения.
Как мы этого избежать?
1) Непосредственно работать с соответствующими объектами
Рассмотрим этот код
Sheets("Sheet1").Activate
Range("A1").Select
Selection.Value = "Blah"
Selection.NumberFormat = "@"
Этот код также может быть записан как
With Sheets("Sheet1").Range("A1")
.Value = "Blah"
.NumberFormat = "@"
End With
2) При необходимости объявите свои переменные. Тот же код выше может быть записан как
Dim ws as worksheet
Set ws = Sheets("Sheet1")
With ws.Range("A1")
.Value = "Blah"
.NumberFormat = "@"
End With
Я добавлю один небольшой акцент ко всем превосходным ответам, данным выше:
Вероятно, самое большое, что вы можете сделать, чтобы избежать использования Select, - это максимально использовать именованные диапазоны (в сочетании со значимыми именами переменных) в вашем коде VBA. Этот момент был упомянут выше, но немного приукрашен; Однако это заслуживает особого внимания.
Вот еще несколько причин, по которым можно свободно использовать именованные диапазоны, хотя я уверен, что мог бы придумать еще.
Именованные диапазоны облегчают чтение и понимание вашего кода.
Пример:
Dim Months As Range
Dim MonthlySales As Range
Set Months = Range("Months")
'e.g, "Months" might be a named range referring to A1:A12
Set MonthlySales = Range("MonthlySales")
'e.g, "Monthly Sales" might be a named range referring to B1:B12
Dim Month As Range
For Each Month in Months
Debug.Print MonthlySales(Month.Row)
Next Month
Совершенно очевидно, что названные диапазоны Months
а также MonthlySales
содержать, и что делает процедура.
Почему это важно? Частично потому, что другим людям легче это понять, но даже если вы единственный человек, который когда-либо увидит или использует ваш код, вы все равно должны использовать именованные диапазоны и хорошие имена переменных, потому что ВЫ ЗАБУДЕТЕ то, что вы хотели с ним сделать год спустя, и вы потратите 30 минут на то, чтобы понять, что делает ваш код.
Именованные диапазоны гарантируют, что ваши макросы не сломаются, когда (не если!) Изменяется конфигурация электронной таблицы.
Рассмотрим, если приведенный выше пример был написан так:
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = Range("A1:A12")
Set rng2 = Range("B1:B12")
Dim rng3 As Range
For Each rng3 in rng1
Debug.Print rng2(rng3.Row)
Next rng3
Сначала этот код будет работать нормально - пока вы или будущий пользователь не примете решение: "Ну и дела, я думаю, что я собираюсь добавить новый столбец с указанием года в столбце". A
!", или поместите столбец расходов между месяцами и столбцами продаж, или добавьте заголовок к каждому столбцу. Теперь ваш код поврежден. И поскольку вы использовали ужасные имена переменных, вам потребуется гораздо больше времени, чтобы выяснить, как чтобы исправить это, чем это должно занять.
Если вы использовали именованные диапазоны для начала, Months
а также Sales
столбцы можно перемещать вокруг всего, что вам угодно, и ваш код будет работать нормально.
Я собираюсь дать короткий ответ, так как все остальные дали длинный.
Вы получите.select и.activate всякий раз, когда будете записывать макросы и использовать их повторно. Когда вы выбираете ячейку или лист, она просто становится активной. С этого момента всякий раз, когда вы используете неквалифицированные ссылки, такие как Range.Value
они просто используют активную ячейку и лист. Это также может быть проблематично, если вы не смотрите, где находится ваш код, или пользователь нажимает на книгу.
Таким образом, вы можете устранить эти проблемы, напрямую ссылаясь на ваши ячейки. Который идет:
'create and set a range
Dim Rng As Excel.Range
Set Rng = Workbooks("Book1").Worksheets("Sheet1").Range("A1")
'OR
Set Rng = Workbooks(1).Worksheets(1).Cells(1, 1)
Или ты мог
'Just deal with the cell directly rather than creating a range
'I want to put the string "Hello" in Range A1 of sheet 1
Workbooks("Book1").Worksheets("Sheet1").Range("A1").value = "Hello"
'OR
Workbooks(1).Worksheets(1).Cells(1, 1).value = "Hello"
Существуют различные комбинации этих методов, но это была бы общая идея, выраженная как можно короче для нетерпеливых людей, таких как я.
"... и я обнаружил, что мой код был бы более пригодным для повторного использования, если бы я мог использовать переменные вместо функций выбора".
Хотя я не могу думать о чем-то большем, чем об изолированной горстке ситуаций, когда .Select
было бы лучшим выбором, чем прямая ссылка на ячейку, я бы встал на защиту Selection
и указать, что его не следует выбрасывать по тем же причинам, что .Select
необходимо избегать.
Иногда бывают случаи, когда короткие подпрограммы макроса, позволяющие экономить время и назначаемые комбинациям горячих клавиш, которые доступны при нажатии нескольких клавиш, экономят много времени. Возможность выбора группы ячеек для введения в действие операционного кода творит чудеса, когда имеешь дело с карманными данными, которые не соответствуют формату данных всей таблицы. Во многом так же, как вы можете выбрать группу ячеек и применить изменение формата, выбор группы ячеек для запуска специального макрокодов может существенно сэкономить время.
Примеры подструктуры на основе выбора:
Public Sub Run_on_Selected()
Dim rng As Range, rSEL As Range
Set rSEL = Selection 'store the current selection in case it changes
For Each rng In rSEL
Debug.Print rng.Address(0, 0)
'cell-by-cell operational code here
Next rng
Set rSEL = Nothing
End Sub
Public Sub Run_on_Selected_Visible()
'this is better for selected ranges on filtered data or containing hidden rows/columns
Dim rng As Range, rSEL As Range
Set rSEL = Selection 'store the current selection in case it changes
For Each rng In rSEL.SpecialCells(xlCellTypeVisible)
Debug.Print rng.Address(0, 0)
'cell-by-cell operational code here
Next rng
Set rSEL = Nothing
End Sub
Public Sub Run_on_Discontiguous_Area()
'this is better for selected ranges of discontiguous areas
Dim ara As Range, rng As Range, rSEL As Range
Set rSEL = Selection 'store the current selection in case it changes
For Each ara In rSEL.Areas
Debug.Print ara.Address(0, 0)
'cell group operational code here
For Each rng In ara.Areas
Debug.Print rng.Address(0, 0)
'cell-by-cell operational code here
Next rng
Next ara
Set rSEL = Nothing
End Sub
Фактический код для обработки может быть чем угодно, от одной строки до нескольких модулей. Я использовал этот метод для запуска длительных подпрограмм на рваной выборке ячеек, содержащих имена внешних рабочих книг.
Короче, не выбрасывайте Selection
из-за его тесной связи с .Select
а также ActiveCell
, В качестве свойства листа он имеет много других целей.
(Да, я знаю, что этот вопрос был о .Select
не Selection
но я хотел бы устранить любые заблуждения, которые могут сделать начинающие VBA-кодеры.)
Как избежать Select
а также Activate
это шаг, который делает вас немного лучше разработчика VBA. В общем, Select
а также Activate
используются при записи макроса, таким образом, Parent
лист или диапазон всегда считается активным.
Вот как вы можете избежать Select
а также Activate
в следующих случаях:
Добавление нового рабочего листа и копирование в него ячейки:
From (код, сгенерированный с помощью устройства записи макросов):
Sub Makro2()
Range("B2").Select
Sheets.Add After:=ActiveSheet
Sheets("Tabelle1").Select
Sheets("Tabelle1").Name = "NewName"
ActiveCell.FormulaR1C1 = "12"
Range("B2").Select
Selection.Copy
Range("B3").Select
ActiveSheet.Paste
Application.CutCopyMode = False
End Sub
Для того, чтобы:
Sub TestMe()
Dim ws As Worksheet
Set ws = Worksheets.Add
With ws
.Name = "NewName"
.Range("B2") = 12
.Range("B2").Copy Destination:=.Range("B3")
End With
End Sub
Если вы хотите скопировать диапазон между листами:
От:
Sheets("Source").Select
Columns("A:D").Select
Selection.Copy
Sheets("Target").Select
Columns("A:D").Select
ActiveSheet.Paste
Для того, чтобы:
Worksheets("Source").Columns("A:D").Copy Destination:=Worksheets("Target").Range("a1")
Использование модных именованных диапазонов
Вы можете получить к ним доступ с []
, Что действительно красиво, по сравнению с другим способом. Проверь себя:
Dim Months As Range
Dim MonthlySales As Range
Set Months = Range("Months")
Set MonthlySales = Range("MonthlySales")
Set Months =[Months]
Set MonthlySales = [MonthlySales]
Пример сверху будет выглядеть так:
Worksheets("Source").Columns("A:D").Copy Destination:=Worksheets("Target").[A1]
Не копировать значения, а принимать их
Обычно, если вы готовы select
Скорее всего, вы что-то копируете. Если вас интересуют только значения, это хороший вариант, чтобы избежать выбора:
Range("B1:B6").Value = Range("A1:A6").Value
Старайтесь всегда ссылаться на рабочий лист
Это, наверное, самая распространенная ошибка в VBA. Всякий раз, когда вы копируете диапазоны, иногда на рабочий лист не ссылаются, и поэтому VBA рассматривает ActiveWorksheet.
'This will work only if the 2. Worksheet is selected!
Public Sub TestMe()
Dim rng As Range
Set rng = Worksheets(2).Range(Cells(1, 1), Cells(2, 2)).Copy
End Sub
'This works always!
Public Sub TestMe2()
Dim rng As Range
With Worksheets(2)
.Range(.Cells(1, 1), .Cells(2, 2)).Copy
End With
End Sub
Могу ли я действительно никогда не использовать .Select
или же .Activate
для всего?
Единственный раз, когда вы можете быть оправданы, чтобы использовать .Activate
а также .Select
это когда вы хотите убедиться, что конкретный рабочий лист выбран по визуальным причинам. Например, ваш Excel всегда будет открываться с выбранным первым листом обложки, не учитывая, какой лист был активным при закрытии файла. Таким образом, что-то вроде этого абсолютно нормально:
Private Sub Workbook_Open()
Worksheets("Cover").Activate
End Sub
Обратите внимание, что ниже я сравниваю подход Select (тот, который ОП хочет избежать) с подходом Range (и это ответ на вопрос). Так что не прекращайте читать, когда видите первый выбор.
Это действительно зависит от того, что вы пытаетесь сделать. В любом случае, простой пример может быть полезен. Давайте предположим, что вы хотите установить значение активной ячейки в "foo". Используя ActiveCell, вы могли бы написать что-то вроде этого:
Sub Macro1()
ActiveCell.Value = "foo"
End Sub
Если вы хотите использовать его для ячейки, которая не является активной, например, для "B2", вы должны сначала выбрать ее, например, так:
Sub Macro2()
Range("B2").Select
Macro1
End Sub
Используя диапазоны, вы можете написать более общий макрос, который можно использовать для установки значения любой ячейки, которую вы хотите, в любое, что вы хотите:
Sub SetValue(cellAddress As String, aVal As Variant)
Range(cellAddress).Value = aVal
End Sub
Затем вы можете переписать Macro2 как:
Sub Macro2()
SetCellValue "B2", "foo"
End Sub
И Macro1 как:
Sub Macro1()
SetValue ActiveCell.Address, "foo"
End Sub
Надеюсь, это поможет немного прояснить ситуацию.
Всегда указывайте рабочую книгу, рабочий лист и ячейку / диапазон.
Например:
Thisworkbook.Worksheets("fred").cells(1,1)
Workbooks("bob").Worksheets("fred").cells(1,1)
Поскольку конечные пользователи всегда будут просто нажимать кнопки, и как только фокус переместится с рабочей книги, код захочет работать с ним, тогда все пойдет не так.
И никогда не используйте индекс рабочей книги.
Workbooks(1).Worksheets("fred").cells(1,1)
Вы не знаете, какие другие рабочие книги будут открыты, когда пользователь выполнит ваш код.
Эти методы довольно стигматизированы, поэтому взяли на себя инициативу @Vityata и @Jeeped ради рисования линии на песке:
Почему бы не позвонить .Activate
, .Select
, Selection
, ActiveSomething
методы / свойства
В основном потому, что они вызваны прежде всего для обработки пользовательского ввода через пользовательский интерфейс приложения. Так как они являются методами, вызываемыми, когда пользователь обрабатывает объекты через пользовательский интерфейс, они записываются макрос-рекордером, и поэтому вызов их является либо хрупким, либо избыточным для большинства ситуаций: вам не нужно выбирать объект, чтобы выполнить действие с Selection
сразу после.
Тем не менее, это определение разрешает ситуации, к которым они обращаются:
Когда звонить .Activate
, .Select
, .Selection
, .ActiveSomething
методы / свойства
В основном, когда вы ожидаете, что конечный пользователь будет играть роль в исполнении.
Если вы разрабатываете и ожидаете, что пользователь выберет экземпляры объектов для вашего кода, тогда .Selection
или же .ActiveObject
являются подходящими.
С другой стороны, .Select
а также .Activate
полезны, когда вы можете сделать вывод о следующем действии пользователя и хотите, чтобы ваш код направлял пользователя, возможно сэкономив ему время и щелчки мышью. Например, если ваш код только что создал новый экземпляр диаграммы или обновил его, пользователь может захотеть проверить его, и вы можете вызвать .Activate
на нем или на его листе, чтобы сэкономить пользователю время на его поиск; или если вы знаете, что пользователю потребуется обновить некоторые значения диапазона, вы можете программно выбрать этот диапазон.
ИМХО использование .select
исходит от людей, которые, как и я, начали изучать VBA по необходимости, записывая макросы, а затем изменяя код, не осознавая, что .select
и последующее selection
это просто ненужный посредник.
.select
можно избежать, как многие уже опубликовали, напрямую работая с уже существующими объектами, что позволяет использовать различные косвенные ссылки, такие как сложные вычисления i и j, а затем редактировать ячейки (i,j) и т. д.
В противном случае, нет ничего неявного не так с .select
само по себе, и вы можете легко найти применение для этого, например, у меня есть таблица, которую я заполняю датой, активирую макрос, который делает с ним что-то волшебное, и экспортирует его в приемлемом формате на отдельном листе, что, однако, требует некоторого окончательного руководства (непредсказуемые) входы в соседнюю ячейку. Вот и наступил момент для .select
это спасает меня от этого дополнительного движения мыши и щелчка.
Быстрый ответ:
Чтобы избежать использования .Select
Методом вы можете установить переменную, равную тому свойству, которое вы хотите.
► Например, если вы хотите, чтобы значение в Cell A1
Вы можете установить переменную, равную значению свойства этой ячейки.
- пример
valOne = Range("A1").Value
► Например, если вы хотите использовать кодовое имя "Sheet3", вы можете установить переменную, равную свойству кодового имени этого листа.
- пример
valTwo = Sheets("Sheet3").Codename
Надеюсь, это поможет. Дайте знать, если у вас появятся вопросы.
Как избежать копипаста?
Посмотрим правде в глаза: этот часто появляется при записи макросов:
Range("X1").Select
Selection.Copy
Range("Y9).Select
Selection.Paste
А человек хочет только:
Range("Y9").Value = Range("X1").Value
Поэтому вместо использования копипаста в макросах VBA я бы посоветовал следующий простой подход:
Destination_Range.Value = Source_Range.Value
Я заметил, что ни один из этих ответов не упоминает свойство.Offset. Это также может быть использовано, чтобы избежать использования Select
действие при манипулировании определенными ячейками, особенно в отношении выбранной ячейки (как упоминается в OP ActiveCell
).
Вот пара примеров.
Я также предполагаю, что ActiveCell - это J4.
ActiveCell.Offset(2, 0).Value = 12
- Это изменит клетку
J6
быть значением 12 - Минус -2 будет ссылаться на J2
ActiveCell.Offset(0,1).Copy ActiveCell.Offset(,2)
- Это скопирует ячейку в
k4
вL4
, - Обратите внимание, что "0" не требуется в параметре смещения, если не требуется (,2)
- Как и в предыдущем примере, минус 1 будет
i4
ActiveCell.Offset(, -1).EntireColumn.ClearContents
- Это очистит значения во всех ячейках столбца k.
Это не значит, что они "лучше", чем описанные выше варианты, а просто перечисление альтернатив.
Основная причина никогда не использовать Select или Activesheet заключается в том, что у большинства людей будет открыта по крайней мере еще пара книг (иногда десятки), когда они запускают ваш макрос, и если они щелкают вдали от вашего листа во время выполнения вашего макроса и нажимают какой-либо другой книга, которую они открыли, то "Активная таблица" изменяется, и целевая книга для неквалифицированной команды "Выбрать" также изменяется.
В лучшем случае ваш макрос выйдет из строя, в худшем вы можете записать значения или изменить ячейки в неправильной книге, не имея возможности "отменить" их.
У меня есть простое золотое правило, которому я следую: добавьте переменные с именами "wb" и "ws" для объекта Workbook и объекта Worksheet и всегда используйте их для ссылки на мою книгу макросов. Если мне нужно сослаться на несколько книг или на несколько листов, я добавляю больше переменных.
например
Dim wb as Workbook
Dim ws as Worksheet
Set wb = ThisWorkBook
Set ws = wb.sheets("Output")
Команда "Set wb = ThisWorkbook" абсолютно важна. ThisWorkbook - это особое значение в Excel, которое означает книгу, из которой в настоящее время выполняется ваш код VBA. Очень полезный ярлык для установки переменной Workbook с помощью.
После того, как вы сделали это в верхней части подпрограммы, их использование не может быть проще, просто используйте их везде, где вы использовали бы "Выбор":
Итак, чтобы изменить значение ячейки "A1" в "Output" на "Hello" вместо:
Sheets("Output").Activate
ActiveSheet.Range("A1").Select
Selection.Value = "Hello"
Теперь мы можем сделать это:
ws.Range("A1").Value = "Hello"
Это не только намного надежнее и с меньшей вероятностью приведет к сбою, если пользователь работает с несколькими электронными таблицами, но и намного короче, быстрее и проще в написании.
В качестве дополнительного бонуса, если вы всегда называете свои переменные "wb" и "ws", вы можете копировать и вставлять код из одной книги в другую, и это обычно будет работать с минимальными необходимыми изменениями, если таковые имеются.
Работа с функцией.Parent. В этом примере показано, как установка только одной ссылки myRng обеспечивает динамический доступ ко всей среде без.Select, .Activate, .Activecell, .ActiveWorkbook, .ActiveSheet и т. Д. (Нет общей функции.Child)
Sub ShowParents()
Dim myRng As Range
Set myRng = ActiveCell
Debug.Print myRng.Address ' an address of the selected cell
Debug.Print myRng.Parent.name ' the name of sheet, where MyRng is in
Debug.Print myRng.Parent.Parent.name ' the name of workbook, where MyRng is in
Debug.Print myRng.Parent.Parent.Parent.name ' the name of application, where MyRng is in
' You may use this feature to set reference to these objects
Dim mySh As Worksheet
Dim myWbk As Workbook
Dim myApp As Application
Set mySh = myRng.Parent
Set myWbk = myRng.Parent.Parent
Set myApp = myRng.Parent.Parent.Parent
Debug.Print mySh.name, mySh.Cells(10, 1).Value
Debug.Print myWbk.name, myWbk.Sheets.Count
Debug.Print myApp.name, myApp.Workbooks.Count
' You may use dynamically addressing
With myRng
.Copy
' pastes in D1 on sheet 2 in the same workbook, where copied cell is
.Parent.Parent.Sheets(2).Range("D1").PasteSpecial xlValues
' or myWbk.Sheets(2).Range("D1").PasteSpecial xlValues
' we may dynamically call active application too
.Parent.Parent.Parent.CutCopyMode = False
' or myApp.CutCopyMode = False
End With
End Sub
Это пример, который очистит содержимое ячейки "A1" (или более, если тип выбора - xllastcell и т. Д.). Все сделано без выбора ячеек.
Application.GoTo Reference:=Workbook(WorkbookName).Worksheets(WorksheetName).Range("A1")
Range(Selection,selection(selectiontype)).clearcontents
Я надеюсь, что это помогает кому-то.