
2 семестр / vba_2002
.pdf
Моя функция рабочего листа отображается в категории Определенные пользователем в диалоговом окне Мастер функций. Как переместить функцию в другую категорию?
Для этого необходимо воспользоваться кодом VBA. Следующий оператор перемешает функцию MyFunc в категорию 1 (Финансовые функции):
Application.MacroOptions Macro:="MyFunc", Category:=1
Представленная ниже таблица содержит список допустимых номеров категорий функции.
Номер Категория
0 |
Без категории (отображается только е категории Все функции) |
1финансовые
2Дата и время
3Мат. и тригонометрия
4Статистические
5Ссылки и массивы
6Работа с базой данных
7Текстовые
8Логические
9Информационные
10Команды (обычно эта категория скрыта)
11Настройка (обычно эта категория скрыта)
12Управление макросами (обычно эта категория скрыта)
13DDE/External (обычно эта категория является скрытой)
14Определенные пользователем (по умолчанию)
15Инженерные (эта категория может использоваться только тогда, когда установлена надстройка Пакет анализа)
Как создать новую категорию функций?
Для этого воспользуйтесь макросом XLM. Однако данный метод ненадежный, и использовать его не рекомендуется.
У меня есть пользовательская функция, которая будет применяться в формуле рабочего листа. Как сделать так, чтобы при вводе неверного значения функция возвращала значение ошибки (#ЗНАЧ)?
Если функция называется MyFunction, то можно использовать следующий оператор для возврата кода ошибки в ячейку, содержащую функцию:
MyFunction = CVErr(xlErrValue)
В этом примере xlErrValue является предопределенной константой. Константы остальных кодов ошибок описываются в интерактивном справочном руководстве.
ЧастьVII,Другиетемы |
719 |
Как провести пересчет формул, применяющих пользовательскую функцию?
Для этого можно воспользоваться комбинацией клавиш <Ctrl+Alt+F9>.
Можно ли использовать встроенные функции Excel рабочего листа
вкоде VBA?
Вбольшинстве случаев — да. Функции Excel рабочего листа задаются с помощью метода WorksheetFunction объекта A p p l i c a t i o n . Например, доступ к функции POWER (СТЕПЕНЬ) вы получите, введя следующий оператор:
Ans = A p p l i c a t i o n . W o r k s h e e t F u n c t i o n . P o w e r ( 5 , 3)
В этом примере 5 возводится в третью степень, и возвращается результат (125).
Если VBA содержит эквивалент функции рабочего листа, то последнюю нельзя использовать на рабочем листе. Например, если VBA залает функцию подсчета квадратного корня (Sgr), то функцию SQRT рабочего листа в коде VEiA использовать нельзя.
Excel 95 не поддерживает метод WorksheetFunction. Значит ли это, что мое приложение для Excel 2002 не совместимо с Excel 95?
Нет. На самом деле метод W o r k s h e e t F u n c t i o n использовать не обязательно. Следующие два оператора выполняют одно и то же действие:
Ans = Application.WorksheetFunction.Power(5, 3) Ans = Application.Power(5, 3)
Можно ли в коде VBA использовать функции надстройки Пакет анализа?
Да, но для этого необходимо выполнить дополнительные действия. В Excel выберите Сер- в и с ^ Надстройки и установите флажок для надстройки Analisys Toolpak — VBA. После этого активизируйте проект VBA и выберите Tools^References (Сервис^Ссылки). Установите флажок для файла a t p v b a e n . x l s , чтобы создать необходимую ссылку. После этого в коде можно использовать любую из функций пакета анализа. Например, приведенный ниже оператор пепольчуст функцию CONVERT надстройки Пакет анализа, чтобы преобразовать 5000 метров в мили:
M s g B o x C O N V E R T ( 5 0 0 0 , " m " , " m i " )
Существует ли способ задать разрыв строки в тексте окна сообщения?
Для этого необходимо воспользоваться символом возврата каретки или перевода строки. Представленный далее оператор отображает окно сообщения, которое содержит текст, состоящий из двух строк. vbCr является встроенной константой, которая представляет символ возврата каретки.
MsgBox " H e l l o " & vbCr & Application . UserName
Объекты, свойства, методы и события
Я не понимаю концепцию объектов. Существует ли список объектов Excel, которые можно использовать?
Да. Интерактивное справочное руководство представляет всю необходимую информацию в удобном графическом формате.
720 |
Глава 30. Часто задаваемые вопросы о программировании в Excel |
Я потрясен количеством доступных свойств и методов. Как можно определить, какие методы или свойства доступны для определенного объекта?
Существует несколько способов получения этой информации. Можно воспользоваться окном Object Browser, которое отображается в редакторе VBE. Нажмите клавишу <F2> для получения доступа к окну Object Browser и выберите Excel из выпадающего списка Libraries;/ Workbooks (Все библиотеки)- Список Classes (Классы) (слева) содержит все доступные объекты Excel. При выборе объекта его свойства и методы отображаются справа в списке Members (Компоненты).
Кроме того, список свойств и методов можно отобразить при введении имени объекта. Например, введите следующий текст:
Range("A1") .
При вводе точки будет отображен список всех доступных свойств и методов объекта Range. Если этого не произошло, то необходимо выбрать Tools^Options, перейти на вкладку Editor и установить флажок опции Auto List Members.
Также достаточно большое количество информации по языку VBA содержит интерактивное справочное руководство. В нем вы найдете описание методов и свойств всех объектсш, которые могут вызвать интерес разработчика. Самым простым способом получения этой информации является ввод имени объекта в поле Immediate в нижней части окна VBE или наведение указателя на имя объекта с последующим нажатием клавиши <F1>. В результате будет отображен раздел справочного руководства, посвященного этому объекту.
В чем смысл использования коллекций? Является ли коллекция объектом? Что такое коллекция?
Коллекция — это объект, который содержит группу подобных объектов. Коллекция получает название в виде существительного во множественном числе. Например, коллекция W o r k s h e e t s — это объект, который содержит объекты Worksheet рабочих книг. Коллекцию можно воспринимать как массив: W o r k s h e e t s ( I ) указывает на первый объект Work- s h e e t в коллекции Workbooks. Вместо индекса, можно указать имя рабочего листа, например, W o r k s h e e t s (" Л и с т 1 " ) . Концепция коллекции упрощает одновременное управление подобными объектами. А для циклического перебора членов коллекции можно воспользоваться конструкцией F o r Each - Next .
Когда в коде VBA я ссылаюсь на рабочий лист, возникает сообщение об ошибке "subscript out of range". Но я не использую подсценариев. Что происходит?
Эта ошибка возникает при попытке получить доступ к несуществующему члену коллекции. Например, приведенный ниже оператор создает сообщение об ошибке, если активная рабочая книга не содержит рабочего листа, который называется MySheet:
Set X = ActiveWorkbook.Worksheets("MySheet")
Как лишить пользователя возможности прокручивать рабочий лист?
Для этого можно или скрыть неиспользуемые строки и столбцы, или воспользоваться оператором VBA для перенастройки полосы прокрутки на рабочем листе. Следующий оператор устанавливает область прокрутки на листе Лист1 таким образом, что пользователь не может активизировать ячейки за пределами диапазона В2 : D50:
W o r k s h e e t s ( " Л и с т 1 " ) . S c r o l l A r e a = |
"B2:D50" |
ЧастьVII.Другиетемы |
721 |
Для того чтобы восстановить первоначальную область прокрутки, воспользуйтесь оператором Worksheets (-"Лист1") . ScrollArea = ""
Помните, что значение свойства ScrollArea не сохраняется вместе с рабочей книгой. Таким образом, необходимо устанавливать это свойство при каждом следующем открытии рабочей книги. Данный оператор можно разместить в процедуре Workbook_Open.
Какая разница между использованием методов Select и Application.Goto?
Метод Select объекта Range выделяет диапазон только на активном рабочем листе. Метод Application . Goto можно использовать для выделения диапазона на любом листе рабочей книги. Метод Application . Goto может либо активизировать, либо деактивизировать другой лист. Кроме того, метод Goto позволяет прокручивать рабочий лист, чтобы расположить выделенный диапазон в левом верхнем углу экрана.
Какая разница между активизацией и выделением диапазона?
В отдельных случаях методы Activat e и Select приводят к одинаковому эффекту. Но зачастую эти методы возвращают разные результаты. Предположим, что выделен диапазон А1: СЗ. Приведенный ниже оператор актинизирует ячейку СЗ. Первоначальный диапазон остается выделенным, но ячейка СЗ становится активной, т.е. курсор находится в этой ячейке.
Range("СЗ").Activate
Предположим также, что диапазон А1 :СЗ выделен. Представленный далее оператор выделяет единственную ячейку, которая становится активной:
Range("СЗ").Select
Существует ли быстрый способ удаления всех значений из рабочего листа без удаления формул?
Да. Код выполняется по отношению к активному рабочему листу и удаляет значения всех ячеек, которые не содержат формул (форматирование ячеек тоже не очищается):
On Error Resume Next Cells.SpecialCells(xlCellTypeConstants, 23).ClearContents
Использование оператора On Erro r Resume Next позволяет отменить сообщение об ошибке, которое возникает, если ни одна ячейка не соответствует указанному критерию.
Я знаю, как писать операторы VBA для выделения диапазона, для которого известен адрес. Объясните, как создать оператор выделения, если известны только номер строки и номер столбца?
Для этого воспользуйтесь методом c e l l s . Следующий оператор выделяет ячейку в пятой строке и двенадцатом столбце {т.е. ячейку L5):
Cells{5, 12)-Select
Существует ли команда VBA для выхода из Excel? Когда я пытаюсь записать макрос с командой Файл<=>Выход, Excel закрывается до того, как предоставляется возможность просмотреть записанный код!
Для выхода из Excel необходимо воспользоваться оператором
Application.Quit
722 |
Глава 30. Часто задаваемые вопросы о программировании в Excel |
Как отключить обновление экрана в процессе работы макроса?
Представленный далее оператор отключает обновление экрана и ускоряет работу макроса, модифицирующего отображаемую информацию:
Application.ScreenUpdating = False
Какой способ создания имени диапазона с помощью VBA является самым простым?
Если включить запись макроса при создании имени диапазона, то будет получен следующий код:
Range<"D14:G20n).Select ActiveWorkbook.Names.Add Name:="inputArea", _
RefersToRlCl: ="=Лист1!R14C4:R2 0C7"
Однако намного проще использовать такой оператор:
Sheets("Лисг1").Range("D14:G20").Name = "inputArea"
Как определить, имеет ли имя конкретная ячейка или диапазон?
Для этого необходимо проверить значение свойства Name объекта Name, который содержится в объекте Range. Следующая функция принимает диапазон в качестве аргумента и возвращает имя диапазона, если оио существует. Если диапазон не имеет имени, то функция возвращает значение F a l s e .
Function RangeName(rng) As Variant On Error Resume Next RangeName = rng.Name.Name
If Err <> 0 Then RangeName = False End Function
Существует ли способ отключить кнопки Страница и Поля, которые отображаются в окне Предварительный просмотр?
Да. Для этого необходимо воспользоваться следующим оператором: ActiveSheet.PrintPreview EnableChanges:=False
Аргумент EnableChanges метода PrintPreview не документирован в интерактивном справочном руководстве, но он отображается в окне Object Browser.
Можно ли отображать сообщения в строке состояния в процессе выполнения макроса? Я использую сложный макрос и неплохо бы иметь представление о ходе его выполнения
Рекомендуем назначить строковые данные свойству StatusBar объекта Application. Приведем пример соответствующего оператора:
Application.StatusBar = "Обработка файла " & FileNum
После завершения процедуры необходимо восстановить строку состояния с помощью такого оператора:
Application-StatusBar = False
Часть VII. Другие темы |
723 |
Я записал макрос VBA, который копирует диапазон и вставляет его
в другое место на рабочем листе. Этот макрос использует метод Select. Существует ли более эффективный способ копирования и вставки?
Да. Хотя при записи макроса ячейки сначала выделяются, выделение выполнять вовсе не обязательно — на самом деле это только замедляет работу макроса. Запись простой операции копирования и вставки приводит к генерированию кода VBA, состоящего из четырех строк. Две из них вызывают метод S e l e c t . Например:
Range("А1").Select Selection.Copy Range{"Bl").Select ActiveSheet.Paste
Эти четыре строки кода можно заменить одним оператором, который приводится ниже. Range{"Al")-Copy R a n g e ( " B l " )
Обратите внимание, что последний оператор не 1ребует использования метода S e l e c t .
Я не нашел метода сортировки массива VBA. Значит ли это, что необходимо копировать значения на рабочий лист и использовать метод Range.Sort?
В языке VBA не существует встроенных средств сортировки массивов. Копирование массива на рабочий лист — это только один из методов, но можно создать собственную процедуру сортировки. В настоящее время существует довольно много алгоритмов сортировки, часть из которых достаточно просто реализуется с помощью VBA. В этой книге приводится код VBA нескольких методов сортировки.
Мой макрос работает с выделенными ячейками, но он неудачно завершается, если выделенной оказывается диаграмма.
Как удостовериться, что выделен диапазон ячеек?
Можно воспользоваться функцией VBA TypeName, которая применяется для проверки объекта S e l e c t i o n . Ниже приведен пример такого кода.
If TypeNarae(Selection) <> "Range" Then MsgBox "Выделите диапазон!"
Exit Sub End If
Еще одним вариантом является использование свойства R a n g e S e l e c t i o n , которое возвращает объект Range, представляющий выделенные ячейки рабочего листа. Это свойство возвращает выделенные ячейки на рабочем листе указанного окна, даже если помимо них выделен графический объект. Это свойство объекта Window, а не объекта Workbook. Следующий оператор отображает адрес выделенного диапазона:
MsgBox ActiveWindow . RangeSelection . Address
Макрос VBA должен подсчитать количество строк, выделенных пользователем. Метод Selection.Rows.Count не применяется, если выделены несмежные строки. Это ошибка?
На самом деле так и должно быть. Метол Count возвращает количество элементов в первой выделенной области (предположим, что выделение состоит из нескольких областей). Для
724 |
Глава 30. Часто задаваемые вопросы о программировании в Excel |
того чтобы получить точное количество строк, код VBA должен определить количество выделенных областей и подсчитать количество строк в каждой области. Сначала необходимо воспользоваться методом S e l e c t i o n . A r e a . C o u n t , чтобы получить количество областей. Ниже приведен пример, который сохраняет общее количество выделенных строк в переменной NumRows.
NumRows = 0
For Each areaCounter In Selection.Areas NumRows = NumRows + areaCounter.Rows.Count
Next areaCounter
Кстати, это относится и к подсчету количества выделенных строк и столбцов.
Я использую Excel для создания накладных. Существует ли способ генерации уникального номера накладной?
Одним из способов является использование системного реестра. Следующий код демонстрирует этот способ.
Counter = GetSetting("XYZ Corp", "InvoiceNum", "Count", 0) Counter = Counter + 1
SaveSetting "XYZ Corp", "InvoiceNum", "Count", Counter
При выполнении данного кода текущее значение извлекается из системного реестра, увеличивается на единицу и назначается переменной C o u n t e r . После этого обновленное значение сохраняется в системном реестре. Значение переменной C o u n t e r можно использовать в качестве уникального номера накладной.
Существует ли свойство рабочей книги Excel, которое позволяет ей всегда отображаться на экране и не перекрываться окнами других приложений?
К сожалению, не существует.
Существует ли способ блокировки сообщения Excel, отображаемого в процессе работы макроса? Например, мне необходимо избавиться от сообщения, выводимого на экран при удалении данных макросом рабочего листа.
Следующий оператор отключает большинство предупреждений Excel:
Application.DisplayAlerts = False
Существует ли оператор VBA для выделения последнего значения в строке или в столбце? Как правило, я могу воспользоваться
комбинацией клавиш <Стг1+8Ш+стрелка вниз> или <Ctrl+Shift+CTpenKa вверх> для выполнения этого действия, но как это сделать с помощью макроса?
Эквивалентом комбинации клавиш <Ог1+5ЫЛ+стрелка вниз> в VBA выступает оператор
Selection.End(xlDown).Select
Для других направлений используется три других константы: xlToLeft, xlToRight и xlup.
Часть W/. Другие темы |
725 |
Как определить последнюю непустую ячейку в выбранном столбце?
Представленный ниже оператор отображает адрес последней непустой ячейки в столбце А. MsgBox ActiveSheet.Range("A65536").End(xlUp).Address
Следующий оператор выполняется, если рабочий лист имеет больше 65536 строк. MsgBox ActiveSheet.Cells(Rows-Count, 11.End(xlUp).Address
Но этот оператор не будет работать, если ячейкаА65536 содержит значение!
Для того чтобы обойти такую маловероятную ситуацию, необходимо воспользоваться следующим кодом.
With ActiveSheet.Cells{Rows.Count, 1) If IsEmptyt.Value) Then
MsgBox .End(xlUp).Address Else
MsgBox .Address End If
End With
Ссылки VBA могут стать очень длинными, особенно если необходимо точно указать объект в рабочей книге и рабочем листе. Существует ли способ сократить длину ссылок?
Да. Для этого воспользуйтесь оператором S e t для создания объектной переменкой. Ниже приведен пример подобного кода.
Dim MyRange as Range
Set MyRange = ThisWorkbook.Worksheets{"Лист1"),Range("Al")
После выполнения оператора S e t можно ссылаться на объект Range по имени MyRange. Например, вы имеете возможность определить значение ячейки с помощью следующего оператора:
MyRange.Value = 10
Кроме упрощения ссылок на объекты, использование таких переменных ускоряет выполнение кода.
Существует ли способ объявления массива, если не известно, сколько элементов он будет содержать?
Да. Можно объявить динамический массив с помощью оператора Dim. При этом используются пустые скобки. Как только станет известно, сколько элементов будет содержаться в массиве, можно воспользоваться оператором ReDim, чтобы переопределить массив. Оператор ReDim P r e s e r v e позволяет переопределить массив без потери текущего содержимого.
Как можно создать макрос, который выделяет только отдельные листы в рабочей книге?
Для этого необходимо указать значение False в качестве аргумента метода Select. Например, следующая процедура выделяет все листы диаграмм в активной рабочей книге.
Sub SelectChartSheetsO Dim cht As Chart
726 |
Глава $0. Часто задаваемые вопросы о программировании в Excel |
If Charts.Count = 0 Then Exit Sub Charts(1).Select
For Each cht In Charts cht.Select False
Next cht End Sub
Можно ли предоставить пользователю возможность отменить результат выполнения макроса?
Да, но эта возможность не доступна по умолчанию. Для того чтобы включить ее, модуль кода VBA должен отслеживать изменения, проведенные макросом. Макрос должен быть готов отменить внесенные изменения при выборе пользователем команды ПравкаоОтмена.
Чтобы разрешить пользователю выполнять команду Правка^Отмена, воспользуйтесь методом OnUndo в качестве последнего оператора макроса. Этот метод позволяет указать текст, который отображается в опции меню Отмена, а также процедуру, вызываемую командой Правка=>Отмена. Например:
Application . OnUndo "Последний макрос", "MyUndoMacro"
У меня есть макрос Lotus 1-2-3, который останавливает свою работу для предоставления пользователю возможности введения данных . в ячейку. Как достичь такого же эффекта в макросе VBA?
Excel не может повторить этот тип поведения, однако вы вправе использовать функцию Excel inputBox, чтобы получить значение от пользователя и разместить его в определенной ячейке. Первый оператор, который показан ниже, отображает окно ввода. Когда пользователь вводит значение, это значение размещается в ячейке А1.
UserVal = Application.InputBox(prompt:="Введите значение", Туре:=1) If UserVal <> False Then Range("Al") = UserVal
VBA имеет функцию InputBox, но метод с таким же названием содержится в объекте Application. Они одинаковы?
Нет. Метод Excel I n p u t B o x является более гибким, так как позволяет проверить введенное пользователем значение. В предыдущем примере в качестве значения аргумента Туре метода InputBox используется единица (представляет числовое значение). Это значение позволяет удостовериться, что пользователь ввел в поле числовое значение.
При использовании функции RGB для указания цвета часто цвет оказывается неправильным. Что я делаю неверно?
Возможно, ничего. Рабочая книга Excel может использовать только 56 цветов (палитру из 56 цветов). Если указанный цвет RGB не входит в число цветов палитры. Excel использует самый близкий цвет на поддерживаемой палитре.
Я пытаюсь написать оператор VBA, который создает формулу. Чтобы это сделать, необходимо вставить символ кавычек (") в текст. Как это сделать?
Предположим, что вам с помощью кода VBA необходимо ввести следующую формулу в ячейку с адресом В1.
=ЕСЛИ(А1="Да";ИСТИНА;ЛОЖЬ)
ЧастьVII.Другиетемы |
727 |
Следующий оператор генерирует сообщение о синтаксической ошибке: R a n g e ( " B l " ) . F o r m u l a = "=IF(Al="YeE",TRUE,FALSE)"
Решением будет последовательное использование двух двойных кавычек. Представленный далее оператор приводит к необходимому результату:
Range("B1") .Formula = " = I F ( A l = " " Y e s " ' \ TRUE,FALSE)"
Еще одним способом является использование функции VBA Chr с аргументом 34. Функция возвращает символ кавычки. Следующий пример демонстрирует применение этого способа.
Range("Bl").Formula = „
"=IF(A1=" & Chr(34J & "Yes" & Chr(34J & " ,TRUE,FALSE)"
Я создал массив, но первый его элемент воспринимается как второй. Что я делают неправильно?
Если не указать обратного, VBA использует значение 0 в качестве индекса первого элемента массива. Если необходимо, чтобы индекс массива начинался с 1, вставьте представленный ниже оператор в начало модуля VBA:
Option Base I
Кроме того, можно указать верхнюю и нижнюю границы массива при его создании. Например:
Dim Months(I To 12) As String
Я хотел бы добиться от кода VBA максимального быстродействия. Что вы можете посоветовать?
Предложим несколько общих советов, Удостоверьтесь, что объявлены все используемые переменные. Воспользуйтесь оператором o p t i o n E x p l i c i t в начале модуля, чтобы сделать объявление переменных обязательным. Если ссылка на объект Excel применяется более одного раза, создайте для этого объекта переменную. Используйте конструкцию With-End With везде, где это возможна. Если макрос записывает информацию на рабочий лист, отключите обновленке экрана с помощью оператора Application . Screentlpdatin g = False . Если приложение вводит данные в ячейки, на которые ссылается более одной формулы, то следует включить ручной режим пересчета, чтобы избежать лишних вычислений.
Я работаю с функциями Windows API. Существует ли способ заставить Windows управлять окном Excel?
Да. Но для этого необходимо использовать Excel 2002. Чтобы получить такое поведение, используется свойство Hwnd объекта Application .
Пользовательские диалоговые окна
Мне необходимо получить от пользователя данные, но диалоговое окно UserForm требует сложного программирования. Существует ли альтернатива?
Да. Обратитесь к функциям VBA MsgBox и InputBox. Кроме того, можно воспользоваться метолом Excel InputBox.
728 |
Глава 30. Часто задаваемые вопросы о программировании в Excel |