Программируя в VBA, часто можно столкнуться с ситуацией, когда приходится решать одни и те же задачи снова и снова из-за того, что в языке нет удобных встроенных средств для работы с объектами. В данной статье собраны аналоги функций Python для работы с объектами в VBA.
Содержание
Table of Contents:
Функция для добавления элемента к массиву VBA
Аналог метода append из Python для массива MS Office VBA.
# Метод в Python
MyList.append(ItemToAppend)
Вариант аналога в VBA:
'Функция append:
Function append(InArray, Value) 'InArray - массив, Value - элемент, который необходимо добавить к нему
ReDim Preserve InArray(UBound(InArray) + 1) 'увеличиваем размер массива с сохранением имеющихся в нём значений
InArray(UBound(InArray)) = Value 'дописываем Value в массив
append = InArray 'функция возвращает новый массив
End Function
'Пример использования функции:
Sub MySub ()
'Для работы необходимо вставить эту функцию в свой проект VBA
'и использовать в качестве первого аргумента динамический массив:
ReDim InArray(0) as Variant 'Наш динамический массив
ReDim Value as String 'Произвольная переменная, например, типа String
Value = "MyStringValue" 'записываем произвольный текст в переменную
InArray = append(InArray, Value) 'вызов функции append
Debug.Print (InArray(1)) 'Убедиться в том, что первый элемент добавлен можно, например, так - в окне Immediate
MsgBox(InArray(1)) 'либо так – в сообщении
End Sub
UPD 2022. Вариант проще:
ReDim Preserve MyArray (UBound(MyArray) + 1)
MyArray (UBound(MyArray))= "VALUE"
Последняя строка/столбец VBA
Метод 1 - UsedRange
LastRow1 = ActiveSheet.UsedRange.Row + ActiveSheet.UsedRange.Rows.Count - 1
LastCol1 = ActiveSheet.UsedRange.Column + ActiveSheet.UsedRange.Columns.Count - 1
UsedRange - область на листе, в которой что-то есть. Использование отдельно UsedRange.Rows.Count для поиска последнего ряда/столбца ненадёжно, т.к. в случае, если на листе есть пустые столбцы/строки, будет получен неверный результат.
Метод 2 - End(xlUp).Row
Метод следует использовать, если нужно найти последний заполненный столбец/строку по конкретной строке/столбцу.
LastRow2 = Cells(Rows.Count, 7).End(xlUp).Row ' Найти последнюю строку в столбце 7
LastCol2 = Cells(13, Columns.Count).End(xlToLeft).Column 'Найти послдений столбец в строке 13
Метод 3 - пользовательская функция. Получить последнюю ячейку как объект Range
В данном случае используется поиск -1 значения относительно первой ячейки по столбцам и по строкам. По умолчанию работает на активном листе. Можно указать на вход лист (как объект Worksheet).
Function Last_Cell(Optional ws As Worksheet) As Range
Dim LastCol As Long, LastRow As Long
LastCol = 1
LastRow = 1
On Error Resume Next
If ws Is Nothing Then Set ws = ActiveSheet
LastCol = ws.UsedRange.Cells.Find(what:="*", after:=ws.UsedRange.Cells(1), _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, searchformat:=False).Column
LastRow = ws.UsedRange.Cells.Find(what:="*", after:=ws.UsedRange.Cells(1), _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, searchformat:=False).Row
Set Last_Cell = ws.Cells(LastRow, LastCol)
End Function
Все функции:
Sub findlastrow()
'1 - using UsedRange
LastRow1 = ActiveSheet.UsedRange.Row + ActiveSheet.UsedRange.Rows.Count - 1
LastCol1 = ActiveSheet.UsedRange.Column + ActiveSheet.UsedRange.Columns.Count - 1
'where UsedRange begins + number of rows/columns in the usedrange - 1
Debug.Print ("Method 1")
Debug.Print ("Row" + Str(LastRow1) + " Column " + Str(LastCol1))
Debug.Print ("Value " + Str(ThisWorkbook.ActiveSheet.Cells(LastRow1, LastCol1).Value))
Debug.Print (" Usedrange params")
Debug.Print (" ActiveSheet.UsedRange.Rows.Count " + Str(ActiveSheet.UsedRange.Rows.Count))
Debug.Print (" ActiveSheet.UsedRange.Row " + Str(ActiveSheet.UsedRange.Row))
Debug.Print ("LastCol " + Str(LastCol1))
Debug.Print (" ")
'2 if you know which column/row to choose to count as last:
LastRow2 = Cells(Rows.Count, 7).End(xlUp).Row '!!!! 7 - column to look for last row
LastCol2 = Cells(13, Columns.Count).End(xlToLeft).Column '!!! row to look for last column
Debug.Print ("Method 2")
Debug.Print ("LastRow " + Str(LastRow2) + " LastCol " + Str(LastCol2))
Debug.Print (" ")
'3 - ultimate solution - custom function - using Search (previous from the first cell -> last cell
' output of the funciton Last_Cell - object (range) - lastcell
LastRow = Last_Cell.Row
LastCol = Last_Cell.Column
LastVal = Last_Cell.Value
Debug.Print ("Method 3")
Debug.Print ("Last_Cell.Row " + Str(Last_Cell.Row))
Debug.Print ("Last_Cell.Column " + Str(Last_Cell.Column))
Debug.Print ("Last_Cell.Value " + Str(Last_Cell.Value))
End Sub
Function Last_Cell(Optional ws As Worksheet) As Range
Dim LastCol As Long, LastRow As Long
LastCol = 1
LastRow = 1
On Error Resume Next
If ws Is Nothing Then Set ws = ActiveSheet
LastCol = ws.UsedRange.Cells.Find(what:="*", after:=ws.UsedRange.Cells(1), _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, searchformat:=False).Column
LastRow = ws.UsedRange.Cells.Find(what:="*", after:=ws.UsedRange.Cells(1), _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, searchformat:=False).Row
Set Last_Cell = ws.Cells(LastRow, LastCol)
End Function
'OUTPUT:
'Method 1
'Row 13 Column 7
'Value 1234
' Usedrange params
' ActiveSheet.UsedRange.Rows.Count 1
' ActiveSheet.UsedRange.Row 13
'LastCol 7
'Method 2
'LastRow 13 LastCol 7
'Method 3
'Last_Cell.Row 13
'Last_Cell.Column 7
'Last_Cell.Value 1234