Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Уокенбах Формулы в Excel

.pdf
Скачиваний:
212
Добавлен:
26.03.2016
Размер:
35.82 Mб
Скачать

Пропущено одно или несколько аргументов.

Аргумент неправильного типа (например, текстовый вместо числового).

Аргумент находится вне приемлемого числового диапазона (например,деление наноль).

Во многих случаях ошибку можно просто проигнорировать. Если не указать корректное значение аргумента, то функция просто выдаст значение ошибки. Устранением ошибки занимается пользователь вручную. Так исправляются ошибки в рабочем листе Excel.

В любых случаях появившиеся ошибки нужно исправлять. Оператор On Error в Excel позволяет выявить иустранить их.

Чтобы просто проигнорировать ошибку, воспользуйтесь следующим выражением: Or Error Resume Next

При использовании этого выражения ошибки определяются в результате проверки свой-

ства

Number объекта Err. Если свойство равно нулю, ошибка не появляется. Если

Err

.Number равно другому значению, то появляется сообщение обошибке.

Вследующем примере написана функция, возвращающая имя ячейки или диапазона. Если

уячейки или диапазона нетимени, то появляется ошибка, а формула, в которой используется функция, возвращает #ЗНАЧ!.

Function RENGENAME(rng)

RANGENAME = rng . Name. Name

End Function

В приведенном ниже листинге показана улучшенная версия этой же функции. Оператор On Error Resume Next сообщает VBA, что ошибку нужно проигнорировать. Оператор I f Err проверяет наличие ошибок. Если они есть, то функция возвращает пустую строку.

Function RANGENAME(rng)

On Error Resume Next

RANGENAME = rng . Name. Name

If Err.Number <> 0 Then RANGENAME =

End Function

Представленное ниже выражение предлагает VBA проверить существование ошибок, и, если ошибка найдена, продолжить выполнение с другого места; в данном случае, с оператора ErrHandler .

On Error GoTo ErrHandler

В следующей процедуре функции продемонстрировано практическое применение этого выражения. Функция DIVIDETWO принимает два аргумента {numl и пит2) и возвращает результат — numl, деленный на пит2.

Function DIVIDETWO(numl, num2) on Error GoTo ErrHandler DIVIDETWO = numl / num2 Exit Function

ErrHandler:

DIVIDETWO = "ERROR" End Function

В случае возникновения ошибки, выражение On Error GoTo предлагает VBA перейти к операциям, помеченным какErrHandler. В результате функция возвратит строку (ERROR), если при выполнении функции возникнет ошибка. Обратите внимание на оператор Exit Function. Без этого выражения выполнение кода продолжится, и всегда будет отображаться ошибка. Другими словами, функция всегда будет возвращать ERROR.

530

Часть VI. Разработка пользовательских функ

Важно понять, что функция DIVIDETWO нестандартная. Здесь при появлении ошибки (ERROR) в качестве результата возвращается строка, чего нет в Excel. В Excel обычно возвращается действительное значение ошибки.

В главе 25 приведены несколько примеров использования выражения On Error, в том числе пример, показывающий, чтосделать, чтобы функция возвратиладействительное значение ошибки.

Работа с диапазонами

Многие созданные пользовательские функции работают сданными, расположенными вячейке или вдиапазоне ячеек. Не забудьте, что диапазоном называется как одна ячейка, так игруппа ячеек. В этом разделе описываются некоторые основные способы улучшенного выполнения задач. Приведенная в этом разделе информация рассчитана напрактическое применение. Чтобы подробно ознакомиться с ихфункционированием, обратитесь ксправочной системе.

В главе 25 приведено много практических примеров использования диапазонов. Изучение этих примеров поможет разобраться синформациейданного раздела.

Конструкция For Each-Next

Иногда процедуру функции нужно зациклить наопределенном диапазоне ячеек. Например, можно написать функцию, которая в качестве аргумента принимала бы диапа-

зон. В описанном случае код проверяет каждую

ячейку диапазона и выполняет опреде-

ленное действие. Конструкция For Each-Next

очень удобна для операций такого ро-

да. Вней используется следующий синтаксис:

 

For Each элемент In группа

 

[операторы]

 

[Exit For]

 

[ опера торы]

 

Next [элемент]

 

Нижеприведенная процедура Function принимает аргумент диапазона и возвращает сумму квадратов величин этого диапазона.

Function SUMOFSQUARES(rng asRange) Dim total asDouble

Dim cell asRange total = 0

For Each cell In rng total = total + cell Л 2

Next cell

SUMOFSQUARES = t o t a l End Function

А вотформула Excel, вкоторой используется функция SumOf Squares: =SumOfSquares(Al:C100)

В описанном случае аргументом функции является диапазон, состоящий из 100ячеек.

Глава24. Принципы программирования на VBA

531

В предыдущем

примере cell и тд— имена переменных. В именах нет ничего

необычного; их

можно изменить на любое другое допустимое название.

Ссылка надиапазон

В коде VB А к диапазону можно обратиться несколькими способами:

с помощью свойства Range

с помощью свойства Cell s

с помощью свойства Offset

Свойство Range

Свойство Range можно использовать для прямого обращения к диапазону, используя адрес или имя ячейки. В приведенном ниже примере значение ячейки А1 присваивается переменной,которая называется I n i t . Таким образом, организуется доступ к свойству Value диапазона.

Init = Range("Al").Value

Кроме Value VBA предлагает и другие свойства диапазона. Например, следующее выражение подсчитывает количество ячеек в диапазоне и присваивает это значение переменной Cnt.

Cnt = Range("Al:C300").Count

Свойство Range также удобно использовать для обращения к одной ячейке многоячеечного диапазона. Например, можно создать функцию, которая принимает в качестве аргумента одну ячейку. Если пользователь задает в качестве аргумента несколько ячеек, то с помощью свойства Range можно получить значение левой верхней ячейки диапазона. В следующем примере используется свойство Range (с аргументом А1) для получения значения левой верхней ячейки диапазона, представленного аргументом c e l l .

Function Square(cell as Range) Dim CellValue as Double

CellValue = cell.Range("Al").Value Square = CellValue Л 2

End Function

Предположим, что пользователь ввел следующую формулу: =Square(C5:C12)

Функция Square обращается к левой верхней ячейке диапазона С5 : С12 (т.е. С5) и возвращает квадрат его значения.

Так работают многие функции Excel. Например, если в качестве первого аргумента функции ЛЕВСИМВ задать многоячеечный диапазон, то Excel примет левую верхнюю ячейку диапазона. Однако Excel — противоречивая программа. Если многоячеечный диапазон указать в качестве аргумента функции SQRT, TO Excel возвратит ошибку.

Свойство Cells

Другим способом обращения к диапазону является свойство Cells . Оно принимает два аргумента (номер строки и столбца) и возвращает одну ячейку. В следующем выражении значение ячейки А1 присваивается переменной F i r s t C e l l :

F i r s t C e l l = Cells(1,1).Value

532

Часть VI. Разработка пользовательских функ

А следующее выражение возвращает левую верхнюю ячейку диапазона С5 :С12: UpperLeft = R a n g e ( " C 5 : C 1 2 H ) . C e l l s ( 1 , 1 )

Если свойство Cells используется безаргумента, то оно возвращает диапазон, содержащий всеячейки рабочего листа. В приведенном ниже примере переменная T o t a l C e l l s содержит общее количество ячеек рабочего листа:

TotalCells = Cells.Count

В следующем выражении используется функция Excel для определения количества непустых ячеек листа:

NonEmpty = WorksheetFunction.COUNTS(Cells)

Свойство Offset

Свойство Offset (как и свойства Range и Cells) также возвращает объект Range. Свойство Offset применяется к диапазону. Оно принимает два аргумента, соответствующие относительному расположению левой верхней ячейки определенного объекта Range. Аргументы могут быть положительными, отрицательными или равными нулю. В следующем примере возвращается значение ячейки, которая на одну ниже ячейки А1 (т.е. А2), и присваивается переменной NextCell:

NextCell = Range("Al").Offset(1, 0).Value

В следующей процедуре функции принимается аргумент одной ячейки и используется цикл For-Next для возращения суммы 10 ячеек, находящихся под выбранной ячейкой:

Function SumBelow(cell as Range) Dim Total As Double

Dim i as Integer Total = 0

For i = 1 To 10

Total = Total + cell.Offset(i, 0) Next i

SubBelow = Total End Function

Часто используемые свойства диапазона

В предыдущих разделах приводились примеры использования свойства Value диапазона. VBA предоставляет возможность работать со многими дополнительными свойствами диапазона. Некоторые наиболее полезные свойства кратко описаны в следующих разделах. Более полная информация по тому или иному свойству находится в справочной системе.

Свойство Formula

Свойство Formula возвращает формулу (как строку), которая находится в ячейке. При обращении к свойству Formula диапазона, содержащего несколько ячеек, возникает ошибка. Если в ячейке нет формулы, то свойство возвратит строку — значение ячейки в таком виде, в каком оно выглядит в строке формул. Следующая функция отображает формулу левой верхней ячейки диапазона:

Function CELLFORMULA(cell)

CELLFORMULA =cell.Range("Al").Formula End Function

Чтобы определить, есть ли в ячейке формула, используйте свойство HasFormula.

Глава 24. Принципы программирования на VBA

533

Свойство Address

Свойство Address возвращает адрес диапазона в виде строки. По умолчанию это свойство возвращает адрес в виде абсолютной ссылки (например, $А$1:$С$12). Следующая функция, используемая не так уж и часто, возвращает адрес диапазона.

Function RANGEADDRESS(rng) RANGEADDRESS = rng.Address

End Function

А следующая формула возвращает строку $А$1: $С$3:

=RANGEADDRESS(А1:СЗ)

Свойство Count

Свойство Count возвращает количество ячеек в диапазоне. Оно используется в следующем примере:

Function CELLCOUNT(rng) CELLCOUNT = rng.Count

End Function

Эта формула возвращает 9:

=CELLCOUNT(A1:C3)

Свойство Parent

Свойство Parent возвращает объект, соответствующий контейнеру текущего объекта. Для объекта Range свойство Parent возвращает объект Worksheet (рабочий лист, содержащийдиапазон).

В приведенной ниже функции используется функция Parent; она возвращает имя рабочего листа диапазона, используемого в качестве аргумента:

Function SHEETNAME(rng) SHEETNAME = rng.Parent.Name

End Function

Следующая формула возвращает строку Sheet 1: =SHEETNAME(Sheetl!A16)

Свойство Name

Свойство Name возвращает объект Name ячейки диапазона. Чтобы получить реальное имя ячейки или диапазона, нужно обратиться к свойству Name объекта Name. Если у ячейки или диапазона нет имени, то свойство Name возвратит ошибку.

В следующей процедуре функции определяется имя ячейки или диапазона, переданных в качестве аргумента. Если у диапазона или ячейки нет имени, функция возвращает пустую строку. Обратите внимание, что в ней используется выражение On Error Resume Next. Таким образом, учитывается ситуация, когда у диапазона нет имени.

Function RANGENAME (rng)

On Error Resume Next RANGENAME = rng.Name.Name

If Err.Number <> 0 Then RANGENAME = "" End Function

534

Часть VI. Разработка пользовательских функ

Свойство Numberformat

Свойство Numberformat возвращает числовой формат ячейки (в виде строки), присвоенный самой ячейке или диапазону. В приведенной ниже функции показан формат номера левой верхней ячейки диапазона:

Function NUMBERFORMAT(cell)

NUMBERFORMAT =cell.Range("Al").NumberFormat End Function

Свойство Font

Свойство Font возвращает объект Font диапазона или ячейки. Чтобы осуществить какоелибо действие с помощью объекта Font, нужно обратиться к его свойствам. Например, у объекта Font есть такие свойства, как Bold, I t a l i c , Name, Color и так далее. Следующая функциявозвращает значение TRUE,если клевой верхней ячейке применено полужирное начертание:

Function ISBOLD(cell)

ISBOLD =cell.Range("Al").Font.Bold End Function

Свойства Columns иRows

Свойства Columns и Rows используются для управления строками и столбцами диапазона. Например, следующая функция с помощью обращения к свойству Count возвращает количество столбцов в диапазоне:

Function COLUMNCOUNT(rng) COLUMNCOUNT = rng.Column.Count

End Function

Свойства Entirerow и Entirecolumn

Свойства Entirerow и Entirecolumn позволяют работать со всей строкой или столбцом, в которой(ом) расположена текущая ячейка. Следующая функция принимает в качестве аргумента одну ячейку и использует свойство EntireColumn, чтобы получить диапазон, содержащий целый столбец с заданной ячейкой. Далее используется функция Excel СЧЁТЗ, чтобы определить количество непустых ячеек в столбце.

Function NONEMPTY(cell)

NONEMPTY = WorksheetFunction.CountA(cell.EntireColumn) End Function

Свойство Hidden

Свойство Hidden используется для управления строками и столбцами. Оно возвращает значение TRUE, если строка или столбец скрыт. Если применить это свойство к диапазону, в который не входит целая строка или столбец, возникает ошибка. Приведенная ниже функция принимает аргумент одной ячейки и возвращает TRUE, если либо строка, либо столбец с указанной ячейкой скрыт:

Function CELLISHIDDEN(cell)

If cell.EntireRow.Hidden Orcell.EntireColumn.Hidden Then

CELLISHIDDEN = True Else

CELLISHIDDEN = False End If

End Function

Глава24. Принципы программирования на VBA

535

Эту функцию можно записать без использования конструкции If-Then-Else. В следующей функции выражение справа от знака равенства возвращает либо TRUE, либо FALSE — и это значение присваивается переменной, возвращаемой функцией.

Function CELLISHIDDEN(cell)

CELLISHIDDEN = cell.EntireRow.Hidden Or cell.EntireColumn.Hidden

End Function

Ключевое словоSet

Важным моментом VBA является возможность создавать новый объект Range и присваивать его переменной, а конкретнее, создавать переменную объекта. Эта задача выполняется с помощью ключевого слова Set. Следующее выражение создает переменную объекта MyRange:

Set MyRange =Range("Al:A10")

После выполненияэтого выражения переменную MyRange можно использовать в коде для обращения кдиапазону. Примеры следующих подразделов помогут разобраться в этой возможности.

Создание объекта Range отличается отсоздания именованного диапазона. Другими словами, имя объекта Range нельзя использовать в формулах.

Функция Intersect

Функция I n t e r s e c t

возвращает диапазон, образованный пересечением двух диапазо-

нов. Например, возьмем два диапазона, представленных

на рис.24.2. У этих диапазонов,

D3 : D10 и В5 : F5, есть одна общая ячейка (D5). Другими словами, D5 является пересечением

D3 :D10 HB5:F5.

 

 

 

i

D

E i

F jfti^ii^il

•i

 

 

~5~

1

 

10

 

"6

 

 

 

7

 

 

 

8

 

 

 

9

 

 

 

Ж

 

I

2

 

Рис.24.2. Использование функции Intersect для управления пересечением двух диапазонов

Следующая процедура функции принимает два диапазона и подсчитывает, сколько у них общих ячеек.

Function CELLSINCOMMON(rngl, rng2) Dim CommonCells As Range

On Error Resume Next

Set CommonCells = Intersect(rngl,rng2) If Err.Number = 0 Then

536

ЧастьVI.Разработка пользовательских функций

CELLINCOMMON = CommonCelIs.Count Else

CELLINCOMMON = 0 End If

End Function

Функция CELLINCOMMON использует функцию I n t e r s e c t для создания объекта диапазона CoiranonCells. Обратите внимание на использование выражения On Error Resume Next. Оно необходимо, поскольку, если у диапазонов нет общих ячеек, функция I n t e r s e c t возвращает ошибку. Если встречается ошибка и используется выражение On Error Resume Next, то ошибка игнорируется. Последнее выражение проверяет свойство Number объекта Err. Если оно равно 0, то ошибка не возникает, и функция возвращает значение свойства Count объекта CommonCells. Если возникает ошибка, то Err .Number принимает значение, отличное от нуля, и функция возвращает 0.

Функция Union

Функция Union объединяет два и более диапазона в один. В следующем выражении функция Union используется для создания объекта диапазона, содержащего первый и третий столбцы рабочего листа:

Set TwoCols = Union(Range("A:A"), Range("C:C")) Функция Union может содержать любое количество аргументов.

Свойство UsedRange

Свойство UsedRange возвращает объект Range, характеризующий используемый диапазон рабочего листа. При нажатии клавиш <Ctrl+End> активизируется правая нижняя ячейка используемого диапазона. Свойство UsedRange может быть полезно при повышении эффективности выполнения функций.

Рассмотрим следующую процедуру функции. Эта функция принимает аргумент диапазона и возвращает количество ячеек с формулами в диапазоне.

Function FORMULACOUNT(rng As Range) Dim cnt As Long

Dim cell As Range cnt = 0

For Each cell In rng

If cell.HasFormula Then cnt = cnt + 1 Next cell

FORMULACOUNT = cnt End Function

В большинстве случаев эта функция прекрасно работает. Но что если пользователь введет следующую формулу:

=FORMULACOUNT("А:С")

С аргументом, содержащим один или более столбцов, эта функция не работает, поскольку она в цикле просматривает каждую ячейку диапазона, даже те ячейки, которые лежат вне области использованного листа. Ниже приведена функция, исправляющая рассмотренный недостаток предыдущей функции:

Function FORMULACOUNT(rng As Range) Dim cnt As Long

Dim cell As Range

Глава 24. Принципы программирования на VBA

S37

cnt = О

set WorkRange = Intersect(rng, rng.Parent.UsedRange) For Each cell In WorkRange

If cell.HasFormula Then cnt = cnt + 1 Next cell

FORMULACOUNT = cnt End Function

Эта функция создает объект Range с именем WorkRange, в котором сохраняется пересечение диапазона, принимаемого в качестве аргумента, и используемого диапазона рабочего листа. Другими словами, WorkRange состоит из подмножества аргументов диапазона, в которое входят ячейки используемого диапазона рабочего листа.

Резюме

Вэтой главе вы познакомились с элементами языка VBA, а именно с переменными, типами данных, константами и массивами. Здесь также рассматривались различные методы регулирования выполнения процедур функций. Было представлено несколько примеров функций, которые продемонстрировали управление массивами и использование встроенных функций VBА.

Вследующей, последней главе приведены примеры пользовательских функций.

538

Часть VI. Разработка пользовательских функ

Глава 25

Примеры пользовательских функций VBA

Вэтой главе...

Простые функции

Определение типа данных в ячейке

Многофункциональная функция

Генерирование случайных чисел

Вычисление комиссионных от продаж

Функцииуправления текстом

Функции подсчета и суммирования

Функцииуправления датами

Возвращение последней непустой ячейки столбца или строки

Функциидля работы в нескольких листах

Дополнительные пользовательские функции

Резюме

Вэтой главе приведены различные примеры полезных (или потенциально полезных) пользовательских функций VBA. Большинство функций можно использовать в таком виде, в каком они приведены. Но некоторые функции нужно немного изменить, чтобы они отвечали конечным задачам. Для повышения производительности и эффективности выполнения таких процедур функций в этой главе описываются все используемые в них переменные.

Простые функции

Относительно простые функции, представленные в этой главе, могут оказаться очень полезными. Многие из них основаны на том факте, что VBA получает доступ к большому количеству полезной информации, которая обычно не используется в формулах. Например, код VBA может обратиться к свойству ячейки HasFormula, чтобы определить, содержится ли в ячейке формула. Странно, но в Excel нет такой встроеннойфункции.

Есть ли вячейке формула?

Приведенная ниже функция CELLHASFORMULA принимает аргумент в виде одной ячейки и возвращает значение TRUE,если в ячейке содержится формула.

Function CELLHASFORMULA(cell) As Boolean

1

Возвращает TRUE если в ячейке введена формула

 

CELLHASFORMULA = cell.Range("Al").HasFormula

End

Function

Глава 25. Примеры пользовательских функций VBA

539