Свойство Cells объекта Range в VBA Excel, представляющее коллекцию ячеек заданного диапазона. Обращение к ячейкам диапазона с помощью свойства Cells.
Range.Cells – свойство, возвращающее коллекцию всех ячеек указанного диапазона.
Свойство Cells объекта Worksheet
Обращение к ячейке «A1» активного рабочего листа с помощью свойства Cells:
‘по индексу (порядковому номеру) ячейки MsgBox Cells(1).Address ‘Результат: $A$1 ‘по номеру строки и номеру столбца MsgBox Cells(1, 1).Address ‘Результат: $A$1 ‘по номеру строки и буквенному обозначению столбца MsgBox Cells(1, «A»).Address ‘Результат: $A$1 |
В данном случае в качестве объекта Range выступает диапазон всего активного рабочего листа (ActiveSheet). Полный путь к ячейке «A1» можно записать так:
MsgBox ThisWorkbook.ActiveSheet.Cells(1).Address ‘Результат: $A$1 MsgBox ThisWorkbook.ActiveSheet.Cells(1, 1).Address ‘Результат: $A$1 MsgBox ThisWorkbook.ActiveSheet.Cells(1, «A»).Address ‘Результат: $A$1 |
Обращение в VBA Excel к ячейке «C5» с помощью свойства Cells по имени рабочего листа (Worksheet) в другой книге Excel:
MsgBox Workbooks(«Книга1.xlsm»).Worksheets(«Лист1»).Cells(65539).Address ‘Результат: $C$5 в Excel 2016 MsgBox Workbooks(«Книга1.xlsm»).Worksheets(«Лист1»).Cells(5, 3).Address ‘Результат: $C$5 MsgBox Workbooks(«Книга1.xlsm»).Worksheets(«Лист1»).Cells(5, «C»).Address ‘Результат: $C$5 |
Обращение к диапазону «C5:G10» с помощью свойства Cells активного рабочего листа:
MsgBox Range(Cells(5, 3), Cells(10, 7)).Address ‘Результат: $C$5:$G$10 |
Обращение в VBA Excel к ячейкам заданного диапазона с помощью свойства Cells рассмотрим на коллекции ячеек диапазона «C5:G10». Обращаться будем к ячейке «D8» активного листа:
MsgBox Range(«C5:G10»).Cells(17).Address ‘Результат: $D$8 MsgBox Range(«C5:G10»).Cells(4, 2).Address ‘Результат: $D$8 MsgBox Range(«C5:G10»).Cells(4, «B»).Address ‘Результат: $D$8 |
Обратите внимание, что отсчет номеров строк, номеров и буквенных обозначений столбцов для указания адреса ячейки внутри диапазона ведется от верхней левой ячейки данного диапазона.
Обход диапазона ячеек циклом
Обход ячеек циклом For Each… Next
Обход ячеек циклом For Each… Next — это самый простой способ обхода всех ячеек заданного диапазона. Он может быть применен, например, для присвоения ячейкам свойств и значений или поиска ячейки с определенным свойством или значением.
Присвоение ячейкам диапазона «B3:F10» числовых значений, соответствующих их порядковым номерам (индексам) в диапазоне:
Sub Primer1() Dim myCell As Range, n As Long For Each myCell In Range(«B3:F10») n = n + 1 myCell = n Next End Sub |
Поиск в диапазоне «B3:F10», заполненном предыдущим кодом VBA Excel значениями, ячейки со значением «27», окрашивание ее в зеленый цвет и выход из цикла:
Sub Primer2() Dim myCell As Range, n As Long For Each myCell In Range(«B3:F10») If myCell = 27 Then myCell.Interior.Color = vbGreen Exit For End If Next End Sub |
Обход диапазона циклом For… Next
Цикл For… Next позволяет указывать переменные в качестве индексов ячеек или номеров строк и столбцов для обхода ячеек заданного диапазона.
Присвоение ячейкам диапазона «B3:F10» числовых значений, соответствующих их порядковым номерам (индексам) в диапазоне, с помощью цикла For… Next:
Sub Primer3() Dim i As Long, n As Long With Range(«B3:F10») n = .Cells.Count For i = 1 To n .Cells(i) = i Next End With End Sub |
Если в блоке с оператором With вместо строки .Cells(i) = i
указать строку без точки впереди — Cells(i) = i
, то свойство Cells будет относиться не к диапазону Range("B3:F10")
, а к рабочему листу (объекту ActiveSheet). В этом случае, порядковыми номерами будут заполнены первые 40 ячеек первой строки активного рабочего листа.
Применение в качестве параметров свойства Cells объекта Range переменных, задающих номера строк и номера столбцов указанного диапазона при обходе его ячеек циклом For… Next:
Sub Primer4() Dim i1 As Long, i2 As Long, r As Long, c As Long With Range(«B3:F10») r = .Rows.Count c = .Columns.Count For i1 = 1 To r For i2 = 1 To c .Cells(i1, i2) = (i1 — 1) * c + i2 Next Next End With End Sub |
Номер ячейки на рабочем листе
Определение порядкового номера (индекса) активной ячейки на рабочем листе Excel с помощью кода VBA:
Sub Primer5() Dim n As Double n = (ActiveCell.Row — 1) * CDbl(Cells.Columns.Count) + ActiveCell.Column MsgBox n End Sub |
На чтение 18 мин. Просмотров 75.5k.
сэр Артур Конан Дойл
Это большая ошибка — теоретизировать, прежде чем кто-то получит данные
Эта статья охватывает все, что вам нужно знать об использовании ячеек и диапазонов в VBA. Вы можете прочитать его от начала до конца, так как он сложен в логическом порядке. Или использовать оглавление ниже, чтобы перейти к разделу по вашему выбору.
Рассматриваемые темы включают свойство смещения, чтение
значений между ячейками, чтение значений в массивы и форматирование ячеек.
Содержание
- Краткое руководство по диапазонам и клеткам
- Введение
- Важное замечание
- Свойство Range
- Свойство Cells рабочего листа
- Использование Cells и Range вместе
- Свойство Offset диапазона
- Использование диапазона CurrentRegion
- Использование Rows и Columns в качестве Ranges
- Использование Range вместо Worksheet
- Чтение значений из одной ячейки в другую
- Использование метода Range.Resize
- Чтение Value в переменные
- Как копировать и вставлять ячейки
- Чтение диапазона ячеек в массив
- Пройти через все клетки в диапазоне
- Форматирование ячеек
- Основные моменты
Краткое руководство по диапазонам и клеткам
Функция | Принимает | Возвращает | Пример | Вид |
Range | адреса ячеек |
диапазон ячеек |
.Range(«A1:A4») | $A$1:$A$4 |
Cells | строка, столбец |
одна ячейка |
.Cells(1,5) | $E$1 |
Offset | строка, столбец |
диапазон | .Range(«A1:A2») .Offset(1,2) |
$C$2:$C$3 |
Rows | строка (-и) | одна или несколько строк |
.Rows(4) .Rows(«2:4») |
$4:$4 $2:$4 |
Columns | столбец (-цы) |
один или несколько столбцов |
.Columns(4) .Columns(«B:D») |
$D:$D $B:$D |
Введение
Это третья статья, посвященная трем основным элементам VBA. Этими тремя элементами являются Workbooks, Worksheets и Ranges/Cells. Cells, безусловно, самая важная часть Excel. Почти все, что вы делаете в Excel, начинается и заканчивается ячейками.
Вы делаете три основных вещи с помощью ячеек:
- Читаете из ячейки.
- Пишите в ячейку.
- Изменяете формат ячейки.
В Excel есть несколько методов для доступа к ячейкам, таких как Range, Cells и Offset. Можно запутаться, так как эти функции делают похожие операции.
В этой статье я расскажу о каждом из них, объясню, почему они вам нужны, и когда вам следует их использовать.
Давайте начнем с самого простого метода доступа к ячейкам — с помощью свойства Range рабочего листа.
Важное замечание
Я недавно обновил эту статью, сейчас использую Value2.
Вам может быть интересно, в чем разница между Value, Value2 и значением по умолчанию:
' Value2 Range("A1").Value2 = 56 ' Value Range("A1").Value = 56 ' По умолчанию используется значение Range("A1") = 56
Использование Value может усечь число, если ячейка отформатирована, как валюта. Если вы не используете какое-либо свойство, по умолчанию используется Value.
Лучше использовать Value2, поскольку он всегда будет возвращать фактическое значение ячейки.
Свойство Range
Рабочий лист имеет свойство Range, которое можно использовать для доступа к ячейкам в VBA. Свойство Range принимает тот же аргумент, что и большинство функций Excel Worksheet, например: «А1», «А3: С6» и т.д.
В следующем примере показано, как поместить значение в ячейку с помощью свойства Range.
Sub ZapisVYacheiku() ' Запишите число в ячейку A1 на листе 1 этой книги ThisWorkbook.Worksheets("Лист1").Range("A1").Value2 = 67 ' Напишите текст в ячейку A2 на листе 1 этой рабочей книги ThisWorkbook.Worksheets("Лист1").Range("A2").Value2 = "Иван Петров" ' Запишите дату в ячейку A3 на листе 1 этой книги ThisWorkbook.Worksheets("Лист1").Range("A3").Value2 = #11/21/2019# End Sub
Как видно из кода, Range является членом Worksheets, которая, в свою очередь, является членом Workbook. Иерархия такая же, как и в Excel, поэтому должно быть легко понять. Чтобы сделать что-то с Range, вы должны сначала указать рабочую книгу и рабочий лист, которому она принадлежит.
В оставшейся части этой статьи я буду использовать кодовое имя для ссылки на лист.
Следующий код показывает приведенный выше пример с использованием кодового имени рабочего листа, т.е. Лист1 вместо ThisWorkbook.Worksheets («Лист1»).
Sub IspKodImya () ' Запишите число в ячейку A1 на листе 1 этой книги Sheet1.Range("A1").Value2 = 67 ' Напишите текст в ячейку A2 на листе 1 этой рабочей книги Sheet1.Range("A2").Value2 = "Иван Петров" ' Запишите дату в ячейку A3 на листе 1 этой книги Sheet1.Range("A3").Value2 = #11/21/2019# End Sub
Вы также можете писать в несколько ячеек, используя свойство
Range
Sub ZapisNeskol() ' Запишите число в диапазон ячеек Sheet1.Range("A1:A10").Value2 = 67 ' Написать текст в несколько диапазонов ячеек Sheet1.Range("B2:B5,B7:B9").Value2 = "Иван Петров" End Sub
Свойство Cells рабочего листа
У Объекта листа есть другое свойство, называемое Cells, которое очень похоже на Range . Есть два отличия:
- Cells возвращают диапазон только одной ячейки.
- Cells принимает строку и столбец в качестве аргументов.
В приведенном ниже примере показано, как записывать значения
в ячейки, используя свойства Range и Cells.
Sub IspCells() ' Написать в А1 Sheet1.Range("A1").Value2 = 10 Sheet1.Cells(1, 1).Value2 = 10 ' Написать в А10 Sheet1.Range("A10").Value2 = 10 Sheet1.Cells(10, 1).Value2 = 10 ' Написать в E1 Sheet1.Range("E1").Value2 = 10 Sheet1.Cells(1, 5).Value2 = 10 End Sub
Вам должно быть интересно, когда использовать Cells, а когда Range. Использование Range полезно для доступа к одним и тем же ячейкам при каждом запуске макроса.
Например, если вы использовали макрос для вычисления суммы и
каждый раз записывали ее в ячейку A10, тогда Range подойдет для этой задачи.
Использование свойства Cells полезно, если вы обращаетесь к
ячейке по номеру, который может отличаться. Проще объяснить это на примере.
В следующем коде мы просим пользователя указать номер столбца. Использование Cells дает нам возможность использовать переменное число для столбца.
Sub ZapisVPervuyuPustuyuYacheiku() Dim UserCol As Integer ' Получить номер столбца от пользователя UserCol = Application.InputBox("Пожалуйста, введите номер столбца...", Type:=1) ' Написать текст в выбранный пользователем столбец Sheet1.Cells(1, UserCol).Value2 = "Иван Петров" End Sub
В приведенном выше примере мы используем номер для столбца,
а не букву.
Чтобы использовать Range здесь, потребуется преобразовать эти значения в ссылку на
буквенно-цифровую ячейку, например, «С1». Использование свойства Cells позволяет нам
предоставить строку и номер столбца для доступа к ячейке.
Иногда вам может понадобиться вернуть более одной ячейки, используя номера строк и столбцов. В следующем разделе показано, как это сделать.
Использование Cells и Range вместе
Как вы уже видели, вы можете получить доступ только к одной ячейке, используя свойство Cells. Если вы хотите вернуть диапазон ячеек, вы можете использовать Cells с Range следующим образом:
Sub IspCellsSRange() With Sheet1 ' Запишите 5 в диапазон A1: A10, используя свойство Cells .Range(.Cells(1, 1), .Cells(10, 1)).Value2 = 5 ' Диапазон B1: Z1 будет выделен жирным шрифтом .Range(.Cells(1, 2), .Cells(1, 26)).Font.Bold = True End With End Sub
Как видите, вы предоставляете начальную и конечную ячейку
диапазона. Иногда бывает сложно увидеть, с каким диапазоном вы имеете дело,
когда значением являются все числа. Range имеет свойство Address, которое
отображает буквенно-цифровую ячейку для любого диапазона. Это может
пригодиться, когда вы впервые отлаживаете или пишете код.
В следующем примере мы распечатываем адрес используемых нами
диапазонов.
Sub PokazatAdresDiapazona() ' Примечание. Использование подчеркивания позволяет разделить строки кода. With Sheet1 ' Запишите 5 в диапазон A1: A10, используя свойство Cells .Range(.Cells(1, 1), .Cells(10, 1)).Value2 = 5 Debug.Print "Первый адрес: " _ + .Range(.Cells(1, 1), .Cells(10, 1)).Address ' Диапазон B1: Z1 будет выделен жирным шрифтом .Range(.Cells(1, 2), .Cells(1, 26)).Font.Bold = True Debug.Print "Второй адрес : " _ + .Range(.Cells(1, 2), .Cells(1, 26)).Address End With End Sub
В примере я использовал Debug.Print для печати в Immediate Window. Для просмотра этого окна выберите «View» -> «в Immediate Window» (Ctrl + G).
Свойство Offset диапазона
У диапазона есть свойство, которое называется Offset. Термин «Offset» относится к отсчету от исходной позиции. Он часто используется в определенных областях программирования. С помощью свойства «Offset» вы можете получить диапазон ячеек того же размера и на определенном расстоянии от текущего диапазона. Это полезно, потому что иногда вы можете выбрать диапазон на основе определенного условия. Например, на скриншоте ниже есть столбец для каждого дня недели. Учитывая номер дня (т.е. понедельник = 1, вторник = 2 и т.д.). Нам нужно записать значение в правильный столбец.
Сначала мы попытаемся сделать это без использования Offset.
' Это Sub тесты с разными значениями Sub TestSelect() ' Понедельник SetValueSelect 1, 111.21 ' Среда SetValueSelect 3, 456.99 ' Пятница SetValueSelect 5, 432.25 ' Воскресение SetValueSelect 7, 710.17 End Sub ' Записывает значение в столбец на основе дня Public Sub SetValueSelect(lDay As Long, lValue As Currency) Select Case lDay Case 1: Sheet1.Range("H3").Value2 = lValue Case 2: Sheet1.Range("I3").Value2 = lValue Case 3: Sheet1.Range("J3").Value2 = lValue Case 4: Sheet1.Range("K3").Value2 = lValue Case 5: Sheet1.Range("L3").Value2 = lValue Case 6: Sheet1.Range("M3").Value2 = lValue Case 7: Sheet1.Range("N3").Value2 = lValue End Select End Sub
Как видно из примера, нам нужно добавить строку для каждого возможного варианта. Это не идеальная ситуация. Использование свойства Offset обеспечивает более чистое решение.
' Это Sub тесты с разными значениями Sub TestOffset() DayOffSet 1, 111.01 DayOffSet 3, 456.99 DayOffSet 5, 432.25 DayOffSet 7, 710.17 End Sub Public Sub DayOffSet(lDay As Long, lValue As Currency) ' Мы используем значение дня с Offset, чтобы указать правильный столбец Sheet1.Range("G3").Offset(, lDay).Value2 = lValue End Sub
Как видите, это решение намного лучше. Если количество дней увеличилось, нам больше не нужно добавлять код. Чтобы Offset был полезен, должна быть какая-то связь между позициями ячеек. Если столбцы Day в приведенном выше примере были случайными, мы не могли бы использовать Offset. Мы должны были бы использовать первое решение.
Следует иметь в виду, что Offset сохраняет размер диапазона. Итак .Range («A1:A3»).Offset (1,1) возвращает диапазон B2:B4. Ниже приведены еще несколько примеров использования Offset.
Sub IspOffset() ' Запись в В2 - без Offset Sheet1.Range("B2").Offset().Value2 = "Ячейка B2" ' Написать в C2 - 1 столбец справа Sheet1.Range("B2").Offset(, 1).Value2 = "Ячейка C2" ' Написать в B3 - 1 строка вниз Sheet1.Range("B2").Offset(1).Value2 = "Ячейка B3" ' Запись в C3 - 1 столбец справа и 1 строка вниз Sheet1.Range("B2").Offset(1, 1).Value2 = "Ячейка C3" ' Написать в A1 - 1 столбец слева и 1 строка вверх Sheet1.Range("B2").Offset(-1, -1).Value2 = "Ячейка A1" ' Запись в диапазон E3: G13 - 1 столбец справа и 1 строка вниз Sheet1.Range("D2:F12").Offset(1, 1).Value2 = "Ячейки E3:G13" End Sub
Использование диапазона CurrentRegion
CurrentRegion возвращает диапазон всех соседних ячеек в данный диапазон. На скриншоте ниже вы можете увидеть два CurrentRegion. Я добавил границы, чтобы прояснить CurrentRegion.
Строка или столбец пустых ячеек означает конец CurrentRegion.
Вы можете вручную проверить
CurrentRegion в Excel, выбрав диапазон и нажав Ctrl + Shift + *.
Если мы возьмем любой диапазон
ячеек в пределах границы и применим CurrentRegion, мы вернем диапазон ячеек во
всей области.
Например:
Range («B3»). CurrentRegion вернет диапазон B3:D14
Range («D14»). CurrentRegion вернет диапазон B3:D14
Range («C8:C9»). CurrentRegion вернет диапазон B3:D14 и так далее
Как пользоваться
Мы получаем CurrentRegion следующим образом
' CurrentRegion вернет B3:D14 из приведенного выше примера Dim rg As Range Set rg = Sheet1.Range("B3").CurrentRegion
Только чтение строк данных
Прочитать диапазон из второй строки, т.е. пропустить строку заголовка.
' CurrentRegion вернет B3:D14 из приведенного выше примера Dim rg As Range Set rg = Sheet1.Range("B3").CurrentRegion ' Начало в строке 2 - строка после заголовка Dim i As Long For i = 2 To rg.Rows.Count ' текущая строка, столбец 1 диапазона Debug.Print rg.Cells(i, 1).Value2 Next i
Удалить заголовок
Удалить строку заголовка (т.е. первую строку) из диапазона. Например, если диапазон — A1:D4, это возвратит A2:D4
' CurrentRegion вернет B3:D14 из приведенного выше примера Dim rg As Range Set rg = Sheet1.Range("B3").CurrentRegion ' Удалить заголовок Set rg = rg.Resize(rg.Rows.Count - 1).Offset(1) ' Начните со строки 1, так как нет строки заголовка Dim i As Long For i = 1 To rg.Rows.Count ' текущая строка, столбец 1 диапазона Debug.Print rg.Cells(i, 1).Value2 Next i
Использование Rows и Columns в качестве Ranges
Если вы хотите что-то сделать со всей строкой или столбцом,
вы можете использовать свойство «Rows и
Columns» на рабочем листе. Они оба принимают один параметр — номер строки
или столбца, к которому вы хотите получить доступ.
Sub IspRowIColumns() ' Установите размер шрифта столбца B на 9 Sheet1.Columns(2).Font.Size = 9 ' Установите ширину столбцов от D до F Sheet1.Columns("D:F").ColumnWidth = 4 ' Установите размер шрифта строки 5 до 18 Sheet1.Rows(5).Font.Size = 18 End Sub
Использование Range вместо Worksheet
Вы также можете использовать Cella, Rows и Columns, как часть Range, а не как часть Worksheet. У вас может быть особая необходимость в этом, но в противном случае я бы избегал практики. Это делает код более сложным. Простой код — твой друг. Это уменьшает вероятность ошибок.
Код ниже выделит второй столбец диапазона полужирным. Поскольку диапазон имеет только две строки, весь столбец считается B1:B2
Sub IspColumnsVRange() ' Это выделит B1 и B2 жирным шрифтом. Sheet1.Range("A1:C2").Columns(2).Font.Bold = True End Sub
Чтение значений из одной ячейки в другую
В большинстве примеров мы записали значения в ячейку. Мы
делаем это, помещая диапазон слева от знака равенства и значение для размещения
в ячейке справа. Для записи данных из одной ячейки в другую мы делаем то же
самое. Диапазон назначения идет слева, а диапазон источника — справа.
В следующем примере показано, как это сделать:
Sub ChitatZnacheniya() ' Поместите значение из B1 в A1 Sheet1.Range("A1").Value2 = Sheet1.Range("B1").Value2 ' Поместите значение из B3 в лист2 в ячейку A1 Sheet1.Range("A1").Value2 = Sheet2.Range("B3").Value2 ' Поместите значение от B1 в ячейки A1 до A5 Sheet1.Range("A1:A5").Value2 = Sheet1.Range("B1").Value2 ' Вам необходимо использовать свойство «Value», чтобы прочитать несколько ячеек Sheet1.Range("A1:A5").Value2 = Sheet1.Range("B1:B5").Value2 End Sub
Как видно из этого примера, невозможно читать из нескольких ячеек. Если вы хотите сделать это, вы можете использовать функцию копирования Range с параметром Destination.
Sub KopirovatZnacheniya() ' Сохранить диапазон копирования в переменной Dim rgCopy As Range Set rgCopy = Sheet1.Range("B1:B5") ' Используйте это для копирования из более чем одной ячейки rgCopy.Copy Destination:=Sheet1.Range("A1:A5") ' Вы можете вставить в несколько мест назначения rgCopy.Copy Destination:=Sheet1.Range("A1:A5,C2:C6") End Sub
Функция Copy копирует все, включая формат ячеек. Это тот же результат, что и ручное копирование и вставка выделения. Подробнее об этом вы можете узнать в разделе «Копирование и вставка ячеек»
Использование метода Range.Resize
При копировании из одного диапазона в другой с использованием присваивания (т.е. знака равенства) диапазон назначения должен быть того же размера, что и исходный диапазон.
Использование функции Resize позволяет изменить размер
диапазона до заданного количества строк и столбцов.
Например:
Sub ResizePrimeri() ' Печатает А1 Debug.Print Sheet1.Range("A1").Address ' Печатает A1:A2 Debug.Print Sheet1.Range("A1").Resize(2, 1).Address ' Печатает A1:A5 Debug.Print Sheet1.Range("A1").Resize(5, 1).Address ' Печатает A1:D1 Debug.Print Sheet1.Range("A1").Resize(1, 4).Address ' Печатает A1:C3 Debug.Print Sheet1.Range("A1").Resize(3, 3).Address End Sub
Когда мы хотим изменить наш целевой диапазон, мы можем
просто использовать исходный размер диапазона.
Другими словами, мы используем количество строк и столбцов
исходного диапазона в качестве параметров для изменения размера:
Sub Resize() Dim rgSrc As Range, rgDest As Range ' Получить все данные в текущей области Set rgSrc = Sheet1.Range("A1").CurrentRegion ' Получить диапазон назначения Set rgDest = Sheet2.Range("A1") Set rgDest = rgDest.Resize(rgSrc.Rows.Count, rgSrc.Columns.Count) rgDest.Value2 = rgSrc.Value2 End Sub
Мы можем сделать изменение размера в одну строку, если нужно:
Sub Resize2() Dim rgSrc As Range ' Получить все данные в ткущей области Set rgSrc = Sheet1.Range("A1").CurrentRegion With rgSrc Sheet2.Range("A1").Resize(.Rows.Count, .Columns.Count) = .Value2 End With End Sub
Чтение Value в переменные
Мы рассмотрели, как читать из одной клетки в другую. Вы также можете читать из ячейки в переменную. Переменная используется для хранения значений во время работы макроса. Обычно вы делаете это, когда хотите манипулировать данными перед тем, как их записать. Ниже приведен простой пример использования переменной. Как видите, значение элемента справа от равенства записывается в элементе слева от равенства.
Sub IspVar() ' Создайте Dim val As Integer ' Читать число из ячейки val = Sheet1.Range("A1").Value2 ' Добавить 1 к значению val = val + 1 ' Запишите новое значение в ячейку Sheet1.Range("A2").Value2 = val End Sub
Для чтения текста в переменную вы используете переменную
типа String.
Sub IspVarText() ' Объявите переменную типа string Dim sText As String ' Считать значение из ячейки sText = Sheet1.Range("A1").Value2 ' Записать значение в ячейку Sheet1.Range("A2").Value2 = sText End Sub
Вы можете записать переменную в диапазон ячеек. Вы просто
указываете диапазон слева, и значение будет записано во все ячейки диапазона.
Sub VarNeskol() ' Считать значение из ячейки Sheet1.Range("A1:B10").Value2 = 66 End Sub
Вы не можете читать из нескольких ячеек в переменную. Однако
вы можете читать массив, который представляет собой набор переменных. Мы
рассмотрим это в следующем разделе.
Как копировать и вставлять ячейки
Если вы хотите скопировать и вставить диапазон ячеек, вам не
нужно выбирать их. Это распространенная ошибка, допущенная новыми пользователями
VBA.
Вы можете просто скопировать ряд ячеек, как здесь:
Range("A1:B4").Copy Destination:=Range("C5")
При использовании этого метода копируется все — значения,
форматы, формулы и так далее. Если вы хотите скопировать отдельные элементы, вы
можете использовать свойство PasteSpecial
диапазона.
Работает так:
Range("A1:B4").Copy Range("F3").PasteSpecial Paste:=xlPasteValues Range("F3").PasteSpecial Paste:=xlPasteFormats Range("F3").PasteSpecial Paste:=xlPasteFormulas
В следующей таблице приведен полный список всех типов вставок.
Виды вставок |
xlPasteAll |
xlPasteAllExceptBorders |
xlPasteAllMergingConditionalFormats |
xlPasteAllUsingSourceTheme |
xlPasteColumnWidths |
xlPasteComments |
xlPasteFormats |
xlPasteFormulas |
xlPasteFormulasAndNumberFormats |
xlPasteValidation |
xlPasteValues |
xlPasteValuesAndNumberFormats |
Чтение диапазона ячеек в массив
Вы также можете скопировать значения, присвоив значение
одного диапазона другому.
Range("A3:Z3").Value2 = Range("A1:Z1").Value2
Значение диапазона в этом примере считается вариантом массива. Это означает, что вы можете легко читать из диапазона ячеек в массив. Вы также можете писать из массива в диапазон ячеек. Если вы не знакомы с массивами, вы можете проверить их в этой статье.
В следующем коде показан пример использования массива с
диапазоном.
Sub ChitatMassiv() ' Создать динамический массив Dim StudentMarks() As Variant ' Считать 26 значений в массив из первой строки StudentMarks = Range("A1:Z1").Value2 ' Сделайте что-нибудь с массивом здесь ' Запишите 26 значений в третью строку Range("A3:Z3").Value2 = StudentMarks End Sub
Имейте в виду, что массив, созданный для чтения, является
двумерным массивом. Это связано с тем, что электронная таблица хранит значения
в двух измерениях, то есть в строках и столбцах.
Пройти через все клетки в диапазоне
Иногда вам нужно просмотреть каждую ячейку, чтобы проверить значение.
Вы можете сделать это, используя цикл For Each, показанный в следующем коде.
Sub PeremeschatsyaPoYacheikam() ' Пройдите через каждую ячейку в диапазоне Dim rg As Range For Each rg In Sheet1.Range("A1:A10,A20") ' Распечатать адрес ячеек, которые являются отрицательными If rg.Value < 0 Then Debug.Print rg.Address + " Отрицательно." End If Next End Sub
Вы также можете проходить последовательные ячейки, используя
свойство Cells и стандартный цикл For.
Стандартный цикл более гибок в отношении используемого вами
порядка, но он медленнее, чем цикл For Each.
Sub PerehodPoYacheikam() ' Пройдите клетки от А1 до А10 Dim i As Long For i = 1 To 10 ' Распечатать адрес ячеек, которые являются отрицательными If Range("A" & i).Value < 0 Then Debug.Print Range("A" & i).Address + " Отрицательно." End If Next ' Пройдите в обратном порядке, то есть от A10 до A1 For i = 10 To 1 Step -1 ' Распечатать адрес ячеек, которые являются отрицательными If Range("A" & i) < 0 Then Debug.Print Range("A" & i).Address + " Отрицательно." End If Next End Sub
Форматирование ячеек
Иногда вам нужно будет отформатировать ячейки в электронной
таблице. Это на самом деле очень просто. В следующем примере показаны различные
форматы, которые можно добавить в любой диапазон ячеек.
Sub FormatirovanieYacheek() With Sheet1 ' Форматировать шрифт .Range("A1").Font.Bold = True .Range("A1").Font.Underline = True .Range("A1").Font.Color = rgbNavy ' Установите числовой формат до 2 десятичных знаков .Range("B2").NumberFormat = "0.00" ' Установите числовой формат даты .Range("C2").NumberFormat = "dd/mm/yyyy" ' Установите формат чисел на общий .Range("C3").NumberFormat = "Общий" ' Установить числовой формат текста .Range("C4").NumberFormat = "Текст" ' Установите цвет заливки ячейки .Range("B3").Interior.Color = rgbSandyBrown ' Форматировать границы .Range("B4").Borders.LineStyle = xlDash .Range("B4").Borders.Color = rgbBlueViolet End With End Sub
Основные моменты
Ниже приводится краткое изложение основных моментов
- Range возвращает диапазон ячеек
- Cells возвращают только одну клетку
- Вы можете читать из одной ячейки в другую
- Вы можете читать из диапазона ячеек в другой диапазон ячеек.
- Вы можете читать значения из ячеек в переменные и наоборот.
- Вы можете читать значения из диапазонов в массивы и наоборот
- Вы можете использовать цикл For Each или For, чтобы проходить через каждую ячейку в диапазоне.
- Свойства Rows и Columns позволяют вам получить доступ к диапазону ячеек этих типов
Excel VBA Cells Function
Cells are one type of element in excel VBA. (Three elements of excel is Workbooks, Worksheets and Ranges/Cells)
Hierarchical between these elements or object will be:
Basic Structure For Referring a Cell
Excel VBA allows you to refer to cells in many different ways, cells refers to single cells only. (Note: it can’t refer to multiple cells like Range (“A2:E7”)
It is used for referencing a cell object e.g. it can be written as Cells (6, 5) for referring a cell “F5” where 6 is the column number & 5 is the row number Cells takes row & column number as an argument, cells are located within the range object With the help of cells in VBA, we can perform three important tasks, i.e. we can
- Read content from a cell
- Write a value to a cell
- Change the format of a cell
Difference between range & cells in VBA is Cells usually refer to a single cell at a time, while Range references a group of cells. The cell is a property of range in excel sheet, which is a characteristic, where it is used to describe a range Cells only returns one cell which is used to represent cells within a range of the worksheet.
This cells property is used to specify a single cell or all cells on the worksheet, where it returns a single cell in the Cells collection.
Syntax of VBA Cells in Excel
The syntax for VBA cells function in excel is as follows:
Cells argument will consider two numeric arguments to represent row & column, where the first one is for representing row number & and the second or last one referring to as column number.
Row Index: Which is row number which we are referring to.
Column Index: Which is column number which we are referring to.
Note: Either numbers or letters can be used to specify the Column index in CELLS E.G. Cells (5, “E”)
Comma (,): Separator between them is the union operator, which is used to combine several range of cells.
Expression = Cells (4, 2) indicates it is “B4” Cell on an active worksheet in row 4 and col 2
OR
Expression = Cells (4, “E”) indicates it is “B4” Cell on an active worksheet in row 4 and col 2
Above either of the code can be used to
Difference between Cell & Range syntax VBA code
To select cell B4 on the active worksheet, you can use either of the following examples:
ActiveSheet.Cells(4, 2).Select
or
ActiveSheet.Range(“B4”).Select
How to Use VBA Cells in Excel?
We will learn how to use VBA cells function with a few examples in excel.
You can download this VBA Cells Excel Template here – VBA Cells Excel Template
Example #1 – VBA Cells
Step 1: Select or click on Visual Basic in the Code group on the Developer tab or you can directly click on Alt + F11 shortcut key.
Step 2: To create a blank module, right-click on Microsoft excel objects, in that click on Insert and under the menu section select Module, where the blank module gets created.
Step 3: Double click on it, it is also called a code window, where you need to type Sub Cells_Example1() as the first message without any quotes around it. Now, you can observe, Excel automatically adds the line End Sub below the first message line when you press Enter.
Code:
Sub Cells_Example1() End Sub
Step 4: Now, all the codes which you enter must be between these two lines, Now you can start typing CELLS VBA code or syntax. Before typing code, enter CTRL + SPACE where VBA Intellisense Drop-down Menu appears, which helps you out in writing the code & you can autocomplete words in the VB editor.
The dropdown contains a list of all the members of the VB OBJECT MODEL active reference (i.e. includes objects, properties, variables, methods, and constants). This feature helps out in saving time & prevent misspell the words or typo-error.
Step 5: After typing cells, click on the tab key to select it.
Code:
Sub Cells_Example1() Cells End Sub
Step 6: Once you leave a space and enter open bracket “(”, CELLS argument will appear where it considers two numeric arguments to represent row & column index, where the first one is for representing row number & and the second or last one referring to as column number.
Code:
Sub Cells_Example1() Cells( End Sub
Step 7: Now, I enter the row index number as “4” & column index as “2” and close the bracket. Full stop and enter one space by clicking on the spacebar, now the cells argument is ready. And I want value in it. So, I enter again enter CTRL + SPACE where VBA Intellisense Drop-down Menu appears, type “Val” which means value.
Code:
Sub Cells_Example1() Cells(4, 2). Val End Sub
Step 8: Suppose you want “HI” to appear in that cell. For that, you need to type = “HI”. and click enter.
Code:
Sub Cells_Example1() Cells(4, 2).Value = "Hi" End Sub
Step 9: Now, the code is ready, you can run the macro by clicking the Run Sub button (i.e. green “play” button) or by pressing F5. You can observe “Hi” appears in the cell “B4”
Things to Remember
- Only one cell can be referred at a time with the help of Cells property.
- Cell property is very significant & useful in a programming loop.
- If you missed out or don’t specify a worksheet (by its name in VBA code), Excel considers or assumes the ACTIVE Sheet in a workbook.
- If you missed out or don’t specify row and column index argument, then Excel will refer to all cells on the worksheet. E.g. Cells is the syntax for all cells on the Active Sheet.
- You can combine cells with range together to define a starting & ending pint of a range with variables.
Recommended Articles
This is a guide to VBA Cells. Here we discuss how to use Excel VBA Cells Function along with practical examples and downloadable excel template. You can also go through our other suggested articles –
- VBA Web Scraping
- VBA XML
- VBA Subscript out of Range
- VBA IsError
In this Article
- Ranges and Cells in VBA
- Cell Address
- Range of Cells
- Writing to Cells
- Reading from Cells
- Non Contiguous Cells
- Intersection of Cells
- Offset from a Cell or Range
- Setting Reference to a Range
- Resize a Range
- OFFSET vs Resize
- All Cells in Sheet
- UsedRange
- CurrentRegion
- Range Properties
- Last Cell in Sheet
- Last Used Row Number in a Column
- Last Used Column Number in a Row
- Cell Properties
- Copy and Paste
- AutoFit Contents
- More Range Examples
- For Each
- Sort
- Find
- Range Address
- Range to Array
- Array to Range
- Sum Range
- Count Range
Ranges and Cells in VBA
Excel spreadsheets store data in Cells. Cells are arranged into Rows and Columns. Each cell can be identified by the intersection point of it’s row and column (Exs. B3 or R3C2).
An Excel Range refers to one or more cells (ex. A3:B4)
Cell Address
A1 Notation
In A1 notation, a cell is referred to by it’s column letter (from A to XFD) followed by it’s row number(from 1 to 1,048,576). This is called a cell address.
In VBA you can refer to any cell using the Range Object.
' Refer to cell B4 on the currently active sheet
MsgBox Range("B4")
' Refer to cell B4 on the sheet named 'Data'
MsgBox Worksheets("Data").Range("B4")
' Refer to cell B4 on the sheet named 'Data' in another OPEN workbook
' named 'My Data'
MsgBox Workbooks("My Data").Worksheets("Data").Range("B4")
R1C1 Notation
In R1C1 Notation a cell is referred by R followed by Row Number then letter ‘C’ followed by the Column Number. eg B4 in R1C1 notation will be referred by R4C2. In VBA you use the Cells Object to use R1C1 notation:
' Refer to cell R[6]C[4] i.e D6
Cells(6, 4) = "D6"
Range of Cells
A1 Notation
To refer to a more than one cell use a “:” between the starting cell address and last cell address. The following will refer to all the cells from A1 to D10:
Range("A1:D10")
R1C1 Notation
To refer to a more than one cell use a “,” between the starting cell address and last cell address. The following will refer to all the cells from A1 to D10:
Range(Cells(1, 1), Cells(10, 4))
Writing to Cells
To write values to a cell or contiguous group of cells, simple refer to the range, put an = sign and then write the value to be stored:
' Store F5 in cell with Address F6
Range("F6") = "F6"
' Store E6 in cell with Address R[6]C[5] i.e E6
Cells(6, 5) = "E6"
' Store A1:D10 in the range A1:D10
Range("A1:D10") = "A1:D10"
' or
Range(Cells(1, 1), Cells(10, 4)) = "A1:D10"
Reading from Cells
To read values from cells, simple refer to the variable to store the values, put an = sign and then refer to the range to be read:
Dim val1
Dim val2
' Read from cell F6
val1 = Range("F6")
' Read from cell E6
val2 = Cells(6, 5)
MsgBox val1
Msgbox val2
Note: To store values from a range of cells, you need to use an Array instead of a simple variable.
Non Contiguous Cells
To refer to non contiguous cells use a comma between the cell addresses:
' Store 10 in cells A1, A3, and A5
Range("A1,A3,A5") = 10
' Store 10 in cells A1:A3 and D1:D3)
Range("A1:A3, D1:D3") = 10
VBA Coding Made Easy
Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
Learn More
Intersection of Cells
To refer to non contiguous cells use a space between the cell addresses:
' Store 'Col D' in D1:D10
' which is Common between A1:D10 and D1:F10
Range("A1:D10 D1:G10") = "Col D"
Offset from a Cell or Range
Using the Offset function, you can move the reference from a given Range (cell or group of cells) by the specified number_of_rows, and number_of_columns.
Offset Syntax
Range.Offset(number_of_rows, number_of_columns)
Offset from a cell
' OFFSET from a cell A1
' Refer to cell itself
' Move 0 rows and 0 columns
Range("A1").Offset(0, 0) = "A1"
' Move 1 rows and 0 columns
Range("A1").Offset(1, 0) = "A2"
' Move 0 rows and 1 columns
Range("A1").Offset(0, 1) = "B1"
' Move 1 rows and 1 columns
Range("A1").Offset(1, 1) = "B2"
' Move 10 rows and 5 columns
Range("A1").Offset(10, 5) = "F11"
Offset from a Range
' Move Reference to Range A1:D4 by 4 rows and 4 columns
' New Reference is E5:H8
Range("A1:D4").Offset(4,4) = "E5:H8"
Setting Reference to a Range
To assign a range to a range variable: declare a variable of type Range then use the Set command to set it to a range. Please note that you must use the SET command as RANGE is an object:
' Declare a Range variable
Dim myRange as Range
' Set the variable to the range A1:D4
Set myRange = Range("A1:D4")
' Prints $A$1:$D$4
MsgBox myRange.Address
VBA Programming | Code Generator does work for you!
Resize a Range
Resize method of Range object changes the dimension of the reference range:
Dim myRange As Range
' Range to Resize
Set myRange = Range("A1:F4")
' Prints $A$1:$E$10
Debug.Print myRange.Resize(10, 5).Address
Top-left cell of the Resized range is same as the top-left cell of the original range
Resize Syntax
Range.Resize(number_of_rows, number_of_columns)
OFFSET vs Resize
Offset does not change the dimensions of the range but moves it by the specified number of rows and columns. Resize does not change the position of the original range but changes the dimensions to the specified number of rows and columns.
All Cells in Sheet
The Cells object refers to all the cells in the sheet (1048576 rows and 16384 columns).
' Clear All Cells in Worksheets
Cells.Clear
UsedRange
UsedRange property gives you the rectangular range from the top-left cell used cell to the right-bottom used cell of the active sheet.
Dim ws As Worksheet
Set ws = ActiveSheet
' $B$2:$L$14 if L2 is the first cell with any value
' and L14 is the last cell with any value on the
' active sheet
Debug.Print ws.UsedRange.Address
CurrentRegion
CurrentRegion property gives you the contiguous rectangular range from the top-left cell to the right-bottom used cell containing the referenced cell/range.
Dim myRange As Range
Set myRange = Range("D4:F6")
' Prints $B$2:$L$14
' If there is a filled path from D4:F16 to B2 AND L14
Debug.Print myRange.CurrentRegion.Address
' You can refer to a single starting cell also
Set myRange = Range("D4") ' Prints $B$2:$L$14
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
Range Properties
You can get Address, row/column number of a cell, and number of rows/columns in a range as given below:
Dim myRange As Range
Set myRange = Range("A1:F10")
' Prints $A$1:$F$10
Debug.Print myRange.Address
Set myRange = Range("F10")
' Prints 10 for Row 10
Debug.Print myRange.Row
' Prints 6 for Column F
Debug.Print myRange.Column
Set myRange = Range("E1:F5")
' Prints 5 for number of Rows in range
Debug.Print myRange.Rows.Count
' Prints 2 for number of Columns in range
Debug.Print myRange.Columns.Count
Last Cell in Sheet
You can use Rows.Count and Columns.Count properties with Cells object to get the last cell on the sheet:
' Print the last row number
' Prints 1048576
Debug.Print "Rows in the sheet: " & Rows.Count
' Print the last column number
' Prints 16384
Debug.Print "Columns in the sheet: " & Columns.Count
' Print the address of the last cell
' Prints $XFD$1048576
Debug.Print "Address of Last Cell in the sheet: " & Cells(Rows.Count, Columns.Count)
Last Used Row Number in a Column
END property takes you the last cell in the range, and End(xlUp) takes you up to the first used cell from that cell.
Dim lastRow As Long
lastRow = Cells(Rows.Count, "A").End(xlUp).Row
Last Used Column Number in a Row
Dim lastCol As Long
lastCol = Cells(1, Columns.Count).End(xlToLeft).Column
END property takes you the last cell in the range, and End(xlToLeft) takes you left to the first used cell from that cell.
You can also use xlDown and xlToRight properties to navigate to the first bottom or right used cells of the current cell.
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
Cell Properties
Common Properties
Here is code to display commonly used Cell Properties
Dim cell As Range
Set cell = Range("A1")
cell.Activate
Debug.Print cell.Address
' Print $A$1
Debug.Print cell.Value
' Prints 456
' Address
Debug.Print cell.Formula
' Prints =SUM(C2:C3)
' Comment
Debug.Print cell.Comment.Text
' Style
Debug.Print cell.Style
' Cell Format
Debug.Print cell.DisplayFormat.NumberFormat
Cell Font
Cell.Font object contains properties of the Cell Font:
Dim cell As Range
Set cell = Range("A1")
' Regular, Italic, Bold, and Bold Italic
cell.Font.FontStyle = "Bold Italic"
' Same as
cell.Font.Bold = True
cell.Font.Italic = True
' Set font to Courier
cell.Font.FontStyle = "Courier"
' Set Font Color
cell.Font.Color = vbBlue
' or
cell.Font.Color = RGB(255, 0, 0)
' Set Font Size
cell.Font.Size = 20
Copy and Paste
Paste All
Ranges/Cells can be copied and pasted from one location to another. The following code copies all the properties of source range to destination range (equivalent to CTRL-C and CTRL-V)
'Simple Copy
Range("A1:D20").Copy
Worksheets("Sheet2").Range("B10").Paste
'or
' Copy from Current Sheet to sheet named 'Sheet2'
Range("A1:D20").Copy destination:=Worksheets("Sheet2").Range("B10")
Paste Special
Selected properties of the source range can be copied to the destination by using PASTESPECIAL option:
' Paste the range as Values only
Range("A1:D20").Copy
Worksheets("Sheet2").Range("B10").PasteSpecial Paste:=xlPasteValues
Here are the possible options for the Paste option:
' Paste Special Types
xlPasteAll
xlPasteAllExceptBorders
xlPasteAllMergingConditionalFormats
xlPasteAllUsingSourceTheme
xlPasteColumnWidths
xlPasteComments
xlPasteFormats
xlPasteFormulas
xlPasteFormulasAndNumberFormats
xlPasteValidation
xlPasteValues
xlPasteValuesAndNumberFormats
AutoFit Contents
Size of rows and columns can be changed to fit the contents using AutoFit:
' Change size of rows 1 to 5 to fit contents
Rows("1:5").AutoFit
' Change size of Columns A to B to fit contents
Columns("A:B").AutoFit
More Range Examples
It is recommended that you use Macro Recorder while performing the required action through the GUI. It will help you understand the various options available and how to use them.
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
For Each
It is easy to loop through a range using For Each construct as show below:
For Each cell In Range("A1:B100")
' Do something with the cell
Next cell
At each iteration of the loop one cell in the range is assigned to the variable cell and statements in the For loop are executed for that cell. Loop exits when all the cells are processed.
Sort
Sort is a method of Range object. You can sort a range by specifying options for sorting to Range.Sort. The code below will sort the columns A:C based on key in cell C2. Sort Order can be xlAscending or xlDescending. Header:= xlYes should be used if first row is the header row.
Columns("A:C").Sort key1:=Range("C2"), _
order1:=xlAscending, Header:=xlYes
Find
Find is also a method of Range Object. It find the first cell having content matching the search criteria and returns the cell as a Range object. It return Nothing if there is no match.
Use FindNext method (or FindPrevious) to find next(previous) occurrence.
Following code will change the font to “Arial Black” for all cells in the range which start with “John”:
For Each c In Range("A1:A100")
If c Like "John*" Then
c.Font.Name = "Arial Black"
End If
Next c
Following code will replace all occurrences of “To Test” to “Passed” in the range specified:
With Range("a1:a500")
Set c = .Find("To Test", LookIn:=xlValues)
If Not c Is Nothing Then
firstaddress = c.Address
Do
c.Value = "Passed"
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstaddress
End If
End With
It is important to note that you must specify a range to use FindNext. Also you must provide a stopping condition otherwise the loop will execute forever. Normally address of the first cell which is found is stored in a variable and loop is stopped when you reach that cell again. You must also check for the case when nothing is found to stop the loop.
Range Address
Use Range.Address to get the address in A1 Style
MsgBox Range("A1:D10").Address
' or
Debug.Print Range("A1:D10").Address
Use xlReferenceStyle (default is xlA1) to get addres in R1C1 style
MsgBox Range("A1:D10").Address(ReferenceStyle:=xlR1C1)
' or
Debug.Print Range("A1:D10").Address(ReferenceStyle:=xlR1C1)
This is useful when you deal with ranges stored in variables and want to process for certain addresses only.
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
Range to Array
It is faster and easier to transfer a range to an array and then process the values. You should declare the array as Variant to avoid calculating the size required to populate the range in the array. Array’s dimensions are set to match number of values in the range.
Dim DirArray As Variant
' Store the values in the range to the Array
DirArray = Range("a1:a5").Value
' Loop to process the values
For Each c In DirArray
Debug.Print c
Next
Array to Range
After processing you can write the Array back to a Range. To write the Array in the example above to a Range you must specify a Range whose size matches the number of elements in the Array.
Use the code below to write the Array to the range D1:D5:
Range("D1:D5").Value = DirArray
Range("D1:H1").Value = Application.Transpose(DirArray)
Please note that you must Transpose the Array if you write it to a row.
Sum Range
SumOfRange = Application.WorksheetFunction.Sum(Range("A1:A10"))
Debug.Print SumOfRange
You can use many functions available in Excel in your VBA code by specifying Application.WorkSheetFunction. before the Function Name as in the example above.
Count Range
' Count Number of Cells with Numbers in the Range
CountOfCells = Application.WorksheetFunction.Count(Range("A1:A10"))
Debug.Print CountOfCells
' Count Number of Non Blank Cells in the Range
CountOfNonBlankCells = Application.WorksheetFunction.CountA(Range("A1:A10"))
Debug.Print CountOfNonBlankCells
Written by: Vinamra Chandra
Всё о работе с ячейками в Excel-VBA: обращение, перебор, удаление, вставка, скрытие, смена имени.
Содержание:
Table of Contents:
- Что такое ячейка Excel?
- Способы обращения к ячейкам
- Выбор и активация
- Получение и изменение значений ячеек
- Ячейки открытой книги
- Ячейки закрытой книги
- Перебор ячеек
- Перебор в произвольном диапазоне
- Свойства и методы ячеек
- Имя ячейки
- Адрес ячейки
- Размеры ячейки
- Запуск макроса активацией ячейки
2 нюанса:
- Я почти везде стараюсь использовать ThisWorkbook (а не, например, ActiveWorkbook) для обращения к текущей книге, в которой написан этот код (считаю это наиболее безопасным для новичков способом обращения к книгам, чтобы случайно не внести изменения в другие книги). Для экспериментов можете вставлять этот код в модули, коды книги, либо листа, и он будет работать только в пределах этой книги.
- Я использую английский эксель и у меня по стандарту листы называются Sheet1, Sheet2 и т.д. Если вы работаете в русском экселе, то замените Thisworkbook.Sheets(«Sheet1») на Thisworkbook.Sheets(«Лист1»). Если этого не сделать, то вы получите ошибку в связи с тем, что пытаетесь обратиться к несуществующему объекту. Можно также заменить на Thisworkbook.Sheets(1), но это менее безопасно.
Что такое ячейка Excel?
В большинстве мест пишут: «элемент, образованный пересечением столбца и строки». Это определение полезно для людей, которые не знакомы с понятием «таблица». Для того, чтобы понять чем на самом деле является ячейка Excel, необходимо заглянуть в объектную модель Excel. При этом определения объектов «ряд», «столбец» и «ячейка» будут отличаться в зависимости от того, как мы работаем с файлом.
Объекты в Excel-VBA. Пока мы работаем в Excel без углубления в VBA определение ячейки как «пересечения» строк и столбцов нам вполне хватает, но если мы решаем как-то автоматизировать процесс в VBA, то о нём лучше забыть и просто воспринимать лист как «мешок» ячеек, с каждой из которых VBA позволяет работать как минимум тремя способами:
- по цифровым координатам (ряд, столбец),
- по адресам формата А1, B2 и т.д. (сценарий целесообразности данного способа обращения в VBA мне сложно представить)
- по уникальному имени (во втором и третьем вариантах мы будем иметь дело не совсем с ячейкой, а с объектом VBA range, который может состоять из одной или нескольких ячеек). Функции и методы объектов Cells и Range отличаются. Новичкам я бы порекомендовал работать с ячейками VBA только с помощью Cells и по их цифровым координатам и использовать Range только по необходимости.
Все три способа обращения описаны далее
Как это хранится на диске и как с этим работать вне Excel? С точки зрения хранения и обработки вне Excel и VBA. Сделать это можно, например, сменив расширение файла с .xls(x) на .zip и открыв этот архив.
Пример содержимого файла Excel:
Далее xl -> worksheets и мы видим файл листа
Содержимое файла:
То же, но более наглядно:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac xr xr2 xr3" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision" xmlns:xr2="http://schemas.microsoft.com/office/spreadsheetml/2015/revision2" xmlns:xr3="http://schemas.microsoft.com/office/spreadsheetml/2016/revision3" xr:uid="{00000000-0001-0000-0000-000000000000}">
<dimension ref="B2:F6"/>
<sheetViews>
<sheetView tabSelected="1" workbookViewId="0">
<selection activeCell="D12" sqref="D12"/>
</sheetView>
</sheetViews>
<sheetFormatPr defaultRowHeight="14.4" x14ac:dyDescent="0.3"/>
<sheetData>
<row r="2" spans="2:6" x14ac:dyDescent="0.3">
<c r="B2" t="s">
<v>0</v>
</c>
</row>
<row r="3" spans="2:6" x14ac:dyDescent="0.3">
<c r="C3" t="s">
<v>1</v>
</c>
</row>
<row r="4" spans="2:6" x14ac:dyDescent="0.3">
<c r="D4" t="s">
<v>2</v>
</c>
</row>
<row r="5" spans="2:6" x14ac:dyDescent="0.3">
<c r="E5" t="s">
<v>0</v></c>
</row>
<row r="6" spans="2:6" x14ac:dyDescent="0.3">
<c r="F6" t="s"><v>3</v>
</c></row>
</sheetData>
<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>
</worksheet>
Как мы видим, в структуре объектной модели нет никаких «пересечений». Строго говоря рабочая книга — это архив структурированных данных в формате XML. При этом в каждую «строку» входит «столбец», и в нём в свою очередь прописан номер значения данного столбца, по которому оно подтягивается из другого XML файла при открытии книги для экономии места за счёт отсутствия повторяющихся значений. Почему это важно. Если мы захотим написать какой-то обработчик таких файлов, который будет напрямую редактировать данные в этих XML, то ориентироваться надо на такую модель и структуру данных. И правильное определение будет примерно таким: ячейка — это объект внутри столбца, который в свою очередь находится внутри строки в файле xml, в котором хранятся данные о содержимом листа.
Способы обращения к ячейкам
Выбор и активация
Почти во всех случаях можно и стоит избегать использования методов Select и Activate. На это есть две причины:
- Это лишь имитация действий пользователя, которая замедляет выполнение программы. Работать с объектами книги можно напрямую без использования методов Select и Activate.
- Это усложняет код и может приводить к неожиданным последствиям. Каждый раз перед использованием Select необходимо помнить, какие ещё объекты были выбраны до этого и не забывать при необходимости снимать выбор. Либо, например, в случае использования метода Select в самом начале программы может быть выбрано два листа вместо одного потому что пользователь запустил программу, выбрав другой лист.
Можно выбирать и активировать книги, листы, ячейки, фигуры, диаграммы, срезы, таблицы и т.д.
Отменить выбор ячеек можно методом Unselect:
Selection.Unselect
Отличие выбора от активации — активировать можно только один объект из раннее выбранных. Выбрать можно несколько объектов.
Если вы записали и редактируете код макроса, то лучше всего заменить Select и Activate на конструкцию With … End With. Например, предположим, что мы записали вот такой макрос:
Sub Macro1()
' Macro1 Macro
Range("F4:F10,H6:H10").Select 'выбрали два несмежных диапазона зажав ctrl
Range("H6").Activate 'показывает только то, что я начал выбирать второй диапазон с этой ячейки (она осталась белой). Это действие ни на что не влияет
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535 'залили желтым цветом, нажав на кнопку заливки на верхней панели
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
Почему макрос записался таким неэффективным образом? Потому что в каждый момент времени (в каждой строке) программа не знает, что вы будете делать дальше. Поэтому в записи выбор ячеек и действия с ними — это два отдельных действия. Этот код лучше всего оптимизировать (особенно если вы хотите скопировать его внутрь какого-нибудь цикла, который должен будет исполняться много раз и перебирать много объектов). Например, так:
Sub Macro11()
'
' Macro1 Macro
Range("F4:F10,H6:H10").Select '1. смотрим, что за объект выбран (что идёт до .Select)
Range("H6").Activate
With Selection.Interior '2. понимаем, что у выбранного объекта есть свойство interior, с которым далее идёт работа
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
Sub Optimized_Macro()
With Range("F4:F10,H6:H10").Interior '3. переносим объект напрямую в конструкцию With вместо Selection
' ////// Здесь я для надёжности прописал бы ещё Thisworkbook.Sheet("ИмяЛиста") перед Range,
' ////// чтобы минимизировать риск любых случайных изменений других листов и книг
' ////// With Thisworkbook.Sheet("ИмяЛиста").Range("F4:F10,H6:H10").Interior
.Pattern = xlSolid '4. полностью копируем всё, что было записано рекордером внутрь блока with
.PatternColorIndex = xlAutomatic
.Color = 55555 '5. здесь я поменял цвет на зеленый, чтобы было видно, работает ли код при поочерёдном запуске двух макросов
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
Пример сценария, когда использование Select и Activate оправдано:
Допустим, мы хотим, чтобы во время исполнения программы мы одновременно изменяли несколько листов одним действием и пользователь видел какой-то определённый лист. Это можно сделать примерно так:
Sub Select_Activate_is_OK()
Thisworkbook.Worksheets(Array("Sheet1", "Sheet3")).Select 'Выбираем несколько листов по именам
Thisworkbook.Worksheets("Sheet3").Activate 'Показываем пользователю третий лист
'Далее все действия с выбранными ячейками через Select будут одновременно вносить изменения в оба выбранных листа
'Допустим, что тут мы решили покрасить те же два диапазона:
Range("F4:F10,H6:H10").Select
Range("H6").Activate
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
Единственной причиной использовать этот код по моему мнению может быть желание зачем-то показать пользователю определённую страницу книги в какой-то момент исполнения программы. С точки зрения обработки объектов, опять же, эти действия лишние.
Получение и изменение значений ячеек
Значение ячеек можно получать/изменять с помощью свойства value.
'Если нужно прочитать / записать значение ячейки, то используется свойство Value
a = ThisWorkbook.Sheets("Sheet1").Cells (1,1).Value 'записать значение ячейки А1 листа "Sheet1" в переменную "a"
ThisWorkbook.Sheets("Sheet1").Cells (1,1).Value = 1 'задать значение ячейки А1 (первый ряд, первый столбец) листа "Sheet1"
'Если нужно прочитать текст как есть (с форматированием), то можно использовать свойство .text:
ThisWorkbook.Sheets("Sheet1").Cells (1,1).Text = "1"
a = ThisWorkbook.Sheets("Sheet1").Cells (1,1).Text
'Когда проявится разница:
'Например, если мы считываем дату в формате "31 декабря 2021 г.", хранящуюся как дата
a = ThisWorkbook.Sheets("Sheet1").Cells (1,1).Value 'эапишет как "31.12.2021"
a = ThisWorkbook.Sheets("Sheet1").Cells (1,1).Text 'запишет как "31 декабря 2021 г."
Ячейки открытой книги
К ячейкам можно обращаться:
'В книге, в которой хранится макрос (на каком-то из листов, либо в отдельном модуле или форме)
ThisWorkbook.Sheets("Sheet1").Cells(1,1).Value 'По номерам строки и столбца
ThisWorkbook.Sheets("Sheet1").Cells(1,"A").Value 'По номерам строки и букве столбца
ThisWorkbook.Sheets("Sheet1").Range("A1").Value 'По адресу - вариант 1
ThisWorkbook.Sheets("Sheet1").[A1].Value 'По адресу - вариант 2
ThisWorkbook.Sheets("Sheet1").Range("CellName").Value 'По имени ячейки (для этого ей предварительно нужно его присвоить)
'Те же действия, но с использованием полного названия рабочей книги (книга должна быть открыта)
Workbooks("workbook.xlsm").Sheets("Sheet1").Cells(1,1).Value 'По номерам строки и столбца
Workbooks("workbook.xlsm").Sheets("Sheet1").Cells(1,"A").Value 'По номерам строки и букве столбца
Workbooks("workbook.xlsm").Sheets("Sheet1").Range("A1").Value 'По адресу - вариант 1
Workbooks("workbook.xlsm").Sheets("Sheet1").[A1].Value 'По адресу - вариант 2
Workbooks("workbook.xlsm").Sheets("Sheet1").Range("CellName").Value 'По имени ячейки (для этого ей предварительно нужно его присвоить)
Ячейки закрытой книги
Если нужно достать или изменить данные в другой закрытой книге, то необходимо прописать открытие и закрытие книги. Непосредственно работать с закрытой книгой не получится, потому что данные в ней хранятся отдельно от структуры и при открытии Excel каждый раз производит расстановку значений по соответствующим «слотам» в структуре. Подробнее о том, как хранятся данные в xlsx см выше.
Workbooks.Open Filename:="С:closed_workbook.xlsx" 'открыть книгу (она становится активной)
a = ActiveWorkbook.Sheets("Sheet1").Cells(1,1).Value 'достать значение ячейки 1,1
ActiveWorkbook.Close False 'закрыть книгу (False => без сохранения)
Скачать пример, в котором можно посмотреть, как доставать и как записывать значения в закрытую книгу.
Код из файла:
Option Explicit
Sub get_value_from_closed_wb() 'достать значение из закрытой книги
Dim a, wb_path, wsh As String
wb_path = ThisWorkbook.Sheets("Sheet1").Cells(2, 3).Value 'get path to workbook from sheet1
wsh = ThisWorkbook.Sheets("Sheet1").Cells(3, 3).Value
Workbooks.Open Filename:=wb_path
a = ActiveWorkbook.Sheets(wsh).Cells(3, 3).Value
ActiveWorkbook.Close False
ThisWorkbook.Sheets("Sheet1").Cells(4, 3).Value = a
End Sub
Sub record_value_to_closed_wb() 'записать значение в закрытую книгу
Dim wb_path, b, wsh As String
wsh = ThisWorkbook.Sheets("Sheet1").Cells(3, 3).Value
wb_path = ThisWorkbook.Sheets("Sheet1").Cells(2, 3).Value 'get path to workbook from sheet1
b = ThisWorkbook.Sheets("Sheet1").Cells(5, 3).Value 'get value to record in the target workbook
Workbooks.Open Filename:=wb_path
ActiveWorkbook.Sheets(wsh).Cells(4, 4).Value = b 'add new value to cell D4 of the target workbook
ActiveWorkbook.Close True
End Sub
Перебор ячеек
Перебор в произвольном диапазоне
Скачать файл со всеми примерами
Пройтись по всем ячейкам в нужном диапазоне можно разными способами. Основные:
- Цикл For Each. Пример:
Sub iterate_over_cells() For Each c In ThisWorkbook.Sheets("Sheet1").Range("B2:D4").Cells MsgBox (c) Next c End Sub
Этот цикл выведет в виде сообщений значения ячеек в диапазоне B2:D4 по порядку по строкам слева направо и по столбцам — сверху вниз. Данный способ можно использовать для действий, в который вам не важны номера ячеек (закрашивание, изменение форматирования, пересчёт чего-то и т.д.).
- Ту же задачу можно решить с помощью двух вложенных циклов — внешний будет перебирать ряды, а вложенный — ячейки в рядах. Этот способ я использую чаще всего, потому что он позволяет получить больше контроля над исполнением: на каждой итерации цикла нам доступны координаты ячеек. Для перебора всех ячеек на листе этим методом потребуется найти последнюю заполненную ячейку. Пример кода:
Sub iterate_over_cells() Dim cl, rw As Integer Dim x As Variant 'перебор области 3x3 For rw = 1 To 3 ' цикл для перебора рядов 1-3 For cl = 1 To 3 'цикл для перебора столбцов 1-3 x = ThisWorkbook.Sheets("Sheet1").Cells(rw + 1, cl + 1).Value MsgBox (x) Next cl Next rw 'перебор всех ячеек на листе. Последняя ячейка определена с помощью UsedRange 'LastRow = ActiveSheet.UsedRange.Row + ActiveSheet.UsedRange.Rows.Count - 1 'LastCol = ActiveSheet.UsedRange.Column + ActiveSheet.UsedRange.Columns.Count - 1 'For rw = 1 To LastRow 'цикл перебора всех рядов ' For cl = 1 To LastCol 'цикл для перебора всех столбцов ' Действия ' Next cl 'Next rw End Sub
- Если нужно перебрать все ячейки в выделенном диапазоне на активном листе, то код будет выглядеть так:
Sub iterate_cell_by_cell_over_selection() Dim ActSheet As Worksheet Dim SelRange As Range Dim cell As Range Set ActSheet = ActiveSheet Set SelRange = Selection 'if we want to do it in every cell of the selected range For Each cell In Selection MsgBox (cell.Value) Next cell End Sub
Данный метод подходит для интерактивных макросов, которые выполняют действия над выбранными пользователем областями.
- Перебор ячеек в ряду
Sub iterate_cells_in_row() Dim i, RowNum, StartCell As Long RowNum = 3 'какой ряд StartCell = 0 ' номер начальной ячейки (минус 1, т.к. в цикле мы прибавляем i) For i = 1 To 10 ' 10 ячеек в выбранном ряду ThisWorkbook.Sheets("Sheet1").Cells(RowNum, i + StartCell).Value = i '(i + StartCell) добавляет 1 к номеру столбца при каждом повторении Next i End Sub
- Перебор ячеек в столбце
Sub iterate_cells_in_column() Dim i, ColNum, StartCell As Long ColNum = 3 'какой столбец StartCell = 0 ' номер начальной ячейки (минус 1, т.к. в цикле мы прибавляем i) For i = 1 To 10 ' 10 ячеек ThisWorkbook.Sheets("Sheet1").Cells(i + StartCell, ColNum).Value = i ' (i + StartCell) добавляет 1 к номеру ряда при каждом повторении Next i End Sub
Свойства и методы ячеек
Имя ячейки
Присвоить новое имя можно так:
Thisworkbook.Sheets(1).Cells(1,1).name = "Новое_Имя"
Для того, чтобы сменить имя ячейки нужно сначала удалить существующее имя, а затем присвоить новое. Удалить имя можно так:
ActiveWorkbook.Names("Старое_Имя").Delete
Пример кода для переименования ячеек:
Sub rename_cell()
old_name = "Cell_Old_Name"
new_name = "Cell_New_Name"
ActiveWorkbook.Names(old_name).Delete
ThisWorkbook.Sheets(1).Cells(2, 1).Name = new_name
End Sub
Sub rename_cell_reverse()
old_name = "Cell_New_Name"
new_name = "Cell_Old_Name"
ActiveWorkbook.Names(old_name).Delete
ThisWorkbook.Sheets(1).Cells(2, 1).Name = new_name
End Sub
Адрес ячейки
Sub get_cell_address() ' вывести адрес ячейки в формате буква столбца, номер ряда
'$A$1 style
txt_address = ThisWorkbook.Sheets(1).Cells(3, 2).Address
MsgBox (txt_address)
End Sub
Sub get_cell_address_R1C1()' получить адрес столбца в формате номер ряда, номер столбца
'R1C1 style
txt_address = ThisWorkbook.Sheets(1).Cells(3, 2).Address(ReferenceStyle:=xlR1C1)
MsgBox (txt_address)
End Sub
'пример функции, которая принимает 2 аргумента: название именованного диапазона и тип желаемого адреса
'(1- тип $A$1 2- R1C1 - номер ряда, столбца)
Function get_cell_address_by_name(str As String, address_type As Integer)
'$A$1 style
Select Case address_type
Case 1
txt_address = Range(str).Address
Case 2
txt_address = Range(str).Address(ReferenceStyle:=xlR1C1)
Case Else
txt_address = "Wrong address type selected. 1,2 available"
End Select
get_cell_address_by_name = txt_address
End Function
'перед запуском нужно убедиться, что в книге есть диапазон с названием,
'адрес которого мы хотим получить, иначе будет ошибка
Sub test_function() 'запустите эту программу, чтобы увидеть, как работает функция
x = get_cell_address_by_name("MyValue", 2)
MsgBox (x)
End Sub
Размеры ячейки
Ширина и длина ячейки в VBA меняется, например, так:
Sub change_size()
Dim x, y As Integer
Dim w, h As Double
'получить координаты целевой ячейки
x = ThisWorkbook.Sheets("Sheet1").Cells(2, 2).Value
y = ThisWorkbook.Sheets("Sheet1").Cells(3, 2).Value
'получить желаемую ширину и высоту ячейки
w = ThisWorkbook.Sheets("Sheet1").Cells(6, 2).Value
h = ThisWorkbook.Sheets("Sheet1").Cells(7, 2).Value
'сменить высоту и ширину ячейки с координатами x,y
ThisWorkbook.Sheets("Sheet1").Cells(x, y).RowHeight = h
ThisWorkbook.Sheets("Sheet1").Cells(x, y).ColumnWidth = w
End Sub
Прочитать значения ширины и высоты ячеек можно двумя способами (однако результаты будут в разных единицах измерения). Если написать просто Cells(x,y).Width или Cells(x,y).Height, то будет получен результат в pt (привязка к размеру шрифта).
Sub get_size()
Dim x, y As Integer
'получить координаты ячейки, с которой мы будем работать
x = ThisWorkbook.Sheets("Sheet1").Cells(2, 2).Value
y = ThisWorkbook.Sheets("Sheet1").Cells(3, 2).Value
'получить длину и ширину выбранной ячейки в тех же единицах измерения, в которых мы их задавали
ThisWorkbook.Sheets("Sheet1").Cells(2, 6).Value = ThisWorkbook.Sheets("Sheet1").Cells(x, y).ColumnWidth
ThisWorkbook.Sheets("Sheet1").Cells(3, 6).Value = ThisWorkbook.Sheets("Sheet1").Cells(x, y).RowHeight
'получить длину и ширину с помощью свойств ячейки (только для чтения) в поинтах (pt)
ThisWorkbook.Sheets("Sheet1").Cells(7, 9).Value = ThisWorkbook.Sheets("Sheet1").Cells(x, y).Width
ThisWorkbook.Sheets("Sheet1").Cells(8, 9).Value = ThisWorkbook.Sheets("Sheet1").Cells(x, y).Height
End Sub
Скачать файл с примерами изменения и чтения размера ячеек
Запуск макроса активацией ячейки
Для запуска кода VBA при активации ячейки необходимо вставить в код листа нечто подобное:
3 важных момента, чтобы это работало:
1. Этот код должен быть вставлен в код листа (здесь контролируется диапазон D4)
2-3. Программа, ответственная за запуск кода при выборе ячейки, должна называться Worksheet_SelectionChange и должна принимать значение переменной Target, относящейся к триггеру SelectionChange. Другие доступные триггеры можно посмотреть в правом верхнем углу (2).
Скачать файл с базовым примером (как на картинке)
Скачать файл с расширенным примером (код ниже)
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' имеем в виду, что триггер SelectionChange будет запускать эту Sub после каждого клика мышью (после каждого клика будет проверяться:
'1. количество выделенных ячеек и
'2. не пересекается ли выбранный диапазон с заданным в этой программе диапазоном.
' поэтому в эту программу не стоит без необходимости писать никаких других тяжелых операций
If Selection.Count = 1 Then 'запускаем программу только если выбрано не более 1 ячейки
'вариант модификации - брать адрес ячейки из другой ячейки:
'Dim CellName as String
'CellName = Activesheet.Cells(1,1).value 'брать текстовое имя контролируемой ячейки из A1 (должно быть в формате Буква столбца + номер строки)
'If Not Intersect(Range(CellName), Target) Is Nothing Then
'для работы этой модификации следующую строку надо закомментировать/удалить
If Not Intersect(Range("D4"), Target) Is Nothing Then
'если заданный (D4) и выбранный диапазон пересекаются
'(пересечение диапазонов НЕ равно Nothing)
'можно прописать диапазон из нескольких ячеек:
'If Not Intersect(Range("D4:E10"), Target) Is Nothing Then
'можно прописать несколько диапазонов:
'If Not Intersect(Range("D4:E10"), Target) Is Nothing or Not Intersect(Range("A4:A10"), Target) Is Nothing Then
Call program 'выполняем программу
End If
End If
End Sub
Sub program()
MsgBox ("Program Is running") 'здесь пишем код того, что произойдёт при выборе нужной ячейки
End Sub