Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
курсовая / Источники / excel_2010_professionalnoe_programmirovanie_na_vba_RuLit_Me_412629.pdf
Скачиваний:
4
Добавлен:
27.09.2025
Размер:
22.97 Mб
Скачать

Глава 11. Приемы и методы программирования на VBA

339

К о м п а к т-д и ск

Рабочая книга, содержащая три процедуры C olorN egative, находится на при­ лагаемом к книге компакт-диске и называется e f f ic ie n t lo o p in g .xlsm.

Удаление всех пустых строк

Следующая процедура удаляет все пустые строки в активном рабочем листе. Она достаточно эффективна, так как не проверяет все без исключения строки, а просматрива­ ет только строки в так называемом “используемом диапазоне”, определяемом с помо­ щью свойства UsedRange объекта Worksheet.

Sub DeleteEmptyRows ()

Dim LastRow As Long

Dim r As Long

Dim C ounter As Long

A p p lic a tio n .S c re e n U p d a tin g = F alse

LastRow = A ctive S h ee t.U se dR a ng e . Rows. Count + _

A ctiveS heet.U sedR ange.R ow s( 1 ) .Row - 1

For r

= LastRow To 1 Step

-1

I f

A p p lic a tio n .W o rk s h e e tF u n c tio n .C o u n tA (R o w s (r)) = 0 Then

 

R o w s (r). D e le te

1

 

C ounter = C ounter +

End I f

 

Next r

 

A p p lic a tio n . S creenU pdating

= True

MsgBox C ounter & " пустые

строки удалены ."

End Sub

 

Первый шаг — определить последнюю используемую строку и присвоить этот номер строки переменной LastRow. Это не так просто, как можно ожидать, поскольку теку­ щий диапазон необязательно начинается со строки 1. Следовательно, значение LastRow вычисляется таким образом: к найденному количеству строк используемого диапазона прибавляется номер первой строки текущего диапазона и вычитается 1.

В процедуре применена функция Excel СЧЁТЗ (COUNTA), определяющая, является ли строка пустой. Если данная функция для конкретной строки возвращает 0, то эта строка пустая. Обратите внимание, что процедура просматривает строки снизу вверх и использует отрицательное значение шага в цикле For-Next. Это необходимо, по­ скольку при удалении все последующие строки перемещаются “вверх” в рабочем листе. Если бы в цикле просмотр выполнялся сверху вниз, то значение счетчика цикла после удалениястроки оказалось бы неправильным.

В макросе используется еще одна переменная, Counter, с помощью которой под­

считываетсяколичество удаленных строк. Эта величина отображается в окне сообщения позавершении процедуры.

К ом пакт-диск

Рабочая книга, содержащая описанный выше пример, находится на прила­ гаемом к книге компакт-диске и называется d e le te empty ro w s . xlsm .

Дублирование строк

Пример, рассматриваемый в этом разделе, демонстрирует использование возможно­ стей VBA для создания дубликатов строк. На рис. 11.9 показан пример рабочего листа,

342

Часть III. Visual Basic for Applications

Ниже описана функция CellType, которая принимает аргумент-диапазон и возвраща­ ет строку (Пусто, Текст, Булево выражение, Ошибка, Дата, Время или Значение),

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

F u n c tio n C ellType(R ng)

' Возвращает тип верхней левой

'ячейки в диапазоне

Dim

T h e C e ll

As

Range

Set

T he C ell

=

Rng. Range( " A l")

S e le c t

Case

True

 

 

Case

IsE m p ty(T h e C e ll)

 

C e llT yp e

=

"П усто"

 

Case

A p p lic a tio n . Is T e x t(T h e C e ll)

 

C e llT yp e

= "Т е кс т"

 

Case

A p p lic a tio n .Is L o g ic a l(T h e C e ll)

 

C e llT yp e

=

"Булево выражение"

 

Case

A p p lic a tio n . Is E rr(T h e C e ll)

 

C e llT yp e

=

" E rro r"

 

Case

Is D a te (T h e C e ll)

 

C e llT yp e

=

"Д ата"

 

Case

I n S t r ( l,

T h e C e ll. T e x t, " : " ) <> 0

 

C e llT yp e

=

"Время"

 

Case

IsN u m e ric (T h e C e ll)

 

C e llT yp e

=

"Значение"

End

S e le c t

 

 

 

End F u n c tio n

Обратите внимание на использование оператора Set TheCell. Функция CellType получает аргумент-диапазон произвольного размера, но этот оператор указывает, что функция оперирует только левой верхней ячейкой диапазона (представленной перемен­ ной TheCell).

Компакт-диск

Рабочая книга, содержащая описанную выше функцию, находится на прила­ гаемом компакт-диске в файле c e llty p e fu n c t io n . xlsm .

Чтение и запись диапазонов

Многие задачи, выполняемые в электронных таблицах, связаны с переносом значений из массива в диапазон ячеек или из диапазона в массив. Следует отметить, что Excel по­ лучает данные из диапазонов значительно быстрее, чем записывает их. Процедура WriteReadRange демонстрирует относительную скорость записи и чтения диапазона.

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

Sub W riteReadR ange()

 

 

Dim

M yA rra y()

 

 

 

Dim

T im e l As Double

 

 

Dim

NumElements

As

Long,

i As Long

Dim

W riteTim e As

S trin g ,

ReadTime As S trin g

Dim

Msg As

S trin g

 

 

NumElements

= 60000

NumElements)

ReDim M yA rra y(1

To

Глава 11. Приемы и методы программирования на VBA

343

1 Заполнение

массива

 

For i

= 1

То

NumElements

 

M yA rra y(i )

= i

 

Next

i

 

 

 

'Запись массива в диапазон

Timel = Tim er

For i

=

1

To

NumElements

C e lls

( i,

1) = M y A rra y (i)

Next

i

 

=

F orm at(T im e r - T im e l, "0 0 :0 0 ")

WriteTime

'Считывание диапазона в массив

Timel

=

Tim er

 

 

 

 

For i

=

1

To

NumElements

1)

 

M yA rra y(i)

= C e lls

( i,

 

Next

i

 

= F orm at(T im e r

- T im e l,

"0 0 :0 0 ")

ReadTime

 

1 Отображение

р езул ь тато в

 

 

Msg =

"Запись:

" & W riteTim e

 

Msg = Msg

& vb C rL f

" & ReadTime

 

Msg = Msg

&

"Ч тение:

& " элементов"

MsgBox Msg,

vbOKOnly,

NumElements

End Sub

 

 

 

 

 

 

 

 

В моей системе для записи массива из 60 тысяч элементов в диапазон потребовалось 58 секунд, и только 1 секунда ушла на то, чтобы занести этот диапазон обратно в массив.

Болееэффективный способ записи в диапазон

В примере из предыдущего раздела для перемещения содержимого массива в диапа­ зон используется цикл F or-N ext. В данном разделе показан более эффективный способ выполнения этой операции.

Начнем со следующего примера, в котором продемонстрирован наиболее очевидный (но не самый эффективный) способ заполнения диапазона. В этом примере для вставки значений в диапазон используется цикл F or-N ext.

Sub LoopFillRange ()

'Заполнение диапазона в цикле по ячейкам

Dim CellsDown

As

Long, C e lls A c ro s s As In te g e r

Dim CurrRow As

Long, C urrC o l As In te g e r

Dim S tartTim e

As

Double

Dim CurrVal As

Long

'Получение размеров

 

CellsDown

=

In p u tB o x ( "Сколько ячеек в

вы соту?")

 

If CellsDown

=

0

Then E x it Sub

 

.

CellsAcross

=

In p u tB o x ( "Сколько я ч еек

в ширину?")

i

If C ellsA cross

=

0 Then

E x it Sub

 

 

1 Запись момента

начала

 

 

 

StartTime

=

Tim er

 

 

 

:

1 Просмотр

ячеек

и

в став ка

значений

 

CurrVal = 1

s A p plica tion . S creenU pdating = F alse For CurrRow = 1 To CellsDown

344

 

Часть III. Visual Basic for Applications

For C u rrC o l =

1

To C e lls A c ro s s

A c t iv e C e ll. O ffse t(C u rrR o w - 1, _

C u rrC o l

-

1 ) .V alue = C u rrV a l

C u rrV a l =

C u rrV a l + 1

N ext C urrC o l

 

 

N ext CurrRow

 

 

'Отображение времени выполнения операции

A p p lic a tio n .S c re e n U p d a tin g = True

MsgBox F orm at(T im e r - S ta rtT im e , "0 0 .0 0 ") & " секунд" End Sub

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

Sub A rra y F illR a n g e ()

'Заполнение диапазона путем перенесения массива

Dim

C ellsDown

As

Long,

C e lls A c ro s s

As

In te g e r

Dim

i As

Long,

 

j

As In te g e r

 

 

 

Dim

S ta rtT im e

As

Double

 

 

 

 

Dim

Tem pArray()

As Long

 

 

 

 

Dim

TheRange

As

 

Range

 

 

 

 

Dim

C u rrV a l

As

 

Long

 

 

 

 

1 Получение

размеров

 

ячеек

в

высоту?")

CellsDown

=

In p u tB o x ( "Сколько

I f

CellsDown

=

0

Then E x it Sub

 

 

C e lls A c ro s s

=

In p u tB o x ( "Сколько ячеек

в ширину?")

I f

C e lls A c ro s s

 

=

0 Then

E x it

Sub

 

 

'Запись момента начала

S ta rtT im e = Tim er

'Изменение размера временного массива

ReDim Tem pA rray(1 То CellsD ow n, 1 То C e lls A c ro s s )

'Определение диапазона на рабочем листе

Set TheRange = A c tiv e C e ll.R a n g e (C e lls (1, 1 ), _

C e lls (C e lls D o w n , C e lls A c ro s s ))

'Заполнение временного массива

C u rrV a l = 0

A p p lic a tio n . S creenU pdating = F alse

For i

=

1

To

CellsDown

 

For

j

=

1

To C e lls A c ro s s

 

Tem pA rray(i , j ) =

C u rrV a l + 1

 

C u rrV a l

= C u rrV a l

+ 1

N ext

j

 

 

 

N ext i

 

 

 

 

 

'Перенесение временного массива в рабочую кн и гу

TheRange.Value = TempArray

'Отображение времени вычислений

A p p lic a tio n .S c re e n U p d a tin g = True

MsgBox F orm at(T im e r - S ta rtT im e , "0 0 .0 0 ") & " секунд" End Sub

Например, в моей системе на заполнение массива размером 1000x250 ячеек (250 ты­ сяч ячеек) методом цикла уходит 10,05 секунды. Метод перенесения массива потребовал только 0,18 секунды для получения тех же самых результатов — более чем в 50 раз бы­ стрее! Мораль? Если необходимо переносить большие объемы данных на лист Excel, по возможности избегайте циклов.