|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Выношу на суд общественности, принимаются предложения, поправки, дополнения. Думаю, что также нужно больше примеров. ------------------------------------------------------------------------------------ Заглавное утверждение этой статьи: Уберите из своего кода Select, Selection, Activate а также то, что начинается с Active (ActiveSheet, ActiveDocument, ActiveWorkbook, ActiveCell и т.п.) Теперь разберем подробнее. А почему нужно от всего этого избавиться? Во-первых – код можно сильно сократить, его будет легче читать, разбирать, редактировать, он будет работать быстрее. Во-вторых – это источник глюков программы, зачастую трудноуловимых. Прежде всего это вмешательство пользователя. Пока программа работает, пользователь может тыкнуть мышкой куда попало, переключиться на другое окно и т.п. Выделение или активная книга меняется и в лучшем случае программа вылетает, в худшем – запорет нужные данные. Также я сталкивался, что разные версии офиса могут вести себя по-разному с активными документами, и программа, написанная в одной версии Экселя, работая с ActiveWorkbook, неверно работала в другой версии. Откуда все берется? Ну прежде всего из записи макросов. Стандартная и разумная рекомендация – если не знаешь, как сделать что-то – запусти запись макроса и сделай нужные действия. Но только макрос ведь пишет все действия пользователя, а пользователь сначала выделяет объект, а потом с ним что-то делает. Поэтому и получается, что макрос сначала записывает команду Select, а потом какие-то действия над Selection. Записав макрос, дальше стоит его разобрать, вычленить необходимые методы и функции и убрать лишнее. Или посмотреть, как записался макрос, а дальше писать свою программу. Как избавиться? Рассмотрим на примере Экселя. Прежде всего сама книга. В большинстве случаев ActiveWorkbook надо заменить на ThisWorkbook. ActiveWorkbook – это активная книга (которую, как я упоминал, пользователь или какие-то обстоятельства могут изменить). А ThisWorkbook – это книга, в которой находится ваша программа и она всегда одна и та же, даже если активная книга поменялась. Иногда ActiveWorkbook используется для работы с другой книгой, открытой или созданной из текущей. В этом случае надо поступить следующим образом: Код: vbnet 1. 2. 3. 4. 5. 6. 7.
С полученной переменной можно делать то, что раньше делалось через ActiveWorkbook. Например закрыть эту книгу: Код: vbnet 1.
А как избавиться от Selection? К примеру, мы покрасим текст в нескольких ячейках на другом листе. Записанный макрос будет выглядеть так: Код: vbnet 1. 2. 3.
Но это запись действий пользователя. А нам совсем необязательно повторять все за пользователем. Мы можем покрасить текст напрямую: Код: vbnet 1.
А если это нужно сделать в ранее созданной (см. выше) другой книге, то так: Код: vbnet 1.
А когда работа с Select, Active и прочим все же требуется? В немногих случаях. Во-первых, когда требуется взаимодействие с пользователем. Например, пользователь на свое усмотрение выделил какой-то диапазон ячеек, а нам его нужно программой обработать. Тогда мы как раз и обращаемся к Selection. Или когда пользователю после завершения работы макроса требуется что-то отобразить или выделить. Тогда мы используем Activate или Select (как правило, как последнюю команду в работе программы). Во-вторых, есть все-таки ситуации, в которых не обойтись без Select. Я пока столкнулся с одной ситуацией, в которой не нашел другого пути (впрочем, это не значит, что его нет), а именно программное закрепление областей в Экселе: Код: vbnet 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
07.04.2012, 23:11 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Замени Sheets на Worksheets. Sheets это не только таблицы, это любые листы. Упомяни что никогда нельзя писать просто Range() (как это сделано в твоем примере про закрепление областей). Если Range() ни к чему не привязан, то он неявно берется от текущего объекта с фокусом, а это может быть все что угодно, в том числе и кнопка на листе у которой Range в принципе быть не может и макрос умрет. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.04.2012, 09:11 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Shocker.ProА как избавиться от Selection? К примеру, мы покрасим текст в нескольких ячейках на другом листе. Записанный макрос будет выглядеть так: Код: vbnet 1. 2. 3.
Но это запись действий пользователя. А нам совсем необязательно повторять все за пользователем. Мы можем покрасить текст напрямую: Код: vbnet 1.
имхо, когда речь о "переделке" записанного макроса, удобно (и быстро) переписать через with / end with Код: vbnet 1. 2. 3. 4. 5.
что в случае нескольких команд в конечном with (там где .Font.ColorIndex = 3) , ещё и плюс по скорости выполнения ... |
|||
:
Нравится:
Не нравится:
|
|||
08.04.2012, 09:33 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
White OwlЗамени Sheets на Worksheets. Sheets это не только таблицы, это любые листы.я-то это знаю, но именно так записывает макрос. В случае, когда обращаешься через имя листа, этот момент ведь не имеет значения, или я не прав? qwerty112имхо, когда речь о "переделке" записанного макроса, удобно (и быстро) переписать через with / end withДело в том, что те, кто хорошо владеет объектным программированием, это все и так знает. Я-то ориентируюсь на тех, кто в этом плавает и хочу объяснить как можно проще и не забивать голову дополнительной информацией. ИМХО, поначалу тогда нужно показать, как упростить путь к объекту через объектную переменную, а потом уже через With White OwlУпомяни что никогда нельзя писать просто Range()да, это, пожалуй, стоит расписать. Что касается коллекции Worksheets и т.п. - она при обращении без указания книги всегда относится к ThisWorkbook или могут быть варианты? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.04.2012, 10:57 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Еще можно упомянуть, что если обращение идет к конкретной ячейке, а не диапазону, то лучше использовать Cells, а не Range, Cells работает быстрее. Shocker.ProЧто касается коллекции Worksheets и т.п. - она при обращении без указания книги всегда относится к ThisWorkbook или могут быть варианты?Без вариантов. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.04.2012, 13:29 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Shocker.ProWhite OwlЗамени Sheets на Worksheets. Sheets это не только таблицы, это любые листы.я-то это знаю, но именно так записывает макрос. В случае, когда обращаешься через имя листа, этот момент ведь не имеет значения, или я не прав?В принципе прав, но если человек попытается сделать перебор "все листы книги", а такие вопросы возникают часто. То Sheets при наличии листов другого типа породит кучку артефактов... С другой стороны, если человек напорется, то может быть он научиться? Или я слишком многого хочу? Shocker.ProИМХО, поначалу тогда нужно показать, как упростить путь к объекту через объектную переменную, а потом уже через WithВот-вот. Shocker.ProЧто касается коллекции Worksheets и т.п. - она при обращении без указания книги всегда относится к ThisWorkbook или могут быть варианты?не знаю. Но по моему оно тоже должно работать на основе объекта с фокусом. Впрочем, пути микрософта неисповедимы. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.04.2012, 20:35 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
White OwlНо по моему оно тоже должно работать на основе объекта с фокусом.Объект с фокусом это Active, а This — объект, в контексте которого исполняется код. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.04.2012, 21:58 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
AntonariyWhite OwlНо по моему оно тоже должно работать на основе объекта с фокусом.Объект с фокусом это Active, а This — объект, в контексте которого исполняется код. Неверно. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.04.2012, 02:53 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
White OwlAntonariyпропущено... Объект с фокусом это Active, а This — объект, в контексте которого исполняется код. Неверно. а поподробнеее пожалуйста ... |
|||
:
Нравится:
Не нравится:
|
|||
09.04.2012, 08:26 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Да уж, заинтриговал. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.04.2012, 08:37 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
AntonariyWhite OwlНо по моему оно тоже должно работать на основе объекта с фокусом.Объект с фокусом это Active, а This — объект, в контексте которого исполняется код.У Экселя есть Active* объекты, это те которые сам Эксель считает активными. А фокус это свойство системы, это внутренний указатель самой ОС который показывает какой виджет будет получать события клавиатуры. Виджеты ОС и объекты Экселя это очень разные вещи, которые, по хорошему, должны быть либо совсем независимыми либо совершенно синхронными. Но! Эксель имеет кучку багов овеянных временем и ставшими фичами - в частности команды Select и Activate которые в зависимости от объекта на которые вызваны могут перемещать фокус а могут не перемещать. Active* для некоторых объектов следует за фокусом, для некоторых не следует. Когда мы к этому ералашу добавляем контекстные вызовы без явного указания контекста - получается вообще кошмар. В Экселе по существу есть три контекстно активных объекта - this, active и виджет с фокусом. Какой из них будет использоваться для вызова контекстно зависимых методов зависит от метода. Не от каких-то общих правил, а у каждого метода есть свой "предпочтительный" контекст. Если ты способен точно помнить какой контекст когда будет использоваться, и ты веришь что в другой версии Экселя эти правила не изменяться - можешь использовать Range() и Sheets() без явного указания кому они принадлежат. Ну а если хочешь писать надежные макросы - привыкни всегда явно указывать контекст. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.04.2012, 18:54 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
White OwlAntonariyпропущено... Объект с фокусом это Active, а This — объект, в контексте которого исполняется код.У Экселя есть Active* объекты, это те которые сам Эксель считает активными. А фокус это свойство системы, это внутренний указатель самой ОС который показывает какой виджет будет получать события клавиатуры.Подразумевалось объект экселя с фокусом. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.04.2012, 23:39 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
White OwlЕсли ты способен точно помнить какой контекст когда будет использоваться, и ты веришь что в другой версии Экселя эти правила не изменяться - можешь использовать Range() и Sheets() без явного указания кому они принадлежат.Без явного указания Range и Cells можно использовать ничего не опасаясь в контексте листа, а Sheets в контексте книги, и это будут ThisWorksheet и ThisWorkbook соответственно. Sheets(x) можно использовать в контексте листа и это будет ThisWorkbook. Использовать Cells и Range в контексте книги нельзя. Использовать их же и Sheets в контексте модуля нельзя. Никаких исключений из этих правил ни в одной версии экселя нет. Следуя этим правилам, я ни разу не повстречался ни с одним из "кучи багов". ... |
|||
:
Нравится:
Не нравится:
|
|||
09.04.2012, 23:56 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Уважаемые гуру, поскольку здесь создается нетленка (эпохалка) для будущих поколений предлагаю Ексель заменить на Excel ибо первое носит слегка неуважительный оттенок При всем наблюдаемом море багов от MS все же ничего лучшего пока на горизонте не просматривается ================ ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 10:46 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
MX-9, Ok ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 11:19 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
А кто знает как обойтись без ActiveWorkbook при копировании Worksheet из текущей книги с созданием новой. Т.е. такое не катит Код: vbnet 1. 2. 3. 4. 5. 6. 7.
Хотя книга является результатом Worksheets("Sheet2").Copy. А вот такое работает Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8.
... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 11:51 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
А у вас тут вообще туши свет. 1) Copy это процедура, а не функция. 2) Копируя лист вы никак не получите книгу . ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 13:30 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Но я получаю. По крайней мере в Excel 2010. Руками это делается так: на листе книги правой кнопкой, потом "Move or Copy", to book "(new book)", галочка "Create a copy" - и все - в результате копирования имеем новую книгу. Вы первый код запускали? Новая книга создается? У меня да. Но она не присваивается объектной переменной. Хотя она книга. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 14:14 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Код: vbnet 1. 2.
кто вообще сказал, что метод возвращает книгу??? ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 14:17 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Вот я и спрашиваю, как провернуть данную операцию без ActiveWorkbook. Первый код приведен чисто для иллюстрации, я не говорю что он верен. Логика такова: результатом Код: vbnet 1.
является создание новой книги с копией листа "Sheet2". Как эту книгу "запихать" в объектную переменную без использования Код: vbnet 1.
? Я хочу быть уверен, что я "пихаю" именно эту книгу, а не какую нибудь другую, так понятно? А то все такие умные прям. Работай бы первый код, я бы знал наверняка, что в объекте сидит то что надо. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 14:28 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Я думаю, что книга всегда добавляется в конец коллекции, поэтому можно Код: vbnet 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 14:41 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Shocker.Pro, Кстати, это тоже не гарантирует того что в Wb попадет книга, созданная в результате вызова метода Worksheets("Sheet2").Copy. Мало ли что произойдет между Код: vbnet 1.
и Код: vbnet 1.
Так что тут надо быть внимательным. Конечно самый верный способ это Код: vbnet 1.
и далее по тексту гонять листы как надо. Но с Worksheets("Sheet2").Copy оказия получается, ведь в результате имеем новую книгу. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 14:59 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Диклевич Александр, после Worksheets("Sheet2").Copy создается не только книга - но и лист поэтому, видимо, и не проходит Set Wb = Worksheets("Sheet2").Copy '424 - Object required - из-за неоднозначности результата как указано выше - на выходе просто TRUE ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 15:20 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
MX-9, Да это все понятно, что создается книга с листом и все такое. Вопрос в том как эту книгу (книга - это же объект Excel) присвоить объектной переменной Wb типа Workbook для дальнейшей работы, да так чтобы быть уверенным что я присваиваю именно эту книгу. Set Wb = ActiveWorkbook и Set Wb = Workbooks(Workbooks.Count) не дают уверенности что я присваиваю именно то что надо, т.к. мало ли что произойдет между Worksheets("Sheet2").Copy и присваиванием. А это не хорошо. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 15:32 |
|
Проект статьи для FAQ про избавление от Select
|
|||
---|---|---|---|
#18+
Shocker.Proкто вообще сказал, что метод возвращает книгу???Кто сказал, что метод вообще что-то возвращает??????77 F2 Код: plaintext 1.
Диклевич АлександрНо я получаю.Я забыл, если не указывать параметры, то создается копия в новой книге. И никаких ссылок на новые объекты никуда не возвращается. Однако все равно не вижу проблем, багов и загадок. Вижу отсутствие понимания процессов. Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9.
Диклевич Александр Мало ли что произойдет между Worksheets("Sheet2").Copy и Set Wb = Workbooks(Workbooks.Count)Ничего не произойдет. Ничего физически не может произойти (если только не воткнуть туда DoEvents) — работа макроса и действия пользователя обрабатываются в одном и том же потоке, а значит они не могут происходить одновременно. Все макросы всех открытых книг будут исполняться в одном потоке по очереди, а значит тоже не могут пересечься. поэтому, видимо, и не проходит Set Wb = Worksheets("Sheet2").Copy '424 - Object required - из-за неоднозначности результата как указано выше - на выходе просто TRUEОпять эта ерунда... Результат более чем однозначен. Просто вы его не понимаете. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.04.2012, 15:34 |
|
|
start [/forum/topic.php?fid=60&msg=37746837&tid=2157908]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
35ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
56ms |
get tp. blocked users: |
1ms |
others: | 16ms |
total: | 150ms |
0 / 0 |