asesja Пользователь Сообщений: 320 |
Здравствуйте. Изменено: asesja — 02.08.2020 16:52:45 |
New Пользователь Сообщений: 4581 |
#2 02.08.2020 17:23:02
Изменено: New — 02.08.2020 17:28:53 |
||
asesja Пользователь Сообщений: 320 |
New
, Спасибо. То, что нужно. |
k61 Пользователь Сообщений: 2441 |
#4 02.08.2020 17:50:05
|
||
Юрий М Модератор Сообщений: 60575 Контакты см. в профиле |
Написал аналогичное — Карен опередил ) |
New Пользователь Сообщений: 4581 |
Вот любите вы всё усложнять) А новички потом под себя не могут переделать и не знают, что такое циклы ) Изменено: New — 02.08.2020 19:06:51 |
Юрий М Модератор Сообщений: 60575 Контакты см. в профиле |
#7 02.08.2020 19:07:46
Но тогда они не узнают ничего про Find ) |
||
asesja Пользователь Сообщений: 320 |
#8 03.08.2020 01:11:06 Оба варианта работают. Спасибо. |
Поиск номера последней заполненной строки с помощью кода VBA Excel для таблиц, расположенных как в верхнем левом углу, так и в любом месте рабочего листа.
Номер последней заполненной строки в таблице Excel обычно используется в коде VBA для определения следующей за ней первой пустой строки для добавления новой записи. А также для задания интервала для поиска и обработки информации с помощью цикла For… Next (указание границ обрабатываемого диапазона).
Переменную, которой присваивается номер последней строки, следует объявлять как Long или Variant, например: Dim PosStr As Long
. В современных версиях Excel количество строк на рабочем листе превышает максимальное значение типа данных Integer.
Таблица в верхнем левом углу
В первую очередь рассмотрим все доступные варианты поиска номера последней заполненной строки для таблиц, расположенных в верхнем левом углу рабочего листа. Такие таблицы обычно представляют собой простые базы данных в Excel, или, как их еще называют, наборы записей.
Пример таблицы с набором данных в Excel
Вариант 1
Основная формула для поиска последней строки в такой таблице, не требующая соблюдения каких-либо условий:
PosStr = Cells(1, 1).CurrentRegion.Rows.Count
Вариант 2
Ниже таблицы не должно быть никаких записей, в том числе ранее удаленных:
PosStr = ActiveSheet.UsedRange.Rows.Count
Вариант 3
В первом столбце таблицы не должно быть пропусков, а также в таблице должно быть не менее двух заполненных строк, включая строку заголовков:
PosStr = Cells(1, 1).End(xlDown).Row
Вариант 4
В первой колонке рабочего листа внутри таблицы не должно быть пропусков, а ниже таблицы в первой колонке не должно быть других заполненных ячеек:
PosStr = WorksheetFunction.CountA(Range("A:A"))
Вариант 5
Ниже таблицы не должно быть никаких записей:
PosStr = Cells.SpecialCells(xlLastCell).Row
Последняя строка любой таблицы
Последнюю заполненную строку для любой таблицы будем искать, отталкиваясь от ее верхней левой ячейки: Cells(a, b)
.
Вариант 1
Основная формула для поиска последней строки в любой таблице, не требующая соблюдения каких-либо условий:
PosStr = Cells(a, b).CurrentRegion.Cells(Cells(a, b).CurrentRegion.Cells.Count).Row
Вариант 2
Дополнительная формула с условием, что в первом столбце таблицы нет пустых ячеек:
PosStr = Cells(a, b).End(xlDown).Row
Если у вас на рабочем листе Excel есть записи вне таблиц, следите за тем, чтобы таблицы были окружены пустыми ячейками или пустыми ячейками и границами листа. Тогда не будет случайно внесенных заметок, примыкающих к таблицам, которые могут отрицательно повлиять на точность вычисления номера последней строки из кода VBA.
The max number of characters you can use in string in a vba function is 255.
I am trying to run this function
Var1= 1
Var2= 2
.
.
.
Var256 =256
RunMacros= "'Tims_pet_Robot """ & Var1 & """ , """ & Var2 & """ , """ ... """ & Var256 """ '"
Runat=TimeValue("15:00:00")
Application.OnTime EarliestTime:=Runat, Procedure:=RunMacros & RunMacros2 ', schedule:=True
It runs a procedure at a certain time and passes a bunch of variables to it. but the string is too long.
Update:
Regrettably I am sure it is not the watch window.
Also, it isn’t really the max size of a string that I’m dealing with. It’s the max size of
a string in a vba function.
For example this function works.
Sub test()
Dim RunAt As Date
Dim RunWhat As String
RunAt = Now + 0.00001
RunWhat = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 'that makes 254 'a''s
Application.OnTime EarliestTime:=RunAt, Procedure:="'" & RunWhat & " 12'"
End Sub
Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(m As Integer)
MsgBox ("it works!" & m)
End Sub
But if you change the 12 to 123 it breaks
Example
Sub test2()
Dim RunAt As Date
Dim RunWhat As String
RunAt = Now + 0.00001
RunWhat = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 'that makes 254 'a''s
Application.OnTime EarliestTime:=RunAt, Procedure:="'" & RunWhat & " 123'"
End Sub
Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(m As Integer)
MsgBox ("it works!" & m)
End Sub
This code does not work, I’m pretty sure it’s because a vba function cannot handle a string with more than 255 chars.
Even if you’re in Excel and call a function and give it a string longer that 255 chars it doesn’t work.
Try in cell A1 =vlookup(«really long string», A1:Z10, 1) and then put the really long string somewhere in that range. The vlookup will fail (not fail to find it, but you won’t actually be able to do it)
Also I am aware that there is a max length to a sub name, I’m just under it. Sorry that it look so ugly.
Update 2: so I just ended up printing the variable to a sheet and getting the function called by ontime to read them off the sheet.
Байт
Dim Value As Byte
Байт представляет собой неподписанный 8-битный тип данных. Он может представлять целые числа от 0 до 255, и попытка сохранить значение за пределами этого диапазона приведет к ошибке времени выполнения 6: Overflow
. Байт является единственным внутренним беззнаковым типом, доступным в VBA.
Функция кастинга для преобразования в байт — CByte()
. Для бросков из типов с плавающей точкой результат округляется до ближайшего целочисленного значения с округлением .5.
Байт-массивы и строки
Строки и байтовые массивы могут быть заменены друг на друга посредством простого присваивания (необязательные функции преобразования).
Например:
Sub ByteToStringAndBack()
Dim str As String
str = "Hello, World!"
Dim byt() As Byte
byt = str
Debug.Print byt(0) ' 72
Dim str2 As String
str2 = byt
Debug.Print str2 ' Hello, World!
End Sub
Чтобы иметь возможность кодировать символы Unicode , каждый символ в строке занимает два байта в массиве с первым младшим байтом. Например:
Sub UnicodeExample()
Dim str As String
str = ChrW(&H2123) & "." ' Versicle character and a dot
Dim byt() As Byte
byt = str
Debug.Print byt(0), byt(1), byt(2), byt(3) ' Prints: 35,33,46,0
End Sub
целое число
Dim Value As Integer
Целое число — это подписанный 16-битный тип данных. Он может хранить целые числа в диапазоне от -32,768 до 32,767, и попытка сохранить значение за пределами этого диапазона приведет к ошибке времени выполнения 6: переполнение.
Целые числа хранятся в памяти как малозначные значения с отрицаниями, представленными как дополнение к двум .
Обратите внимание, что в целом лучше использовать Long, а не Integer, если меньший тип не является членом типа или не требуется (либо по API-вызову, либо по другой причине), чтобы быть 2 байтами. В большинстве случаев VBA обрабатывает целые числа как 32-битные внутри, поэтому обычно нет преимуществ при использовании меньшего типа. Кроме того, каждый раз, когда используется тип Integer, он выполняет штраф за производительность, поскольку он бесшумно применяется как Long.
Функция кастинга для преобразования в Integer — это CInt()
. Для бросков из типов с плавающей точкой результат округляется до ближайшего целочисленного значения с округлением .5.
логический
Dim Value As Boolean
Логическое значение используется для хранения значений, которые могут быть представлены как True или False. Внутренне тип данных сохраняется как 16-битное значение с 0, представляющим False, и любое другое значение, представляющее True.
Следует отметить, что когда Boolean применяется к числовому типу, все биты имеют значение 1. Это приводит к внутреннему представлению -1 для подписанных типов и максимальному значению для неподписанного типа (байт).
Dim Example As Boolean
Example = True
Debug.Print CInt(Example) 'Prints -1
Debug.Print CBool(42) 'Prints True
Debug.Print CByte(True) 'Prints 255
Функция кастинга для преобразования в булевское значение — CBool()
. Несмотря на то, что он представлен внутренне как 16-битное число, отбрасывание в Boolean из значений вне этого диапазона безопасно от переполнения, хотя оно устанавливает все 16 бит в 1:
Dim Example As Boolean
Example = CBool(2 ^ 17)
Debug.Print CInt(Example) 'Prints -1
Debug.Print CByte(Example) 'Prints 255
Долго
Dim Value As Long
A Long — это подписанный 32-битный тип данных. Он может хранить целые числа в диапазоне от -2,147,483,648 до 2,147,483,647, и попытка сохранить значение за пределами этого диапазона приведет к ошибке времени выполнения 6: переполнение.
Длинны хранятся в памяти как малозначные значения с отрицаниями, представленными как дополнение к двум .
Обратите внимание, что поскольку Long соответствует ширине указателя в 32-разрядной операционной системе, Longs обычно используются для хранения и передачи указателей на и из функций API.
Функция кастинга для преобразования в Long — CLng()
. Для бросков из типов с плавающей точкой результат округляется до ближайшего целочисленного значения с округлением .5.
не замужем
Dim Value As Single
A Single — это подписанный 32-битный тип данных с плавающей точкой. Он хранится внутренне с использованием малогабаритной схемы памяти IEEE 754 . Таким образом, не существует фиксированного диапазона значений, которые могут быть представлены типом данных. Ограничение — это точность сохраненного значения. Единица может хранить значения целочисленных значений в диапазоне от -16,777,216 до 16,777,216 без потери точности. Точность чисел с плавающей запятой зависит от экспоненты.
Единица будет переполняться при назначении значения, превышающего примерно 2 128 . Он не будет переполняться отрицательными показателями, хотя допустимая точность будет сомнительной до того, как будет достигнут верхний предел.
Как и во всех числах с плавающей запятой, следует соблюдать осторожность при проведении сравнений равенства. Лучшей практикой является включение значения дельта, соответствующего требуемой точности.
Функция кастинга для преобразования в Single — это CSng()
.
двойной
Dim Value As Double
A Double — это подписанный 64-битный тип данных с плавающей точкой. Подобно Single , он хранится внутренне с использованием малогабаритной схемы памяти IEEE 754, и должны быть приняты те же меры предосторожности в отношении точности. Двойной объект может хранить целые значения в диапазоне от -9,007,199,254,740,992 до 9,007,199,254,740,992 без потери точности. Точность чисел с плавающей запятой зависит от экспоненты.
Двойной переполняется при назначении значения, превышающего примерно 2 1024 . Он не будет переполняться отрицательными показателями, хотя допустимая точность будет сомнительной до того, как будет достигнут верхний предел.
Функция кастинга для преобразования в Double — это CDbl()
.
валюта
Dim Value As Currency
Валюта — это подписанный 64-битный тип данных с плавающей точкой, аналогичный Double , но масштабированный на 10 000, чтобы обеспечить большую точность для 4 цифр справа от десятичной точки. Переменная Currency может хранить значения от -922,337,203,685,477.5808 до 922,337,203,685,477.5807, предоставляя ей наибольшую емкость любого встроенного типа в 32-битном приложении. Как следует из названия типа данных, считается, что наилучшим образом использовать этот тип данных при представлении денежных расчетов, поскольку масштабирование помогает избежать ошибок округления.
Функция кастинга для преобразования в валюту — CCur()
.
Дата
Dim Value As Date
Тип Даты представлен внутренне в качестве подписанного 64 бит с плавающей точкой типа данных со значением слева от десятичного представляющего количества дней с момента эпохи декабря 30 — го, 1899 (хотя см примечания ниже). Значение справа от десятичного знака представляет время как дробный день. Таким образом, целочисленная дата будет иметь временной компонент в 12:00:00 AM, а x.5 будет иметь временной компонент в 12:00:00 PM.
Допустимые значения Даты находятся между 1 января 100 года и 31 декабря 9999. й Поскольку двойной имеет больший диапазон, можно переполнять Дата путем присвоения значения вне этого диапазона.
Таким образом, его можно использовать взаимозаменяемо с расчетами Double for Date:
Dim MyDate As Double
MyDate = 0 'Epoch date.
Debug.Print Format$(MyDate, "yyyy-mm-dd") 'Prints 1899-12-30.
MyDate = MyDate + 365
Debug.Print Format$(MyDate, "yyyy-mm-dd") 'Prints 1900-12-30.
Функция кастинга для преобразования в дату — это CDate()
, которая принимает любое числовое представление даты / времени с числовым типом. Важно отметить, что строковые представления дат будут преобразованы на основе текущей настройки локали, используемой, поэтому следует избегать прямых бросков, если код предназначен для переносимости.
строка
Строка представляет последовательность символов и поставляется в двух вариантах:
Переменная длина
Dim Value As String
Строка переменной длины позволяет добавлять и усекать и хранится в памяти как COM BSTR . Это состоит из 4-байтового беззнакового целого числа, которое хранит длину строки в байтах, за которой следуют строковые данные в виде широких символов (2 байта на символ) и заканчивается двумя нулевыми байтами. Таким образом, максимальная длина строки, которую может обрабатывать VBA, составляет 2 147 483 647 символов.
Внутренний указатель на структуру (восстанавливаемый StrPtr()
) указывает на расположение памяти данных , а не на префикс длины. Это означает, что VBA String может быть передана непосредственно API-функциям, которым требуется указатель на массив символов.
Поскольку длина может изменяться, VBA перераспределяет память для String каждый раз, когда назначается переменная , которая может налагать штрафы за производительность для процедур, которые изменяют их повторно.
Фиксированная длина
Dim Value As String * 1024 'Declares a fixed length string of 1024 characters.
Строки фиксированной длины выделяются по 2 байта для каждого символа и сохраняются в памяти как простой массив байтов. После выделения длина строки неизменна. Они не имеют нулевой конец в памяти, поэтому строка, заполняющая память, выделенную ненулевыми символами, непригодна для передачи функциям API, ожидающих нулевую завершаемую строку.
Строки фиксированной длины несут на себе устаревшее ограничение на 16 бит, поэтому длина может составлять до 65 535 символов. Попытка присвоить значение дольше, чем доступное пространство памяти, не приведет к ошибке выполнения — вместо этого результирующее значение будет просто усечено:
Dim Foobar As String * 5
Foobar = "Foo" & "bar"
Debug.Print Foobar 'Prints "Fooba"
Функция каста для преобразования в строку любого типа — CStr()
.
Долго долго
Dim Value As LongLong
LongLong — это подписанный 64-битный тип данных и доступен только в 64-битных приложениях. Он не доступен в 32 — разрядных приложений , работающих на 64 — разрядных операционных системах. Он может хранить целые значения в диапазоне от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807, и попытка сохранить значение за пределами этого диапазона приведет к ошибке времени выполнения 6: переполнение.
LongLongs хранятся в памяти как малозначные значения с отрицаниями, представленными как дополнение к двум .
Тип данных LongLong был представлен как часть поддержки 64-битной операционной системы VBA. В 64-битных приложениях это значение может использоваться для хранения и передачи указателей на 64-битные API.
Функция литья для преобразования в LongLong — CLngLng()
. Для бросков из типов с плавающей точкой результат округляется до ближайшего целочисленного значения с округлением .5.
Вариант
Dim Value As Variant 'Explicit
Dim Value 'Implicit
A Variant — это тип данных COM, который используется для хранения и обмена значениями произвольных типов, а любой другой тип в VBA может быть назначен Variant. Переменные, объявленные без явного типа, указанные As [Type]
умолчанию для варианта.
Варианты хранятся в памяти как структура VARIANT, которая состоит из дескриптора байтового типа ( VARTYPE ), за которым следуют 6 зарезервированных байтов, а затем 8-байтовая область данных. Для числовых типов (включая Date и Boolean) базовое значение сохраняется в самом Variant. Для всех других типов область данных содержит указатель на базовое значение.
Основной тип Variant может быть определен с помощью функции VarType()
которая возвращает числовое значение, хранящееся в дескрипторе типа, или функцию TypeName()
которая возвращает строковое представление:
Dim Example As Variant
Example = 42
Debug.Print VarType(Example) 'Prints 2 (VT_I2)
Debug.Print TypeName(Example) 'Prints "Integer"
Example = "Some text"
Debug.Print VarType(Example) 'Prints 8 (VT_BSTR)
Debug.Print TypeName(Example) 'Prints "String"
Поскольку Variant может хранить значения любого типа, назначения из литералов без подсказок типа будут неявно отнесены к варианту соответствующего типа в соответствии с приведенной ниже таблицей. Литералы с типом намеков будут приведены к варианту намеченного типа.
Значение | Результирующий тип |
---|---|
Строковые значения | строка |
Номера без плавающей запятой в диапазоне Integer | целое число |
Номера без плавающей запятой в дальнем расстоянии | Долго |
Номера без плавающей запятой вне дальнего расстояния | двойной |
Все числа с плавающей запятой | двойной |
Примечание. Если не существует конкретной причины использовать вариант (т.е. итератор в цикле For Each или требование API), тип обычно следует избегать для обычных задач по следующим причинам:
- Они не безопасны для типов, что увеличивает вероятность ошибок во время выполнения. Например, вариант, содержащий значение Integer, беззвучно изменяет себя на Long, а не на переполнение.
- Они вносят накладные расходы на обработку, требуя, по крайней мере, одного дополнительного разыменования указателя.
- Требование к памяти для Variant всегда на 8 байт выше, чем требуется для хранения базового типа.
Функция кастинга для преобразования в вариант — это CVar()
.
LongPtr
Dim Value As LongPtr
LongPtr был представлен в VBA для поддержки 64-битных платформ. В 32-битной системе он рассматривается как Long и на 64-битных системах, он рассматривается как LongLong .
Основное использование заключается в предоставлении переносного способа хранения и передачи указателей на обе архитектуры (см. Изменение поведения кода во время компиляции .
Хотя он обрабатывается операционной системой как адрес памяти при использовании в вызовах API, следует отметить, что VBA рассматривает его как подписанный тип (и, следовательно, подвержен неподписанному сигналу переполнения). По этой причине любая арифметика указателя, выполняемая с использованием LongPtrs, не должна использовать >
или <
сравнения. Этот «quirk» также позволяет добавлять простые смещения, указывающие на действительные адреса в памяти, может привести к ошибкам переполнения, поэтому следует соблюдать осторожность при работе с указателями в VBA.
Функция кастинга для преобразования в LongPtr — CLngPtr()
. Для бросков из типов с плавающей точкой результат округляется до ближайшего целочисленного значения с округлением .5 (хотя, поскольку он обычно является адресом памяти, использование его в качестве целевой цели для расчета с плавающей точкой в лучшем случае опасно).
Десятичный
Dim Value As Variant
Value = CDec(1.234)
'Set Value to the smallest possible Decimal value
Value = CDec("0.0000000000000000000000000001")
Тип данных Decimal
доступен только в качестве CDec
Variant
, поэтому вы должны объявить любую переменную, которая должна содержать Decimal
как Variant
а затем назначить Decimal
значение с CDec
функции CDec
. Ключевое слово Decimal
является зарезервированным словом (которое предполагает, что VBA в конечном итоге будет добавлять поддержку первого класса для этого типа), поэтому Decimal
нельзя использовать как имя переменной или процедуры.
Для типа Decimal
требуется 14 байт памяти (в дополнение к байтам, которые требуются родительскому варианту), и может хранить номера до 28 знаков после запятой. Для чисел без знаков после запятой диапазон допустимых значений составляет -79,228,162,514,264,337,593,543,950,335 до +79,228,162,514,264,337,593,543,950,335 включительно. Для чисел с максимальным числом знаков в 28 знаков после запятой диапазон допустимых значений составляет -7.9228162514264337593543950335 по +7.9228162514264337593543950335 включительно.
Хитрости »
1 Май 2011 403766 просмотров
Очень часто при внесении данных на лист Excel возникает вопрос определения последней заполненной или первой пустой ячейки. Чтобы впоследствии с этой первой пустой ячейки начать заносить данные. В этой теме я опишу несколько способов определения последней заполненной ячейки.
В качестве переменной, которой мы будем присваивать номер последней заполненной строки, у нас во всех примерах будет lLastRow. Объявлять мы её будем как Long. Для экономии памяти можно было бы использовать и тип Integer, но т.к. строк на листе может быть больше 32767(это максимальное допустимое значение переменных типа Integer) нам понадобиться именно Long, во избежание ошибки. Подробнее про типы переменных можно прочитать в статье Что такое переменная и как правильно её объявить
Одинаковые переменные для всех примеров
Во всех примерах ниже мы будем запоминать номер последней строки или столбца в одни и те же переменные:
Dim lLastRow As Long 'а для lLastCol можно было бы применить и тип Integer, 'т.к. столбцов в Excel пока меньше 32767, но для однообразности назначим тоже Long Dim lLastCol As Long
Способ 1:
Определение
последней заполненной строки
через свойство End
lLastRow = Cells(Rows.Count,1).End(xlUp).Row 'или lLastRow = Cells(Rows.Count, "A").End(xlUp).Row
1 или «A» — это номер или имя столбца, последнюю заполненную ячейку в котором мы определяем. По сути обе приведенные строки дадут абсолютно одинаковый результат. Просто иногда удобнее указать номер столбца, а иногда его имя. Поэтому использовать можно любой из приведенных вариантов, в зависимости от ситуации.
Определение последнего столбца через свойство End
lLastCol = Cells(1, Columns.Count).End(xlToLeft).Column
1 — это номер строки, последнюю заполненную ячейку в которой мы определяем.
Данный метод определения последней строки/столбца самый распространенный. Используя его мы можем определить последнюю ячейку только в одном конкретном столбце(или строке). В большинстве случаев этого более чем достаточно.
Метод основан именно на принципе работы свойства End. На примере поиска последней строки опишу принцип так, как бы мы это делали руками через выделение ячеек на листе:
- выделили самую последнюю ячейку столбца А на листе(для Excel 2007 и выше это А1048576, а для Excel 2003 — А65536)
- и выполнили переход вверх комбинацией клавиш Ctrl+стрелка вверх. Данная комбинация заставляет Excel двигаться вверх(если точнее, то в направлении стрелки, нажатой вместе с Ctrl) до тех пор, пока не встретиться первая ячейка с формулой или значением. А в случае, если сочетание было вызвано из уже заполненных ячеек — то до первой пустой. И как только Excel доходит до этой ячейки — он её выделяет
- А через свойство .Row мы просто получаем номер строки этой выделенной ячейки
Нюансы:
- даже если в ячейке нет видимого значения, но есть формула — End посчитает ячейку не пустой. С одной стороны вполне справедливо. Но иногда нам надо определить именно «визуально» заполненные ячейки. Поиск ячеек при подобных условиях будет описан ниже(Способ 4: Определение последней ячейки через метод Find)
- если на листе заполнены все строки в просматриваемом столбце(или будут заполнены несколько последних ячеек столбца или даже только одна последняя) — то результат может быть неверный(ну или не совсем такой, какой ожидали)
- Данный способ игнорирует строки, скрытые фильтром, группировкой или командой Скрыть (Hide). Т.е. если последняя строка таблицы будет скрыта, то данный метод вернет номер последней видимой заполненной строки, а не последней реально заполненной.
Ну а если надо получить первую пустую ячейку на листе(а не первую заполненную) — придется вспомнить математику. Т.к. последнюю заполненную мы определили, то первая пустая — следующая за ней. Т.е. к результату необходимо прибавить 1. Это хоть и очевидно, но на всякий случай все же лучше об этом напомнить.
Способ 2:
Определение
последней заполненной строки
через SpecialCells
lLastRow = Cells.SpecialCells(xlLastCell).Row
Определение последнего столбца через SpecialCells
lLastCol = Cells.SpecialCells(xlLastCell).Column
Данный метод не требует указания номера столбца и возвращает последнюю ячейку(Row — строку, Column — столбец).
Если хотите получить номер первой пустой строки или столбца на листе — к результату необходимо прибавить 1.
Нюансы:
- Используя данный способ следует помнить, что не всегда можно получить реальную последнюю заполненную ячейку, т.е. именно ячейку со значением. Метод SpecialCells определяет самую «дальнюю» ячейку на листе, используя при этом механизм «запоминания» тех ячеек, в которых мы работали в данном листе. Т.е. если мы занесем в ячейку AZ90345 значение и сразу удалим его — lLastRow, полученная через SpecialCells будет равна значению именно этой ячейки, из которой вы только что удалили значения(т.е. 90345). Другими словами требует обязательного обновления данных, а этого можно добиться только сохранив файла, а временами даже только закрыв файл и открыв его снова. Так же, если какая-либо ячейка содержит форматирование(например, заливку), но не содержит никаких значений, то метод SpecialCells посчитает её используемой и будет учитывать как заполненную.
Этот недостаток можно попробовать обойти, вызвав перед определением последней ячейки вот такую строку кода:With ActiveSheet.UsedRange: End With
Это должно переопределить границы рабочего диапазона и тогда определение последней строки/столбца сработает как ожидается, даже если до этого в ячейке содержались данные, которые впоследствии были удалены.
Выглядеть в единой процедуре это будет так:Sub GetLastCell() Dim lLastRow As Long 'переопределяем рабочий диапазон листа With ActiveSheet.UsedRange: End With 'ищем последнюю заполненную ячейку на листе lLastRow = Cells.SpecialCells(xlLastCell).Row End Sub
- даже если в ячейке нет видимого значения, но есть формула — SpecialCells посчитает ячейку не пустой
- Данный метод определения последней ячейки не будет работать на защищенном листе(Рецензирование(Review) —Защитить лист(Protect Sheet)).
- Данный метод не будет работать при использовании внутри UDF. Точнее будет работать не так, как ожидается. Подробнее про некоторые «баги» работы встроенных методов внутри UDF(функций пользователя) я описывал в этой статье: Глюк работы в UDF методов SpecialCells и FindNext
Сам же я этот метод обычно использую для определения последней ячейки в только что созданном файле, в котором только добавляю строки кодом и в котором не может быть описанных выше нюансов.
Способ 3:
Определение последней строки через UsedRange
lLastRow = ActiveSheet.UsedRange.Row + ActiveSheet.UsedRange.Rows.Count - 1
Определение последнего столбца через UsedRange
lLastCol = ActiveSheet.UsedRange.Column + ActiveSheet.UsedRange.Columns.Count - 1
НЕМНОГО ПОЯСНЕНИЙ:
- ActiveSheet.UsedRange.Row — этой строкой мы определяем первую ячейку, с которой начинаются данные на листе. Важно понимать для чего это — если у вас первые строк 5 не заполнены ничем(т.е. самые первые данные заносились начиная с 6-ой строки листа), то ActiveSheet.UsedRange.Row вернет именно 6(т.е. номер первой строки с данными). Если же все строки заполнены — то вернет 1.
- ActiveSheet.UsedRange.Rows.Count — определяем кол-во строк, входящих в весь диапазон данных на листе. При этом неважно, есть ли данные в ячейках или нет — достаточно было поработать в этих ячейках и удалить значения или просто изменить цвет заливки.
В итоге получается: первая строка данных + кол-во строк с данными — 1. Зачем вычитать единицу? Попробуем посчитать вместе: первая строка: 6. Всего строк: 3. 6 + 3 = 9. Вроде все верно. А теперь выделим на листе три ячейки, начиная с 6-ой. Выделение завершилось на 8-ой строке. Потому что в 6-ой строке уже есть данные. Поэтому и надо вычесть 1, чтобы учесть этот момент. Думаю, не надо пояснять, что если надо получить первую пустую ячейку — можно 1 не вычитать - То же самое и с ActiveSheet.UsedRange.Column, только уже не для строк, а для столбцов.
Нюансы:
- Обладает некоторыми недостатками предыдущего метода. Определяет самую «дальнюю» ячейку на листе, используя при этом механизм «запоминания» тех ячеек, в которых мы работали в данном листе. Следовательно попробовать обойти этот момент можно точно так же: перед определением последней строки/столбца записать строку: With ActiveSheet.UsedRange: End With
Это должно переопределить границы рабочего диапазона и тогда определение последней строки/столбца сработает как ожидается, даже если до этого в ячейке содержались данные, которые впоследствии были удалены. - даже если в ячейке нет видимого значения, но есть формула — UsedRange посчитает ячейку не пустой
Однако метод через UsedRange.Row работает прекрасно и при установленной на лист защите и внутри UDF, что делает его более предпочтительным, чем метод через SpecialCells при равных условиях.
Способ 4:
Определение последней строки и столбца, а так же адрес ячейки методом Find
Sub GetLastCell_Find() Dim rF As Range Dim lLastRow As Long, lLastCol As Long 'ищем последнюю ячейку на листе, в которой хранится хоть какое-то значение Set rF = ActiveSheet.UsedRange.Find(What:="*", LookIn:=xlValues, LookAt:=xlWhole, SearchDirection:=xlPrevious, MatchCase:=False, MatchByte:=False) If Not rF Is Nothing Then lLastRow = rF.Row 'последняя заполненная строка lLastCol = rF.Column 'последний заполненный столбец MsgBox rF.Address 'показываем сообщение с адресом последней ячейки Else 'если ничего не нашлось - значит лист пустой 'и можно назначить в качестве последних первую строку и столбец lLastRow = 1 lLastCol = 1 MsgBox "A1" 'показываем сообщение с адресом ячейки А1 End If End Sub
Этот метод, пожалуй, самый оптимальный в случае, если надо определить последнюю строку/столбец на листе без учета форматов и формул — только по отображаемому значению в ячейке. Например, если на листе большая таблица и последние строки заполнены формулами, возвращающими при определенных условиях пустую ячейку(=ЕСЛИ(A1>0;1;»»)), предыдущие варианты вернут строку/столбец ячейки с последней ячейкой, в которой формула. В то время как данный метод вернет адрес ячейки только в случае, если в ячейке реально отображается какое-то значение. Такой подход часто используется для того, чтобы определить границы данных для последующего анализа заполненных данных, чтобы не захватывать пустые ячейки с формулами и не тратить время на их проверку.
Здесь следует обратить внимание на параметры метода Find. В данном случае мы специально указываем искать по значениям, а не по формулам:
Set rF = ActiveSheet.UsedRange.Find(What:=»*», LookIn:=xlValues, LookAt:=xlWhole, SearchDirection:=xlPrevious, MatchCase:=False, MatchByte:=False)
Нюансы:
- Метод Find, вызванный с листа или другим кодом, имеет свойство запоминать все параметры последнего поиска, а если поиск еще не вызывался — то применяются параметры по умолчанию. А по умолчанию поиск идет всегда по формулам. Поэтому я настоятельно рекомендую указывать принудительно все необходимые параметры, как в примере.
- Метод Find не будет учитывать в просмотре скрытые строки и столбцы. Это следует учитывать при его применении.
Пара небольших практических кодов
Коды ниже могут помочь понять, как использовать приведенные выше строки кода по поиску последней ячейки/строки:
Sub GetLastCell() Dim lLastRow As Long Dim lLastCol As Long 'определили последнюю заполненную ячейку с учетом формул в столбце А lLastRow = Cells(Rows.Count, 1).End(xlUp).Row MsgBox "Заполненные ячейки в столбце А: " & Range("A1:A" & lLastRow).Address 'определили последний заполненный столбец на листе(с учетом формул и форматирования) lLastCol = Cells.SpecialCells(xlLastCell).Column MsgBox "Заполненные ячейки в первой строке: " & Range(Cells(1, 1), Cells(1, lLastCol)).Address 'выводим сообщение с адресом последней ячейки на листе(с учетом формул и форматирования) MsgBox "Адрес последней ячейки диапазона на листе: " & Cells.SpecialCells(xlLastCell).Address End Sub
Выделяем диапазон ячеек в столбцах с А по С, определяя последнюю ячейку по столбцу A этого же листа:
Sub SelectToLastCell() Range("A1:C" & Cells(Rows.Count, 1).End(xlUp).Row).Select End Sub
Копируем ячейку B1 в первую пустую ячейку столбца A этого же листа:
Sub CopyToFstEmptyCell() Dim lLastRow As Long lLastRow = Cells(Rows.Count, 1).End(xlUp).Row 'определили последнюю заполненную ячейку Range("B1").Copy Cells(lLastRow+1, 1) 'скопировали В1 и вставили в следующую после определенной ячейки End Sub
А код ниже делает тоже самое, но одной строкой — применяется Offset и используется тот факт, что изначально методом End мы получаем именно ячейку, а не номер строки(номер строки мы получаем позже через свойство .Row):
Sub CopyToFstEmptyCell() Range("B1").Copy Destination:=Cells(Rows.Count, 1).End(xlUp).Offset(1) End Sub
Range(«B1»).Copy — копирует ячейку В1. Если для аргумента Destination указать другую ячейку, то в неё будет вставлена скопированная ячейка. Мы передаем в этот аргумент определенную методом End ячейку
Cells(Rows.Count, 1).End(xlUp) — возвращает последнюю заполненную ячейку в столбце А (не строку, а именно ячейку)
Offset(1) — смещает полученную ячейку на строку вниз
Используем инструмент автозаполнение(протягивание) столбца В, начиная с ячейки B2 и определяя последнюю ячейку для заполнения на основании столбца А
Sub AutoFill_B() Dim lLastRow As Long lLastRow = Cells(Rows.Count, 1).End(xlUp).Row Range("B2").AutoFill Destination:=Range("B2:B" & lLastRow) End Sub
На самом деле практических кодов может быть куда больше, т.к. определение последней заполненной или первой пустой ячейки является чуть ли не самой распространенной задачей при написании кодов в Excel.
Так же см.:
Как получить последнюю заполненную ячейку формулой?
Как определить первую заполненную ячейку на листе?
Что такое переменная и как правильно её объявить?
Статья помогла? Поделись ссылкой с друзьями!
Видеоуроки
Поиск по меткам
Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика
is there a limit in vba string variable?
Public query As String
query="select * from ......"
i type a query that’s very long and at a certain point it just stop, i can’t type anything more in the quotes
i tried to copy paste my query from notepad but the query is being split to new line
i tried to print the length it’s stop at 1005
len(query)
if there really is a limit in vba string
how should i do a very long string then?
asked Jun 13, 2014 at 11:18
1
From the documentation :
The zero length empty string and all possible character sequences
using characters from the implementation dependent character set.
There MAY be an implementation defined limit to the length of such
sequences but the limit SHOULD be no smaller than (2^16 – 1)
characters.
So you should be able to have a string length of at least 65535 characters.
However, the editor seems to have some kind of restriction regarding the length of line code, not just strings.
As mentionned, use _
to split a line code.
answered Jun 13, 2014 at 13:12
z̫͋z̫͋
1,53110 silver badges15 bronze badges
2
I have had this problem when writing queries as well. The way around it I found was as follows :-
query = "SELECT * " & _
"FROM...."
Then when you reach a suitable juncture :-
query = query & "WHERE...."
etc. I believe the maximum is in inputting to the string in one go, not on the actual overall length. This solution got me around the problem, so hopefully will aid you.
answered Jun 13, 2014 at 11:28
1
The max number of characters you can use in string in a vba function is 255.
I am trying to run this function
Var1= 1
Var2= 2
.
.
.
Var256 =256
RunMacros= "'Tims_pet_Robot """ & Var1 & """ , """ & Var2 & """ , """ ... """ & Var256 """ '"
Runat=TimeValue("15:00:00")
Application.OnTime EarliestTime:=Runat, Procedure:=RunMacros & RunMacros2 ', schedule:=True
It runs a procedure at a certain time and passes a bunch of variables to it. but the string is too long.
Update:
Regrettably I am sure it is not the watch window.
Also, it isn’t really the max size of a string that I’m dealing with. It’s the max size of
a string in a vba function.
For example this function works.
Sub test()
Dim RunAt As Date
Dim RunWhat As String
RunAt = Now + 0.00001
RunWhat = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 'that makes 254 'a''s
Application.OnTime EarliestTime:=RunAt, Procedure:="'" & RunWhat & " 12'"
End Sub
Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(m As Integer)
MsgBox ("it works!" & m)
End Sub
But if you change the 12 to 123 it breaks
Example
Sub test2()
Dim RunAt As Date
Dim RunWhat As String
RunAt = Now + 0.00001
RunWhat = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 'that makes 254 'a''s
Application.OnTime EarliestTime:=RunAt, Procedure:="'" & RunWhat & " 123'"
End Sub
Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(m As Integer)
MsgBox ("it works!" & m)
End Sub
This code does not work, I’m pretty sure it’s because a vba function cannot handle a string with more than 255 chars.
Even if you’re in Excel and call a function and give it a string longer that 255 chars it doesn’t work.
Try in cell A1 =vlookup(«really long string», A1:Z10, 1) and then put the really long string somewhere in that range. The vlookup will fail (not fail to find it, but you won’t actually be able to do it)
Also I am aware that there is a max length to a sub name, I’m just under it. Sorry that it look so ugly.
Update 2: so I just ended up printing the variable to a sheet and getting the function called by ontime to read them off the sheet.
О чём пойдёт речь?
Знакомство с объектной моделью Excel следует начинать с такого замечательного объекта, как Range. Поскольку любая ячейка — это Range, то без знания, как с этим объектом эффективно взаимодействовать, вам будет затруднительно программировать для Excel. Это очень ладно-скроенный объект. При некоторой сноровке вы найдёте его весьма удобным в эксплуатации.
Что такое объекты?
Мы собираемся изучать объект Range, поэтому пару слов надо сказать, что такое, собственно, «объект«. Всё, что вы наблюдаете в Excel, всё с чем вы работаете — это набор объектов. Например, лист рабочей книги Excel — не что иное, как объект типа WorkSheet. Однотипные объекты объединяют в коллекции себе подобных. Например, листы объединены в коллекцию Sheets. Чтобы не путать друг с другом объекты одного и того же типа, они имеют отличающиеся имена, а также номер индекса в коллекции. Объекты имеют свойства, методы и события.
Свойства — это информация об объекте. Часто эти свойства можно менять, что автоматически влечет изменения внешнего вида объекта или его поведения. Например свойство Visible объекта Worksheet отвечает за видимость листа на экране. Если ему присвоить значение xlSheetHidden (это константа, которая по факту равно нулю), то лист будет скрыт.
Методы — это то, что объект может делать. Например, метод Delete объекта Worksheet удаляет себя из книги. Метод Select делает лист активным.
События — это механизм, при помощи которого вы можете исполнять свой код VBA сразу по факту возникновения того или иного события с вашим объектом. Например, есть возможность выполнять ваш код, как только пользователь сделал текущим определенный лист рабочей книги, либо как только пользователь что-то изменил на этом листе.
Range это диапазон ячеек. Минимум — одна ячейка, максимум — весь лист, теоретически насчитывающий более 17 миллиардов ячеек (строки 2^20 * столбцы 2^14 = 2^34).
В Excel объявлены глобально и всегда готовы к использованию несколько коллекций, имеющий членами объекты типа Range, либо свойства это же типа.
Коллекции глобального объекта Application: Cells, Columns, Rows, а также свойства Range, Selection, ActiveCell, ThisCell.
ActiveCell — активная ячейка текущего листа, ThisCell — если вы написали пользовательскую функцию рабочего листа, то через это свойство вы можете определить какая конкретно ячейка в данный момент пересчитывает вашу функцию. Об остальных перечисленных объектов речь пойдёт ниже.
Работа с отдельными ячейками
Синтаксическая форма | Комментарии по использованию |
Range(«D5«) или [D5] |
Ячейка D5 текущего листа. Полная и краткая формы. Тут применим только синтаксис типа A1, но не R1C1. То есть такая конструкция Range(«R1C2«) — вызовет ошибку, даже если в книге Excel включен режим формул R1C1. Разумеется после этой формы вы можете обратиться к свойствам соответствующей ячейки. Например, Range(«D5«).Interior.Color = RGB(0, 255, 0). |
Cells(5, 4) или Cells(5, «D») | Ячейка D5 текущего листа через свойство Cells. 5 — строка (row), 4 — столбец (column). Допустимость второй формы мало кому известна. |
Cells(65540) | Ячейку D5 можно адресовать и через указание только одного параметра свойсва Cells. При этом нумерация идёт слева направо, потом сверху вниз. То есть сначала нумеруется вся строка (2^14=16384 колонок) и только потом идёт переход на следующую строку. То есть Cells(16385) вернёт вам ячейку A2, а D5 будет Cells(65540). Пока данный способ выглядит не очень удобным. |
Работа с диапазоном ячеек
Синтаксическая форма | Комментарии по использованию |
Range(«A1:B4«) или [A1:B4] | Диапазон ячеек A1:B4 текущего листа. Обратите внимание, что указываются координаты верхнего левого и правого нижнего углов диапазона. Причём первый указываемый угол вполне может быть правым нижним, это не имеет значения. |
Range(Cells(1, 1), Cells(4, 2)) | Диапазон ячеек A1:B4 текущего листа. Удобно, когда вы знаете именно цифровые координаты углов диапазона. |
Работа со строками
Синтаксическая форма | Комментарии по использованию |
Range(«3:5«) или [3:5] | Строки 3, 4 и 5 текущего листа целиком. |
Range(«A3:XFD3«) или [A3:XFD3] | Строка 3, но с указанием колонок. Просто, чтобы вы понимали, что это тождественные формы. XFD — последняя колонка листа. |
Rows(«3:3«) | Строка 3 через свойство Rows. Параметр в виде диапазона строк. Двоеточие — это символ диапазона. |
Rows(3) | Тут параметр — индекс строки в массиве строк. Так можно сослаться только не конкретную строку. Обратите внимание, что в предыдущем примере параметр текстовая строка «3:3» и она взята в кавычки, а тут — чистое число. |
Работа со столбцами
Синтаксическая форма | Комментарии по использованию |
Range(«B:B«) или [B:B] | Колонка B текущего листа. |
Range(«B1:B1048576«) или [B1:B1048576] | То же самое, но с указанием номеров строк, чтобы вы понимали, что это тождественные формы. 2^20=1048576 — максимальный номер строки на листе. |
Columns(«B:B«) | То же самое через свойство Columns. Параметр — текстовая строка. |
Columns(2) | То же самое. Параметр — числовой индекс столбца. «A» -> 1, «B» -> 2, и т.д. |
Весь лист
Синтаксическая форма | Комментарии по использованию |
Range(«A1:XFD1048576«) или [A1:XFD1048576] | Диапазон размером во всё адресное пространство листа Excel. Воспринимайте эту таблицу лишь как теорию — так работать с листами вам не придётся — слишком большое количество ячеек. Даже современные компьютеры не смогут помочь Excel быстро работать с такими массивами информации. Тут проблема больше даже в самом приложении. |
Range(«1:1048576«) или [1:1048576] | То же самое, но через строки. |
Range(«A:XFD«) или [A:XFD] | Аналогично — через адреса столбцов. |
Cells | Свойство Cells включает в себя ВСЕ ячейки. |
Rows | Все строки листа. |
Columns | Все столбцы листа. |
Следует иметь в виду, что свойства Range, Cells, Columns и Rows имеют как объекты типа Worksheet, так и объекты Range. Соответственно в первом случае эти коллекции будут относиться ко всему листу и отсчитываться будут от A1, а вот в случае конкретного объекта Range эти коллекции будут относиться только к ячейкам этого диапазона и отсчитываться будут от левого верхнего угла диапазона. Например Cells(2,2) указывает на ячейку B2, а Range(«C3:D5»).Cells(2,2) укажет на D4.
Также много путаницы в умы вносит тот факт, что объект Range имеет одноименное свойство range. К примеру, Range(«A100:D500»).Range(«A2») — тут выражение до точки ( Range(«A100:D500») ) является объектом Range, выражение после точки ( Range(«A2») ) — свойство range упомянутого объекта, но возвращает это свойство тоже объект типа Range. Вот такие пироги. Из этого следует, что такая цепочка может иметь и более двух членов. Практического смысла в этом будет не много, но синтаксически это будут совершенно корректно, например, так: Range(«CV100:GR200»).Range(«J10:T20»).Range(«A1:B2») укажет на диапазон DE109:DF110.
Ещё один сюрприз таится в том, что объекты Range имеют свойство по-умолчанию Item( RowIndex [, ColumnIndex] ). По правилам VBA при ссылке на default свойства имя свойства (Item) можно опускать. Кстати говоря, то что вы привыкли видеть в скобках после Cells, есть не что иное, как это дефолтовое свойство Item, а не родные параметры Cells, который их не имеет вовсе. Ну ладно к Cells все привыкли и это никакого отторжения не вызывает, но если вы увидите нечто подобное — Range(«C3:D5»)(2,2), то, скорее всего, будете несколько озадачены, а тем временем — это буквально тоже самое, что и у Cells — всё то же дефолтовое свойство Item. Последняя конструкция ссылается на D4. А вот для Columns и Rows свойство Item может быть только одночленным, например Columns(1) — и к этой форме мы тоже вполне привыкли. Однако конструкции вида Columns(2)(3)(4) могут сильно удивить (столбец 7 будет выделен).
Примеры кода
Скачать
Типовые задачи
-
Перебор ячеек в диапазоне (вариант 1)
В данном примере организован цикл For…Next и доступ к ячейкам осуществляется по их индексу. Вместо parRange(i) мы могли бы написать parRange.Item(i) (выше это объяснялось). Обратите внимание, что мы в этом примере успешно применяем, как вариант с parRange(i,c), так и parRange(i). То есть, если мы применяем одночленную форму свойства Item, то диапазон перебирается по строкам (A1, B1, C1, A2, …), а если двухчленную, то столбец у нас зафиксирован и каждая итерация цикла — на новой строке. Это очень интересный эффект, его можно применять для вытягивания таблиц по вертикали. Но — продолжим!
Количество ячеек в диапазоне получено при помощи свойства .Count. Как .Item, так и .Count — это всё атрибуты коллекций, которые широко применяются в объектой модели MS Office и, в частности, Excel.
Sub Handle_Cells_1(parRange As Range) For i = 1 To parRange.Count parRange(i, 5) = parRange(i).Address & " = " & parRange(i) Next End Sub
-
Перебор ячеек в диапазоне (вариант 2)
В этом примере мы использовали цикл For each…Next, что выглядит несколько лаконичней. Однако, в некоторых случаях вам может потребоваться переменная i из предыдущего примера, например, для вывода результатов в определенные строки листа, поэтому выбирайте удробную вам форму оператора For. Тут в цикле мы «вытягивали» все ячейки диапазона в текстовую строку, чтобы потом отобразить её через функцию MsgBox.
Sub Handle_Cells_2(parRange As Range) For Each c In parRange strLine = strLine & c.Address & "=" & c & "; " Next MsgBox strLine End Sub
-
Перебор ячеек в диапазоне (вариант 3)
Если необходимо перебирать ячейки в порядке A1, A2, A3, B1, …, а не A1, B1, C1, A2, …, то вы можете это организовать при помощи 2-х циклов For. Обратите внимание, как мы узнали количество столбцов (parRange.Columns.Count) и строк (parRange.Rows.Count) в диапазоне, а также на использование свойства Cells. Тут Cells относится к листу и никак не связано с диапазоном parRange.
Sub Handle_Cells_3(parRange As Range) colNum = parRange.Columns.Count For i = 1 To parRange.Rows.Count For j = 1 To colNum Cells(i + (j - 1) * colNum, colNum + 2) = parRange(i, j) Next j Next i End Sub
-
Перебор строк диапазона
В цикле For each…Next перебираем коллекцию Rows объекта parRange. Для каждой строки формируем цвет на основе первых трёх ячеек каждой строки. Поскульку у нас в ячейках формула, присваивающая ячейке случайное число от 1 до 255, то цвета получаются всегда разные. Оператор With позволяет нам сократить код и, к примеру, вместо Line.Cells(2) написать просто .Cells(2).
Sub Handle_Rows_1(parRange As Range) For Each Line In parRange.Rows With Line .Interior.Color = RGB(.Cells(1), .Cells(2), .Cells(3)) End With Next End Sub
-
Перебор столбцов
Перебираем коллекцию Columns. Тоже используем оператор With. В последней ячейке каждого столбца у нас хранится размер шрифта для всей колонки, который мы и применяем к свойству Line.Font.Size.
Sub Handle_Columns_1(parRange As Range) For Each Line In parRange.Columns With Line .Font.Size = .Cells(.Cells.Count) End With Next End Sub
-
Перебор областей диапазона
Как вы знаете, в Excel можно выделить несвязанные диапазоны и проделать с ними какие-то операции. Поддерживает это и объект Range. Получить диапазон, состоящий из нескольких областей (area) очень легко — достаточно перечислить через запятую адреса соответствующих диапазонов: Range(«A1:B3, B5:D8, Z1:AA12«).
Вот такой составной диапазон и разбирается процедурой, показанной ниже. Организован цикл по коллекции Areas, настроен оператор with на текущий элемент коллекции, и ниже и правее относительно ячейки J1 мы собираем некоторые сведения о свойствах областей составного диапазона (которые каждый по себе, конечно же, тоже являются объектами типа Range). Для задания смещения от ячейки J1 нами впервые использовано очень полезное свойство Offset. Каждый диапазон получает случайный цвет, плюс мы заносим в таблицу порядковый номер диапазона (i), его адрес (.Address), количество ячеек (.Count) и цвет (.Interior.Color) после того, как он вычислен.Sub Handle_Areas_1(parRange As Range) For i = 1 To parRange.Areas.Count With parRange.Areas(i) Cells(1, 10).Offset(i, 0) = i Cells(1, 10).Offset(i, 1) = .Address Cells(1, 10).Offset(i, 2) = .Count .Interior.Color = RGB(Int(Rnd * 255), Int(Rnd * 255), Int(Rnd * 255)) Cells(1, 10).Offset(i, 3) = .Interior.Color End With Next End Sub
Продолжение следует…
Читайте также:
-
Поиск границ текущей области
-
Массивы в VBA
-
Структуры данных и их эффективность
-
Автоматическое скрытие/показ столбцов и строк