Модули формы и класса довольно специфичны, и если вы до них дошли, то этот пост точно не для вас: вы и так всё знаете.
У остальных модулей - своё назначение, так куда же положить код? Как выбрать подходящее место? На определённом этапе всё станет очевидно, но что делать с самым первым макросом?
Ответ 1: модули листа и книги должны содержать только код, который обрабатывает события листа и книги соответственно (но это же наш первый макрос, какие ещё события?); получается, что единственным местом остаётся модуль.
Ответ 2: если не знаете, куда поместить код, используйте модуль; кстати, записанные макросы попадают именно в модули.
Ответ 3: почти всегда можно использовать любое место, но нужно знать кое-какие особенности, т.к. в зависимости от места расположения один и тот же код может дать разные результаты или привести к ошибке. Связано это с объектной моделью, которая определяет, с какими данными работает код в тот или иной момент времени.
Объект верхнего уровня - Application (собственно приложение Excel). В большинстве случаев его можно не указывать.
Следующий уровень - объект Workbook (книга). Все объекты этого уровня входят в коллекцию Workbooks и на каждый из них можно сослаться
Application.Workbooks("Книга1")
Workbooks("Книга1").
Далее - объект Worksheet (лист). Все объекты этого уровня входят в коллекции Worksheets и на каждый из них можно сослаться разными способами:
Application.Workbooks("Книга1").Worksheets("Лист1")
Workbooks("Книга1").Worksheets("Лист1")
Worksheets("Лист1")
Кроме того, все объекты Worksheet входят в коллекцию Sheets, т.е. можно обращаться к ним:
Application.Workbooks("Книга1").Sheets("Лист1")
Workbooks("Книга1").Sheets("Лист1")
Sheets("Лист1")
Далее остаётся только получить конкретную ячейку на листе в книге. Для получения ячейки используется свойство Cells объекта Worksheet. Для упрощения (очень-очень сильного упрощения) можно считать ячейку концом цепочки:
Application.Workbooks("Книга1").Sheets("Лист1").Cells(1, 1)
Workbooks("Книга1").Sheets("Лист1").Cells(1, 1)
Sheets("Лист1").Cells(1, 1)
Cells(1, 1)
Остаётся упомянуть ещё несколько крайне важных вещей:
Application.ActiveWorkbook или ActiveWorkbook возвращает активную книгу
Application.ActiveSheet или ActiveSheet возвращает активный лист
Application.ThisWorkbook или ThisWorkbook возвращает книгу, в которой расположен код
ThisWorkSheet - ошибка, нет такого слова!
И вот теперь можно, наконец, сказать главное: всегда, в каждой строчке кода, в любой момент времени нужно точно знать цепочку Workbook > Worksheet, потому что почти во всех случаях, если эта цепочка не указана явно, подразумевается активный лист и активная книга. Т.е. если код, расположенный в любом месте в "Книга1", выполняется при активной "Книга2", то он будет работать с данными и изменять содержимое активного листа книги "Книга2".
Исключение: если код расположен в модуле листа, то он всегда работает с этим листом. Т.е всегда подразумевается ThisWorkSheet (которого не существует - и теперь понятно почему: он может существовать только в модуле листа, а там он подразумевается по умолчанию). Разумеется, это не мешает использовать явное указание на другой лист или книгу.
Например, код
Cells(1, 1)
расположенный в модуле листа, всегда будет работать с этим листом. Этот же код, расположенный в модуле или модуле книги, будет работать с активным листом активной книги.
Код
Workbooks("Книга1").Sheets("Лист1").Cells(1, 1)
всегда будет работать одинаково.
Таким образом:
- если вы совершенно точно собираетесь работать только с одним листом, то можно поместить код в модуль листа, это визуально упростит код;
- во всех остальных случаях при каждом обращении к свойствам или методам книги или листа (в том числе, и обращение к данным - Cells и т.п.) вы должны "тащить" всю цепочку начиная от Workbook, а в этом случае нет никаких причин использовать модули листа или книги.
Далее предполагаем, что с местом расположения кода мы определились - это модуль (Модуль. Просто Модуль. Взболтать, а не смешивать).
Существуют разные способы упростить код и избежать ошибок.
1. Если вы уверены, что работа с активным листом активной книги - всё, что вам нужно, то цепочку Workbook > Worksheet в большинстве случаев можно опустить.
2. Оператор With:
With Workbooks("Книга1").Sheets("Лист1")
.Cells(1, 1) = 1
End With
эквивалентен
Workbooks("Книга1").Sheets("Лист1").Cells(1, 1)
Т.е. все свойства и методы внутри этого оператора, которые начинаются с ".", относятся к указанному объекту, а без точки - к активному листу активной книги
3. Переменные типа объект (и помните: любой код в VBA должен начинаться с Option Exlicit - два этих слова уберегут вас от миллионов ошибок)
4. Можно просто сделать нужный лист активным (лично я не люблю этот метод, но почему бы и нет)
Понимание объектной модели данных и умение точно указывать на объект, его свойства и методы, в Excel VBA чрезвычайно важны, без этого любые попытки что-то сделать будут мучением.