Я много слышал о понятном отвращении к использованию .Select
в Excel VBA, но не уверен, как его избежать. Я обнаружил, что мой код был бы более пригодным для повторного использования, если бы я мог использовать переменные вместо Select
функций. Тем не менее, я не уверен, как ссылаться на вещи (например, и ActiveCell
т. Д.), Если не использовать Select
.
Я нашел эту статью о диапазонах и этот пример о преимуществах неиспользования выбора, но ничего не могу найти о том, как ?
Select
и / или иActiveSheet
т. Д. Совершенно неизбежно. Вот пример, который я нашел: stackoverflow.com/questions/22796286/….Select / .Selection
, для того, чтобы установить для всех листов в книге одно и то же значение .Ответы:
Некоторые примеры того, как избежать выбора
Используйте
Dim
переменные dSet
переменная до необходимого диапазона. Есть много способов обратиться к диапазону одной ячейкиили многосотовый диапазон
Вы можете использовать ярлык для
Evaluate
метода, но он менее эффективен и его, как правило, следует избегать в рабочем коде.Все приведенные выше примеры относятся к ячейкам на активном листе . Если вы специально не хотите работать только с активным листом, лучше также затемнить
Worksheet
переменную.Если вы действительно хотите работать с
ActiveSheet
, для ясности , что лучше быть явным. Но будьте осторожны, так как некоторыеWorksheet
методы меняют активный лист.Опять же, это относится к активной книге . Если вы специально не хотите работать только с
ActiveWorkbook
илиThisWorkbook
, лучше также DimWorkbook
переменную.Если вы действительно хотите работать с
ActiveWorkbook
, для ясности , что лучше быть явным. Но будьте осторожны, так как многиеWorkBook
методы меняют активную книгу.Вы также можете использовать
ThisWorkbook
объект для ссылки на книгу, содержащую исполняемый код.Обычный (плохой) кусок кода - открыть книгу, получить некоторые данные и снова закрыть
Это плохо:
И было бы лучше, как:
Передайте диапазоны своим
Sub
s иFunction
s как переменные RangeВы также должны применять методы (такие как
Find
иCopy
) к переменнымЕсли вы циклически изменяете диапазон ячеек, часто лучше (быстрее) сначала скопировать значения диапазона в вариантный массив и выполнить цикл по нему.
Это небольшой дегустатор для того, что возможно.
источник
rng1(12, 12)
угол ... например, будет работать, даже если для rng1 было установлено[A1:A10]
только.Range
так:ActiveSheet.[a1:a4]
илиws.[b6]
.variant
Переменная не требует ,Set
пока вы не назначите объект к нему. Например,Dim x: x = 1
все в порядке, ноDim x: x = Sheets("Sheet1")
сгенерирует ошибку 438. Однако, просто перепутать / уточнитьDim x: x = Range("A1")
, не создаст ошибку. Почему? ... потому что ему присвоено значение объекта переменной, а не ссылка на сам объект (так как он эквивалентенDim x: x = Range("A1").Value
)Две основные причины, по которым
.Select
/.Activate
/Selection
/Activecell
/Activesheet
/ иActiveworkbook
т. Д ... следует избегатьКак мы этого избежать?
1) Непосредственно работать с соответствующими объектами
Рассмотрим этот код
Этот код также можно записать как
2) При необходимости объявите свои переменные. Тот же код выше может быть записан как
источник
Sheets(2).[C10:D12].Value = Sheets(1).[A1:B3].Value
.Activate
для перехода к исходному листу, просто используйтеApplication.Goto
Я добавлю один небольшой акцент ко всем превосходным ответам, данным выше:
Вероятно, самое большое, что вы можете сделать, чтобы избежать использования Select, - это максимально использовать именованные диапазоны (в сочетании со значимыми именами переменных) в вашем коде VBA . Этот момент был упомянут выше, но немного затенен; Однако это заслуживает особого внимания.
Вот еще несколько причин, по которым можно свободно использовать именованные диапазоны, хотя я уверен, что мог бы придумать еще.
Именованные диапазоны облегчают чтение и понимание вашего кода.
Пример:
Совершенно очевидно, что именованные диапазоны
Months
иMonthlySales
содержат, и что делает процедура.Почему это важно? Частично потому, что другим людям легче понять это, но даже если вы единственный человек, который когда-либо увидит или использует ваш код, вы все равно должны использовать именованные диапазоны и хорошие имена переменных, потому что ВЫ ЗАБУДЕТЕ то, что вы хотели с ним сделать год спустя, и вы потратите 30 минут на то, чтобы понять, что делает ваш код.
Именованные диапазоны гарантируют, что ваши макросы не сломаются, когда (не если!) Изменяется конфигурация электронной таблицы.
Рассмотрим, был ли приведенный выше пример написан так:
Сначала этот код будет работать нормально - пока вы или будущий пользователь не примете решение: «Ну и дела, я думаю, я собираюсь добавить новый столбец с
A
указанием года в столбце !» Или поместить столбец расходов между месяцами и столбцы продаж, или добавьте заголовок к каждому столбцу. Теперь ваш код не работает. А поскольку вы использовали ужасные имена переменных, вам потребуется гораздо больше времени, чтобы понять, как это исправить, чем нужно.Если вы использовали именованные диапазоны , чтобы начать с того , что
Months
иSales
столбцы могут быть перемещены все , что вам нравится, и ваш код будет продолжать работать нормально.источник
Я собираюсь дать короткий ответ, так как все остальные дали длинный.
Вы будете получать .select и .activate всякий раз, когда будете записывать макросы и использовать их повторно. Когда вы выбираете ячейку или лист, она просто становится активной. С этого момента всякий раз, когда вы используете неквалифицированные ссылки, как будто
Range.Value
они просто используют активную ячейку и лист. Это также может быть проблематично, если вы не смотрите, где находится ваш код, или пользователь нажимает на книгу.Таким образом, вы можете устранить эти проблемы, напрямую ссылаясь на ваши ячейки. Который идет:
Или ты мог
Существуют различные комбинации этих методов, но это была бы общая идея, выраженная как можно короче для нетерпеливых людей, таких как я.
источник
Хотя я не могу думать ни о чем большем, чем об отдельной ситуации, когда
.Select
выбор будет лучше, чем прямая ссылка на ячейку, я бы встал на защитуSelection
и указал, что его не следует выбрасывать по тем же причинам, которых.Select
следует избегать.Бывают случаи, когда короткие, подпрограммы макроса, позволяющие экономить время и назначаемые сочетаниям горячих клавиш, которые доступны при нажатии пары клавиш, экономят много времени. Возможность выбора группы ячеек для введения в действие операционного кода творит чудеса, когда имеешь дело с карманными данными, которые не соответствуют формату данных всей таблицы. Во многом так же, как вы можете выбрать группу ячеек и применить изменение формата, выбор группы ячеек для запуска специального макрокодов может быть значительным сбережением времени.
Примеры подструктуры на основе выбора:
Фактический код для обработки может быть чем угодно, от одной строки до нескольких модулей. Я использовал этот метод для запуска долго выполняющихся подпрограмм на рваной выборке ячеек, содержащих имена внешних рабочих книг.
Короче говоря, не выбрасывайте
Selection
из-за его тесной связи с.Select
иActiveCell
. В качестве свойства листа он имеет много других целей.(Да, я знаю, что этот вопрос был о
.Select
,Selection
но я хотел удалить любые заблуждения, которые могут предположить начинающие программисты VBA.)источник
Selection
в рабочей таблице может быть что угодно, поэтому можно также сначала проверить тип объекта, прежде чем назначить его переменной, поскольку вы явно объявили его какRange
.Обратите внимание, что ниже я сравниваю подход Select (тот, который ОП хочет избежать) с подходом Range (и это ответ на вопрос). Так что не прекращайте читать, когда увидите первый выбор.
Это действительно зависит от того, что вы пытаетесь сделать. В любом случае простой пример может быть полезен. Предположим, вы хотите установить значение активной ячейки в «foo». Используя ActiveCell, вы могли бы написать что-то вроде этого:
Если вы хотите использовать его для ячейки, которая не является активной, например, для «B2», вы должны сначала выбрать ее, например, так:
Используя диапазоны, вы можете написать более общий макрос, который можно использовать для установки значения любой ячейки, которую вы хотите, в любое, что вы хотите:
Затем вы можете переписать Macro2 как:
И Макро1 как:
Надеюсь, это поможет немного прояснить ситуацию.
источник
Избегание
Select
иActivate
это шаг, который делает вас немного лучше VBA разработчика. В общем,Select
иActivate
используются , когда макрос записывается, таким образом,Parent
рабочий лист или диапазон всегда считается активным.Вот как вы можете избежать
Select
иActivate
в следующих случаях:Добавление нового рабочего листа и копирование в него ячейки:
From (код, сгенерированный с помощью устройства записи макросов):
Для того, чтобы:
Если вы хотите скопировать диапазон между листами:
От:
Для того, чтобы:
Использование модных именованных диапазонов
Вы можете получить к ним доступ
[]
, что действительно прекрасно, по сравнению с другими способами. Проверь себя:Пример сверху будет выглядеть так:
Не копировать значения, но принимать их
Обычно, если вы готовы
select
, скорее всего, вы что-то копируете. Если вас интересуют только значения, это хороший вариант, чтобы избежать выбора:Range("B1:B6").Value = Range("A1:A6").Value
Старайтесь всегда ссылаться на рабочий лист
Это, наверное, самая распространенная ошибка в УВА, Всякий раз, когда вы копируете диапазоны, иногда на лист не ссылаются, и поэтому VBA считает неправильный лист ActiveWorksheet.
Могу ли я действительно никогда не использовать
.Select
или.Activate
для чего-либо?.Activate
и.Select
когда вы хотите убедиться, что конкретный Рабочий лист выбран по визуальным причинам. Например, ваш Excel всегда будет открываться с выбранным первым листом обложки, независимо от того, какой лист ActiveSheet был закрыт при закрытии файла.Таким образом, что-то вроде приведенного ниже кода абсолютно нормально:
Еще один хороший пример, когда вам нужно экспортировать все листы в один файл PDF, как уже упоминалось в этом случае. Как избежать операторов выбора / активных в VBA в этом примере?
Когда команда работает только с
ActiveWindow
как ActiveWindow.Zoom или ActiveWindow.FreezePanesисточник
.Select
а также моей работы - можно найти в разделе Как написать одинаковую информацию для всех листов - @Vityata :).FillAcrossSheets
, так что это где-то посередине (по крайней мере, в моем представлении о таксономии VBA)Всегда указывайте рабочую книгу, рабочий лист и ячейку / диапазон.
Например:
Поскольку конечные пользователи всегда будут просто нажимать кнопки, и как только фокус переместится с рабочей книги, код захочет работать с ним, тогда все пойдет не так.
И никогда не используйте индекс рабочей книги.
Вы не знаете, какие другие рабочие книги будут открыты, когда пользователь выполнит ваш код.
источник
Эти методы довольно стигматизированы, поэтому взяли на себя инициативу @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
Надеюсь, это поможет. Дайте знать, если у вас появятся вопросы.
источник
Я заметил, что ни один из этих ответов не упоминает свойство .Offset . Это также можно использовать, чтобы избежать использования
Select
действия при манипулировании определенными ячейками, особенно в отношении выбранной ячейки (как упоминается в OPActiveCell
).Вот пара примеров.
Я также предполагаю, что ActiveCell - это J4 .
ActiveCell.Offset(2, 0).Value = 12
J6
на значение 12ActiveCell.Offset(0,1).Copy ActiveCell.Offset(,2)
k4
наL4
.i4
ActiveCell.Offset(, -1).EntireColumn.ClearContents
Это не значит, что они «лучше», чем описанные выше варианты, а просто перечисление альтернатив.
источник
Работа с .Parent функцией. В этом примере показано, как установка только одной ссылки myRng обеспечивает динамический доступ ко всей среде без .Select, .Activate, .Activecell, .ActiveWorkbook, .ActiveSheet и т. Д. (Там нет общего. Детский особенность)
источник
Основная причина никогда не использовать Select или Activesheet состоит в том, что у большинства людей при запуске макроса будет открыта как минимум еще пара рабочих книг (иногда десятков), и если они щелкают по листу во время работы макроса и нажимают на другие Книга, которую они открыли, затем «Activesheet» изменяется, и целевая рабочая книга для неквалифицированной команды «Select» также изменяется.
В лучшем случае ваш макрос потерпит крах, в худшем случае вы можете в итоге записать значения или изменить ячейки в неправильной книге, не имея возможности отменить их.
У меня есть простое золотое правило, которому я следую: добавьте переменные с именами "wb" и "ws" для объекта Workbook и объекта Worksheet и всегда используйте их для ссылки на мою книгу макросов. Если мне нужно сослаться на более чем одну книгу или более чем на один лист, я добавляю больше переменных.
например
Команда «Set wb = ThisWorkbook» является абсолютно ключевой. «ThisWorkbook» - это специальное значение в Excel, и оно означает рабочую книгу, из которой в данный момент выполняется код VBA . Очень полезный ярлык для установки переменной Workbook с помощью.
После того, как вы сделали это в верхней части вашего Sub, их использование не может быть проще, просто используйте их везде, где вы бы использовали «Selection»:
Таким образом, чтобы изменить значение ячейки «A1» в «Вывод» на «Hello» вместо:
Теперь мы можем сделать это:
Который не только намного более надежен и менее вероятен сбой, если пользователь работает с несколькими электронными таблицами, он также намного короче, быстрее и проще для написания.
В качестве дополнительного бонуса, если вы всегда называете свои переменные «wb» и «ws», вы можете копировать и вставлять код из одной книги в другую, и он обычно будет работать с минимальными необходимыми изменениями, если таковые имеются.
источник
ThisWorkbook
... Я не уверен, что ваш комментарий точен.Это пример, который очистит содержимое ячейки «A1» (или больше, если тип выбора - xllastcell и т. Д.). Все сделано без выбора ячеек.
Я надеюсь, что это помогает кому-то.
источник
Workbook(WorkbookName).Worksheets(WorksheetName).Range("A1").ClearContents
одной строкой, а не двумя, и на самом деле работает без выбора ячеек.