Заполнение ячеек в excel в цикле

godofwaaar

0 / 0 / 0

Регистрация: 10.11.2015

Сообщений: 2

1

23.12.2015, 16:26. Показов 22203. Ответов 3

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Ячейки в Excel данным способом почему-то не заполняются. Почему? Как это исправить?

Visual Basic
1
2
3
4
5
6
7
8
9
10
Sub t()
Dim teta As Double
teta = 0
 
For i = 1 To i = 10
    Cells(i, 1).Value = teta
    teta = teta + 0.25
Next i
 
End Sub



0



Казанский

15136 / 6410 / 1730

Регистрация: 24.09.2011

Сообщений: 9,999

23.12.2015, 16:44

2

Лучший ответ Сообщение было отмечено godofwaaar как решение

Решение

Цитата
Сообщение от godofwaaar
Посмотреть сообщение

For i = 1 To i = 10

Должно быть

Visual Basic
1
For i = 1 To 10



1



pashulka

4131 / 2235 / 940

Регистрация: 01.12.2010

Сообщений: 4,624

23.12.2015, 17:39

3

godofwaaar, В Excel эту задачу можно решить и без цикла, например :

Visual Basic
1
2
Range("A1") = 0
Range("A1:A10").DataSeries Step:=0.25
Visual Basic
1
[A1] = 0: [A1:A10].DataSeries Step:=0.25

P.S. Можно и менее очевидным способом :

Visual Basic
1
2
Range("A1:A10") = "=(ROW(A1:A10)-1)*0.25"
Range("A1:A10") = Range("A1:A10").Value

или даже так

Visual Basic
1
[A1:A10] = [(ROW(A1:A10)-1)*0.25] 'Only ReferenceStyle = xlA1
Visual Basic
1
2
3
4
With Range("A1:A10")
     .Value = Evaluate("(ROW( " & .Address(, , Application.ReferenceStyle, True) & ")-1)*0.25")
     '.Value = .Worksheet.Evaluate("(ROW( " & .Address(, , Application.ReferenceStyle) & ")-1)*0.25")
End With



2



0 / 0 / 0

Регистрация: 28.01.2016

Сообщений: 1

23.01.2020, 10:35

4

Круто!
Вот это я понимаю, глубочайшие познания в программировании!
Респект!



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

23.01.2020, 10:35

Помогаю со студенческими работами здесь

Заполнение ячеек
Здравия, форум!
Нужна помощь в экселе, я в бейсике полный ноль, так что заранее извините. Вобщем…

Заполнение ячеек
Отлавливаю ошибку и нужно реализовать такую последовательность:если хоть одна ячейка заполнена,то…

Макрос на заполнение ячеек
Добрый день, фоурмчане!
Необходима ваша неоценимая помощь и подсказ, как разобраться с заданием:

Заполнение диапазона ячеек
Еще вопрос.
Запросите у пользователя диапазон ячеек и заполните его случайными символами….

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:

4

 

kamlayka

Пользователь

Сообщений: 16
Регистрация: 24.10.2016

#1

02.03.2017 19:18:58

В общем, задача такая. Есть форма с одним textbox и кнопкой ок. При нажатии на кнопку нужно чтобы происходил цикл: если ячейка в столбце A не пустая, то в ячейке столбца U должно записаться значение из textbox, увеличенное на 1, в следующей ячейке на 2 и т.д.

Код
Private Sub CommandButton1_Click()
per = UserForm1.TextBox1.Value

For n = 2 To i
If IsEmpty(Cells(n, 1)) = False Then
per = per + 1
Cells(n, 21).Value = per
Else
Exit For
End If
Next n

End Sub

Подскажите, как это правильно оформить, пожалуйста.

Изменено: kamlayka06.03.2017 02:22:18

 

heso

Пользователь

Сообщений: 444
Регистрация: 14.08.2015

 

kamlayka

Пользователь

Сообщений: 16
Регистрация: 24.10.2016

#3

04.03.2017 11:45:34

Да ради бога)))

Код
Private Sub CommandButton1_Click() 
per = UserForm1.TextBox1.Value 

For n = 2 To i 
If IsEmpty(Cells(n, 1)) = False Then 
per = per + 1 
Cells(n, 21).Value = per 
Else 
Exit For 
End If 
Next n 

End Sub 
 

Юрий М

Модератор

Сообщений: 60580
Регистрация: 14.09.2012

Контакты см. в профиле

kamlayka, сделайте это (оформление кода) в стартовом сообщении.
По вопросу: где у Вас присваивается значение переменной i?
И обратите внимание на принудительный выход из цикла )

 

kamlayka

Пользователь

Сообщений: 16
Регистрация: 24.10.2016

Юрий М, ммм, а можете подсказать?
Во-первых, я не знаю, чему должно равняться значение i (по идее количеству не пустых ячеек в столбце А). Как вообще сделать цикл, который прерывается, если в ячейке (Cells(n, 1)) будет пусто?

 

kamlayka, Вам что то вроде такого надо ? Или я ошибаюсь ?

Изменено: Александр06.03.2017 04:35:29

 

kamlayka

Пользователь

Сообщений: 16
Регистрация: 24.10.2016

Александр, вы великолепны, благодарю!)

 

kamlayka

Пользователь

Сообщений: 16
Регистрация: 24.10.2016

Александр, можете еще немножко помочь? Не знаю, как сравнить первые 6 символов активной ячейки с предыдущей. Мне нужно сделать условие: если у активной ячейки совпадают первые 6 символов с предыдущей, тогда значение во втором столбце тоже берется из ячейки выше. Если нет — тогда Cl.Offset(0, 3).Value = per

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

 

Юрий М

Модератор

Сообщений: 60580
Регистрация: 14.09.2012

Контакты см. в профиле

#9

06.03.2017 23:16:48

Цитата
kamlayka написал:
Подскажите хотя бы функции
Код
If Left(ActiveCell, 6) = Left(ActiveCell.Offset(-1, 0), 6) Then ...
 

kamlayka, Не понимаю почему должно быть именно так, как в вашем примере, нелогично как то (было 5882 и следом 5889), но дело ваше.

 

kamlayka

Пользователь

Сообщений: 16
Регистрация: 24.10.2016

#11

08.03.2017 07:57:43

Александр, вы не совсем правильно меня поняли. Но на основе вашего макроса я сумела поправить свой. У меня остался только один вопрос, я не совсем понимаю действие Rng.Columns(1).SpecialCells(2). Rng.Columns(1) — это наш столбец А, а SpecialCells(2) — вторая ячейка что ли??

Код
Private Sub CommandButton1_Click()
Dim Cl As Range, Cl1 As Range, Rng As Range, per As Long
Application.ScreenUpdating = False
per = UserForm1.TextBox1.Value
Set Rng = ActiveSheet.UsedRange

For Each Cl In Rng.Columns(1).SpecialCells(2)
    per = per + 1
    Cl.Offset(0, 1).Value = per

If Left(Cl, 6) = LastCl Then
        Cl.Offset(0, 4).Value = Cl.Offset(-1, 4).Value

        Else
        Cl.Offset(0, 4).Value = per
        LastCl = Left(Cl, 6)
    End If

Next
Application.ScreenUpdating = True
Unload Me
End Sub
 

БМВ

Модератор

Сообщений: 21380
Регистрация: 28.12.2016

Excel 2013, 2016

kamlayka

. Есть действительно трюки и секреты, которые не отражаются в инструкциях и документации, но на 99% подобных вопросов ответит сайт производителя

Range.SpecialCells Method (Excel)

По вопросам из тем форума, личку не читаю.

 

kamlayka

Пользователь

Сообщений: 16
Регистрация: 24.10.2016

БМВ, теперь понятно, большое спасибо)

 

Александр

Пользователь

Сообщений: 1147
Регистрация: 16.03.2016

#14

08.03.2017 13:42:35

kamlayka,

Цитата
kamlayka написал:
вы не совсем правильно меня поняли.

Извините, как написали так и понял =)

Цитата
kamlayka написал:
Пример, как должно быть подкрепляю

Цикл For… Next в VBA Excel, его синтаксис и описание отдельных компонентов. Примеры использования цикла For… Next.

Цикл For… Next в VBA Excel предназначен для выполнения группы операторов необходимое количество раз, заданное управляющей переменной цикла — счетчиком. При выполнении цикла значение счетчика после каждой итерации увеличивается или уменьшается на число, указанное выражением оператора Step, или, по умолчанию, на единицу. Когда необходимо применить цикл к элементам, количество которых и индексация в группе (диапазон, массив, коллекция) неизвестны, следует использовать цикл For Each… Next.


For counter = start To end [ Step step ]

    [ statements ]

    [ Exit For ]

    [ statements ]

Next [ counter ]


For счетчик = начало To конец [ Step шаг ]

    [ операторы ]

    [ Exit For ]

    [ операторы ]

Next [ счетчик ]


В квадратных скобках указаны необязательные атрибуты цикла For… Next.

Компоненты цикла For… Next

Компонент Описание
counter Обязательный атрибут. Числовая переменная, выполняющая роль счетчика, которую еще называют управляющей переменной цикла.
start Обязательный атрибут. Числовое выражение, задающее начальное значение счетчика.
end Обязательный атрибут. Числовое выражение, задающее конечное значение счетчика.
Step* Необязательный атрибут. Оператор, указывающий, что будет задан шаг цикла.
step Необязательный атрибут. Числовое выражение, задающее шаг цикла. Может быть как положительным, так и отрицательным.
statements Необязательный** атрибут. Операторы вашего кода.
Exit For Необязательный атрибут. Оператор выхода из цикла до его окончания.
Next [ counter ] Здесь counter — необязательный атрибут. Это то же самое имя управляющей переменной цикла, которое можно здесь не указывать.

*Если атрибут Step отсутствует, цикл For… Next выполняется с шагом по умолчанию, равному 1.

**Если не использовать в цикле свой код, смысл применения цикла теряется.

Примеры циклов For… Next

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

Простейший цикл

Заполняем десять первых ячеек первого столбца активного листа Excel цифрами от 1 до 10:

Sub test1()

Dim i As Long

  For i = 1 To 10

    Cells(i, 1) = i

  Next

End Sub

Простейший цикл с шагом

В предыдущий цикл добавлен оператор Step со значением 3, а результаты записываем во второй столбец:

Sub test2()

Dim i As Long

  For i = 1 To 10 Step 3

    Cells(i, 2) = i

  Next

End Sub

Цикл с отрицательными аргументами

Этот цикл заполняет десять первых ячеек третьего столбца в обратной последовательности:

Sub test3()

Dim i As Long

  For i = 0 To 9 Step 1

    Cells(i + 10, 3) = i + 10

  Next

End Sub

Увеличиваем размер шага до -3 и записываем результаты в четвертый столбец активного листа Excel:

Sub test4()

Dim i As Long

  For i = 0 To 9 Step 3

    Cells(i + 10, 4) = i + 10

  Next

End Sub

Вложенный цикл

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

Sub test5()

Dim i1 As Long, i2 As Long

  For i1 = 1 To 10

‘Пятой ячейке в строке i1 присваиваем 0

    Cells(i1, 5) = 0

      For i2 = 1 To 4

        Cells(i1, 5) = Cells(i1, 5) + Cells(i1, i2)

      Next

  Next

End Sub

Выход из цикла

В шестой столбец активного листа запишем названия десяти животных, конечно же, с помощью цикла For… Next:

Sub test6()

Dim i As Long

  For i = 1 To 10

    Cells(i, 6) = Choose(i, «Медведь», «Слон», «Жираф», «Антилопа», _

    «Крокодил», «Зебра», «Тигр», «Ящерица», «Лев», «Бегемот»)

  Next

End Sub

Следующий цикл будет искать в шестом столбце крокодила, который съел галоши. В ячейку седьмого столбца цикл, пока не встретит крокодила, будет записывать строку «Здесь был цикл», а когда обнаружит крокодила, запишет «Он съел галоши» и прекратит работу, выполнив команду Exit For. Это будет видно по ячейкам рядом с названиями животных ниже крокодила, в которых не будет текста «Здесь был цикл».

Sub test7()

Dim i As Long

  For i = 1 To 10

    If Cells(i, 6) = «Крокодил» Then

      Cells(i, 7) = «Он съел галоши»

      Exit For

        Else

      Cells(i, 7) = «Здесь был цикл»

    End If

  Next

End Sub


Результат работы циклов For… Next из примеров:

Результат работы циклов For... Next из примеров

Результат работы циклов For… Next

Такие данные на активном листе Excel вы получите, если последовательно запустите на выполнение в редакторе VBA все семь подпрограмм из примеров, демонстрирующих работу циклов For… Next.

Цикл с дробными аргументами

Атрибуты start, end и step могут быть представлены числом, переменной или числовым выражением:

For i = 1 To 20 Step 2

For i = a To b Step c

For i = a 3 To 2b + 1 Step c/2  

В результате вычисления значения переменной вне цикла или выражения внутри его может получиться дробный результат. VBA Excel округлит его до целого числа, используя бухгалтерское округление:

‘Значения атрибутов до округления

For i = 1.5 To 10.5 Step 2.51

‘Округленные значения атрибутов

For i = 2 To 10 Step 3  

Старайтесь не допускать попадания в тело цикла For… Next неокругленных значений аргументов, чтобы не получить непредсказуемые результаты его выполнения. Если без дробных чисел не обойтись, а необходимо использовать обычное округление, применяйте в коде VBA функцию рабочего листа WorksheetFunction.Round для округления числа перед использованием его в цикле For… Next.


Всё о работе с ячейками в Excel-VBA: обращение, перебор, удаление, вставка, скрытие, смена имени.

Содержание:

Table of Contents:

  • Что такое ячейка Excel?
  • Способы обращения к ячейкам
    • Выбор и активация
    • Получение и изменение значений ячеек
      • Ячейки открытой книги
      • Ячейки закрытой книги 
    • Перебор ячеек
    • Перебор в произвольном диапазоне
  • Свойства и методы ячеек
    • Имя ячейки
    • Адрес ячейки
    • Размеры ячейки
  • Запуск макроса активацией ячейки

2 нюанса:

  1. Я почти везде стараюсь использовать ThisWorkbook (а не, например, ActiveWorkbook) для обращения к текущей книге, в которой написан этот код (считаю это наиболее безопасным для новичков способом обращения к книгам, чтобы случайно не внести изменения в другие книги). Для экспериментов можете вставлять этот код в модули, коды книги, либо листа, и он будет работать только в пределах этой книги. 
  2. Я использую английский эксель и у меня по стандарту листы называются Sheet1, Sheet2 и т.д. Если вы работаете в русском экселе, то замените Thisworkbook.Sheets(«Sheet1») на Thisworkbook.Sheets(«Лист1»). Если этого не сделать, то вы получите ошибку в связи с тем, что пытаетесь обратиться к несуществующему объекту. Можно также заменить на Thisworkbook.Sheets(1), но это менее безопасно.

Что такое ячейка Excel?

В большинстве мест пишут: «элемент, образованный пересечением столбца и строки». Это определение полезно для людей, которые не знакомы с понятием «таблица». Для того, чтобы понять чем на самом деле является ячейка Excel, необходимо заглянуть в объектную модель Excel. При этом определения объектов «ряд», «столбец» и «ячейка» будут отличаться в зависимости от того, как мы работаем с файлом.

Объекты в Excel-VBA. Пока мы работаем в Excel без углубления в VBA определение ячейки как «пересечения» строк и столбцов нам вполне хватает, но если мы решаем как-то автоматизировать процесс в VBA, то о нём лучше забыть и просто воспринимать лист как «мешок» ячеек, с каждой из которых VBA позволяет работать как минимум тремя способами:

  1. по цифровым координатам (ряд, столбец),
  2. по адресам формата А1, B2 и т.д. (сценарий целесообразности данного способа обращения в VBA мне сложно представить)
  3. по уникальному имени (во втором и третьем вариантах мы будем иметь дело не совсем с ячейкой, а с объектом 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. На это есть две причины:

  1. Это лишь имитация действий пользователя, которая замедляет выполнение программы. Работать с объектами книги можно напрямую без использования методов Select и Activate.
  2. Это усложняет код и может приводить к неожиданным последствиям. Каждый раз перед использованием 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

Перебор ячеек

Перебор в произвольном диапазоне

Скачать файл со всеми примерами

Пройтись по всем ячейкам в нужном диапазоне можно разными способами. Основные:

  1. Цикл 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 по порядку по строкам слева направо и по столбцам — сверху вниз. Данный способ можно использовать для действий, в который вам не важны номера ячеек (закрашивание, изменение форматирования, пересчёт чего-то и т.д.).

  2. Ту же задачу можно решить с помощью двух вложенных циклов — внешний будет перебирать ряды, а вложенный — ячейки в рядах. Этот способ я использую чаще всего, потому что он позволяет получить больше контроля над исполнением: на каждой итерации цикла нам доступны координаты ячеек. Для перебора всех ячеек на листе этим методом потребуется найти последнюю заполненную ячейку. Пример кода:
    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​
  3. Если нужно перебрать все ячейки в выделенном диапазоне на активном листе, то код будет выглядеть так:
    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​

    Данный метод подходит для интерактивных макросов, которые выполняют действия над выбранными пользователем областями.

  4. Перебор ячеек в ряду
    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
  5. Перебор ячеек в столбце
    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

Добрый день, фоурмчане! Необходима ваша неоценимая помощь и подсказ, как разобраться с заданием: «В произвольные клетки текущего листа введены натуральные числа. При двойном щелчке по любой заполненной клетке происходит запуск макроса и заполнение ячеек вниз и вправо.» Более подробно во вложении. Расскажу немного, как я это вижу. Необходимо, чтобы от числа шел массив. Соответственно задаем пустой массив, который будет назначаться в процессе макроса и при этом он будет натуральным числом(Integer). Далее мы задаем начало этого массива от выбранной ячейки. Дальше начинается цикл For Each, далее задаем значение целевой ячейки, а именно наш массив с помощью функции ubound — это функция которая создает ряд значений, и n, 1, мы задаем координаты в таблице, то есть n — значение в столбце, 1 — значение строки. Далее идет n = n — 1 и переход на след клетку, необходимо ряд свести к еденице. Затем происходит переход на соседнюю справа клетку. Для этого возвращаемся к первоначальной ячейке и используем функцию: ActiveCell.Offset(0, 1).Select (происходит переход вправо на одну ячейку). Повторяем ряд. Исполнение хромает. Вот что начеркал

Заранее спасибо за помощь.

Содержание

  • 1 Оператор цикла «For» в Visual Basic
    • 1.1 Цикл «For … Next»
    • 1.2 Цикл «For Each»
    • 1.3 Оператор прерывания цикла «Exit For»
  • 2 Цикл «Do While» в Visual Basic
  • 3 Цикл «Do Until» в Visual Basic

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

Excel

таблицей БЕЗ макросов и дополнительных модулей (функций пользователя).

Стандартный набор функций Excel не поддерживает ничего похожего на циклы, однако выход нашелся – использование циклических ссылок и итераций.

Первый шаг, чтобы начать работать с циклическими ссылками – это разрешить итеративные вычисления в Excel. В версии Microsoft Office XP это делается в разделе меню «Сервис – Параметры»:

как сделать цикл в excel

В открывшемся окне активируем соответствующий флажок:

как сделать цикл в excel

Так же обратите внимание на поле «Предельное число итераций» — оно определяет, сколько раз будет проходить вычисление по всем циклическим ссылкам, если вы сами не поставите ограничение.

!Информация: В Excel 2007 включение итеративных вычислений производится в пункте меню «Файл – Параметры Excel» в разделе «Формулы».

Рассмотрим пример использования итеративных вычислений в виде цикла.

Впишите в ячейку А1 формулу:

Если значение предельного числа итераций равно 100, то результатом вычислений в ячейке А1 будет равно 100. Теперь изменим формулу:

как сделать цикл в excel

Как видите число итераций мы ограничили числом в ячейке А2, а именно 10. Чтобы проиллюстрировать, как происходят итерации, добавим формулу в ячейку B2:

как сделать цикл в excel

Как видите, каждый этап итерации (новое значение А1) добавляется к ячейке B1 до тех пор пока происходят итерации.

!Замечание: Возможно, результат в B2 будет не таким – для того, чтобы исправить это сделайте следующее: после ввода формулы в ячейку B1 перейдите в ячейку A1, установите курсор в поле редактирования формулы и нажмите Enter – произойдет пересчет итераций. Для корректной работы итераций необходимо задать ряд дополнительных условий, ограничивающих их количество и задающее условие сброса текущего значения поля в исходное значение. Пересчет всех ячеек с циклическими ссылками происходит каждый раз при изменении ячеек, от которых они зависят.

!Дополнительные ссылки:

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

К циклам VBA относятся:

  • Цикл For
  • Цикл Do While
  • Цикл Do Until

Далее мы подробно рассмотрим каждый из этих циклов.

Оператор цикла «For» в Visual Basic

Структура оператора цикла For в Visual Basic может быть организована в одной из двух форм: как цикл For … Next или как цикл For Each.

Цикл «For … Next»

Цикл For … Next использует переменную, которая последовательно принимает значения из заданного диапазона. С каждой сменой значения переменной выполняются действия, заключённые в теле цикла. Это легко понять из простого примера:

For i = 1 To 10     Total = Total + iArray(i)  Next i

В этом простом цикле For … Next используется переменная i, которая последовательно принимает значения 1, 2, 3, … 10, и для каждого из этих значений выполняется код VBA, находящийся внутри цикла. Таким образом, данный цикл суммирует элементы массива iArray в переменной Total.

В приведённом выше примере шаг приращения цикла не указан, поэтому для пошагового увеличения переменной i от 1 до 10 по умолчанию используется приращение . Однако, в некоторых случаях требуется использовать другие значения приращения для цикла. Это можно сделать при помощи ключевого слова Step, как показано в следующем простом примере.

For d = 0 To 10 Step 0.1     dTotal = dTotal + d  Next d

Так как в приведённом выше примере задан шаг приращения равный 0.1, то переменная dTotal для каждого повторения цикла принимает значения 0.0, 0.1, 0.2, 0.3, … 9.9, 10.0.

Для определения шага цикла в VBA можно использовать отрицательную величину, например, вот так:

For i = 10 To 1 Step -1     iArray(i) = i  Next i

Здесь шаг приращения равен -1, поэтому переменная i с каждым повторением цикла принимает значения 10, 9, 8, … 1.

Цикл «For Each»

Цикл For Each похож на цикл For … Next, но вместо того, чтобы перебирать последовательность значений для переменной-счётчика, цикл For Each выполняет набор действий для каждого объекта из указанной группы объектов. В следующем примере при помощи цикла For Each выполняется перечисление всех листов в текущей рабочей книге Excel:

Dim wSheet As Worksheet    For Each wSheet in Worksheets     MsgBox "Найден лист: " & wSheet.Name  Next wSheet

Оператор прерывания цикла «Exit For»

Оператор Exit For применяется для прерывания цикла. Как только в коде встречается этот оператор, программа завершает выполнение цикла и переходит к выполнению операторов, находящихся в коде сразу после данного цикла. Это можно использовать, например, для поиска определённого значения в массиве. Для этого при помощи цикла просматривается каждый элемент массива. Как только искомый элемент найден, просматривать остальные нет необходимости – цикл прерывается.

Применение оператора Exit For продемонстрировано в следующем примере. Здесь цикл перебирает 100 записей массива и сравнивает каждую со значением переменной dVal. Если совпадение найдено, то цикл прерывается:

For i = 1 To 100     If dValues(i) = dVal Then        IndexVal = i        Exit For     End If  Next i

Цикл «Do While» в Visual Basic

Цикл Do While выполняет блок кода до тех пор, пока выполняется заданное условие. Далее приведён пример процедуры Sub, в которой при помощи цикла Do While выводятся последовательно числа Фибоначчи не превышающие 1000:

'Процедура Sub выводит числа Фибоначчи, не превышающие 1000  Sub Fibonacci()     Dim i As Integer 'счётчик для обозначения позиции элемента в последовательности     Dim iFib As Integer 'хранит текущее значение последовательности     Dim iFib_Next As Integer 'хранит следующее значение последовательности     Dim iStep As Integer 'хранит размер следующего приращения       'инициализируем переменные i и iFib_Next     i = 1     iFib_Next = 0     'цикл Do While будет выполняться до тех пор, пока значение     'текущего числа Фибоначчи не превысит 1000       Do While iFib_Next < 1000        If i = 1 Then           'особый случай для первого элемента последовательности           iStep = 1           iFib = 0        Else           'сохраняем размер следующего приращения перед тем, как перезаписать           'текущее значение последовательности           iStep = iFib           iFib = iFib_Next        End If          'выводим текущее число Фибоначчи в столбце A активного рабочего листа        'в строке с индексом i        Cells(i, 1).Value = iFib        'вычисляем следующее число Фибоначчи и увеличиваем индекс позиции элемента на 1        iFib_Next = iFib + iStep        i = i + 1     Loop    End Sub

В приведённом примере условие iFib_Next < 1000 проверяется в начале цикла. Поэтому если бы первое значение iFib_Next было бы больше 1000, то цикл бы не выполнялся ни разу.

Другой способ реализовать цикл Do While – поместить условие не в начале, а в конце цикла. В этом случае цикл будет выполнен хотя бы раз, не зависимо от того, выполняется ли условие.

Схематично такой цикл Do While с проверяемым условием в конце будет выглядеть вот так:

Do  ...  Loop While iFib_Next < 1000

Цикл «Do Until» в Visual Basic

Цикл Do Until очень похож на цикл Do While: блок кода в теле цикла выполняется раз за разом до тех пор, пока заданное условие выполняется (результат условного выражения равен True). В следующей процедуре Sub при помощи цикла Do Until извлекаются значения из всех ячеек столбца A рабочего листа до тех пор, пока в столбце не встретится пустая ячейка:

iRow = 1  Do Until IsEmpty(Cells(iRow, 1))     'Значение текущей ячейки сохраняется в массиве dCellValues     dCellValues(iRow) = Cells(iRow, 1).Value     iRow = iRow + 1  Loop

В приведённом выше примере условие IsEmpty(Cells(iRow, 1)) находится в начале конструкции Do Until, следовательно цикл будет выполнен хотя бы один раз, если первая взятая ячейка не пуста.

Однако, как было показано в примерах цикла Do While, в некоторых ситуациях нужно, чтобы цикл был выполнен хотя бы один раз, не зависимо от первоначального результата условного выражения. В таком случае условное выражение нужно поместить в конце цикла, вот так:

Do  ...  Loop Until IsEmpty(Cells(iRow, 1))

Урок подготовлен для Вас командой сайта office-guru.ru
Источник: /> Перевел: Антон Андронов

Правила перепечаткиЕще больше уроков по Microsoft Excel

Оцените качество статьи. Нам важно ваше мнение:

Добрый день!
Неделю пытаюсь разобраться с макросами в Excel — выходит признаюсь честно плохо…
Решение задачи так и не нашла. Надеюсь вы сумеете мне подсказать куда конкретнее направить свою активность.

Задача передо мной стоит такая:

ячейка A1 содержит значение, которое я с помощью формул разбиваю на диапазон ячеек (задействовано 276 ячеек) целыми числами. Но при разбивке образуется дельта округления. Так вот мне необходимо эту дельту целыми числами доразнести в уже заполненные формулами ячейки например по порядку.
Например если дельта = 117, а диапазон 276, то в первые 117 ячеек прибавляем по 1, а остальные не трогаем.

Подскажите, пожалуйста, возможно ли вообще это описать для Excel?

Время на прочтение
7 мин

Количество просмотров 312K

Приветствую всех.

В этом посте я расскажу, что такое VBA и как с ним работать в Microsoft Excel 2007/2010 (для более старых версий изменяется лишь интерфейс — код, скорее всего, будет таким же) для автоматизации различной рутины.

VBA (Visual Basic for Applications) — это упрощенная версия Visual Basic, встроенная в множество продуктов линейки Microsoft Office. Она позволяет писать программы прямо в файле конкретного документа. Вам не требуется устанавливать различные IDE — всё, включая отладчик, уже есть в Excel.

Еще при помощи Visual Studio Tools for Office можно писать макросы на C# и также встраивать их. Спасибо, FireStorm.

Сразу скажу — писать на других языках (C++/Delphi/PHP) также возможно, но требуется научится читать, изменять и писать файлы офиса — встраивать в документы не получится. А интерфейсы Microsoft работают через COM. Чтобы вы поняли весь ужас, вот Hello World с использованием COM.

Поэтому, увы, будем учить Visual Basic.

Чуть-чуть подготовки и постановка задачи

Итак, поехали. Открываем Excel.

Для начала давайте добавим в Ribbon панель «Разработчик». В ней находятся кнопки, текстовые поля и пр. элементы для конструирования форм.

Появилась вкладка.

Теперь давайте подумаем, на каком примере мы будем изучать VBA. Недавно мне потребовалось красиво оформить прайс-лист, выглядевший, как таблица. Идём в гугл, набираем «прайс-лист» и качаем любой, который оформлен примерно так (не сочтите за рекламу, пожалуйста):

То есть требуется, чтобы было как минимум две группы, по которым можно объединить товары (в нашем случае это будут Тип и Производитель — в таком порядке). Для того, чтобы предложенный мною алгоритм работал корректно, отсортируйте товары так, чтобы товары из одной группы стояли подряд (сначала по Типу, потом по Производителю).

Результат, которого хотим добиться, выглядит примерно так:

Разумеется, если смотреть прайс только на компьютере, то можно добавить фильтры и будет гораздо удобнее искать нужный товар. Однако мы хотим научится кодить и задача вполне подходящая, не так ли?

Кодим

Для начала требуется создать кнопку, при нажатии на которую будет вызываться наша програма. Кнопки находятся в панели «Разработчик» и появляются по кнопке «Вставить». Вам нужен компонент формы «Кнопка». Нажали, поставили на любое место в листе. Далее, если не появилось окно назначения макроса, надо нажать правой кнопкой и выбрать пункт «Назначить макрос». Назовём его FormatPrice. Важно, чтобы перед именем макроса ничего не было — иначе он создастся в отдельном модуле, а не в пространстве имен книги. В этому случае вам будет недоступно быстрое обращение к выделенному листу. Нажимаем кнопку «Новый».

И вот мы в среде разработки VB. Также её можно вызвать из контекстного меню командой «Исходный текст»/«View code».

Перед вами окно с заглушкой процедуры. Можете его развернуть. Код должен выглядеть примерно так:

Sub FormatPrice()End Sub

Напишем Hello World:

Sub FormatPrice()
    MsgBox "Hello World!"
End Sub

И запустим либо щелкнув по кнопке (предварительно сняв с неё выделение), либо клавишей F5 прямо из редактора.

Тут, пожалуй, следует отвлечься на небольшой ликбез по поводу синтаксиса VB. Кто его знает — может смело пропустить этот раздел до конца. Основное отличие Visual Basic от Pascal/C/Java в том, что команды разделяются не ;, а переносом строки или двоеточием (:), если очень хочется написать несколько команд в одну строку. Чтобы понять основные правила синтаксиса, приведу абстрактный код.

Примеры синтаксиса

' Процедура. Ничего не возвращает
' Перегрузка в VBA отсутствует
Sub foo(a As String, b As String)
    ' Exit Sub ' Это значит "выйти из процедуры"
    MsgBox a + ";" + b
End Sub' Функция. Вовращает Integer
Function LengthSqr(x As Integer, y As IntegerAs Integer
    ' Exit Function
    LengthSqr = x * x + y * y
End FunctionSub FormatPrice()
    Dim s1 As String, s2 As String
    s1 = "str1"
    s2 = "str2"
    If s1 <> s2 Then
        foo "123""456" ' Скобки при вызове процедур запрещены
    End IfDim res As sTRING ' Регистр в VB не важен. Впрочем, редактор Вас поправит
    Dim i As Integer
    ' Цикл всегда состоит из нескольких строк
    For i = 1 To 10
        res = res + CStr(i) ' Конвертация чего угодно в String
        If i = 5 Then Exit For
    Next iDim x As Double
    x = Val("1.234"' Парсинг чисел
    x = x + 10
    MsgBox xOn Error Resume Next ' Обработка ошибок - игнорировать все ошибки
    x = 5 / 0
    MsgBox xOn Error GoTo Err ' При ошибке перейти к метке Err
    x = 5 / 0
    MsgBox "OK!"
    GoTo ne

Err:
    MsgBox 

"Err!"

ne:

On Error GoTo 0 ' Отключаем обработку ошибок

    ' Циклы бывает, какие захотите
    Do While True
        Exit DoLoop 'While True
    Do 'Until False
        Exit Do
    Loop Until False
    ' А вот при вызове функций, от которых хотим получить значение, скобки нужны.
    ' Val также умеет возвращать Integer
    Select Case LengthSqr(Len("abc"), Val("4"))
    Case 24
        MsgBox "0"
    Case 25
        MsgBox "1"
    Case 26
        MsgBox "2"
    End Select' Двухмерный массив.
    ' Можно также менять размеры командой ReDim (Preserve) - см. google
    Dim arr(1 to 10, 5 to 6) As Integer
    arr(1, 6) = 8Dim coll As New Collection
    Dim coll2 As Collection
    coll.Add "item""key"
    Set coll2 = coll ' Все присваивания объектов должны производится командой Set
    MsgBox coll2("key")
    Set coll2 = New Collection
    MsgBox coll2.Count
End Sub

Грабли-1. При копировании кода из IDE (в английском Excel) есь текст конвертируется в 1252 Latin-1. Поэтому, если хотите сохранить русские комментарии — надо сохранить крокозябры как Latin-1, а потом открыть в 1251.

Грабли-2. Т.к. VB позволяет использовать необъявленные переменные, я всегда в начале кода (перед всеми процедурами) ставлю строчку Option Explicit. Эта директива запрещает интерпретатору заводить переменные самостоятельно.

Грабли-3. Глобальные переменные можно объявлять только до первой функции/процедуры. Локальные — в любом месте процедуры/функции.

Еще немного дополнительных функций, которые могут пригодится: InPos, Mid, Trim, LBound, UBound. Также ответы на все вопросы по поводу работы функций/их параметров можно получить в MSDN.

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

Кодим много и под Excel

В этой части мы уже начнём кодить нечто, что умеет работать с нашими листами в Excel. Для начала создадим отдельный лист с именем result (лист с данными назовём data). Теперь, наверное, нужно этот лист очистить от того, что на нём есть. Также мы «выделим» лист с данными, чтобы каждый раз не писать длинное обращение к массиву с листами.

Sub FormatPrice()
    Sheets("result").Cells.Clear
    Sheets("data").Activate
End Sub

Работа с диапазонами ячеек

Вся работа в Excel VBA производится с диапазонами ячеек. Они создаются функцией Range и возвращают объект типа Range. У него есть всё необходимое для работы с данными и/или оформлением. Кстати сказать, свойство Cells листа — это тоже Range.

Примеры работы с Range

Sheets("result").Activate
Dim r As Range
Set r = Range("A1")
r.Value = "123"
Set r = Range("A3,A5")
r.Font.Color = vbRed
r.Value = "456"
Set r = Range("A6:A7")
r.Value = "=A1+A3"

Теперь давайте поймем алгоритм работы нашего кода. Итак, у каждой строчки листа data, начиная со второй, есть некоторые данные, которые нас не интересуют (ID, название и цена) и есть две вложенные группы, к которым она принадлежит (тип и производитель). Более того, эти строки отсортированы. Пока мы забудем про пропуски перед началом новой группы — так будет проще. Я предлагаю такой алгоритм:

  1. Считали группы из очередной строки.
  2. Пробегаемся по всем группам в порядке приоритета (вначале более крупные)
    1. Если текущая группа не совпадает, вызываем процедуру AddGroup(i, name), где i — номер группы (от номера текущей до максимума), name — её имя. Несколько вызовов необходимы, чтобы создать не только наш заголовок, но и всё более мелкие.
  3. После отрисовки всех необходимых заголовков делаем еще одну строку и заполняем её данными.

Для упрощения работы рекомендую определить следующие функции-сокращения:

Function GetCol(Col As IntegerAs String
    GetCol = Chr(Asc("A") + Col)
End FunctionFunction GetCellS(Sheet As String, Col As Integer, Row As IntegerAs Range
    Set GetCellS = Sheets(Sheet).Range(GetCol(Col) + CStr(Row))
End FunctionFunction GetCell(Col As Integer, Row As IntegerAs Range
    Set GetCell = Range(GetCol(Col) + CStr(Row))
End Function

Далее определим глобальную переменную «текущая строчка»: Dim CurRow As Integer. В начале процедуры её следует сделать равной единице. Еще нам потребуется переменная-«текущая строка в data», массив с именами групп текущей предыдущей строк. Потом можно написать цикл «пока первая ячейка в строке непуста».

Глобальные переменные

Option Explicit ' про эту строчку я уже рассказывал
Dim CurRow As Integer
Const GroupsCount As Integer = 2
Const DataCount As Integer = 3

FormatPrice

Sub FormatPrice()
    Dim I As Integer ' строка в data
    CurRow = 1
    Dim Groups(1 To GroupsCount) As String
    Dim PrGroups(1 To GroupsCount) As String

    Sheets(

"data").Activate
    I = 2
    Do While True
        If GetCell(0, I).Value = "" Then Exit Do
        ' ...
        I = I + 1
    Loop
End Sub

Теперь надо заполнить массив Groups:

На месте многоточия

Dim I2 As Integer
For I2 = 1 To GroupsCount
    Groups(I2) = GetCell(I2, I)
Next I2
' ...
For I2 = 1 To GroupsCount ' VB не умеет копировать массивы
    PrGroups(I2) = Groups(I2)
Next I2
I =  I + 1

И создать заголовки:

На месте многоточия в предыдущем куске

For I2 = 1 To GroupsCount
    If Groups(I2) <> PrGroups(I2) Then
        Dim I3 As Integer
        For I3 = I2 To GroupsCount
            AddHeader I3, Groups(I3)
        Next I3
        Exit For
    End If
Next I2

Не забудем про процедуру AddHeader:

Перед FormatPrice

Sub AddHeader(Ty As Integer, Name As String)
    GetCellS("result", 1, CurRow).Value = Name
    CurRow = CurRow + 1
End Sub

Теперь надо перенести всякую информацию в result

For I2 = 0 To DataCount - 1
    GetCellS("result", I2, CurRow).Value = GetCell(I2, I)
Next I2

Подогнать столбцы по ширине и выбрать лист result для показа результата

После цикла в конце FormatPrice

Sheets("Result").Activate
Columns.AutoFit

Всё. Можно любоваться первой версией.

Некрасиво, но похоже. Давайте разбираться с форматированием. Сначала изменим процедуру AddHeader:

Sub AddHeader(Ty As Integer, Name As String)
    Sheets("result").Range("A" + CStr(CurRow) + ":C" + CStr(CurRow)).Merge
    ' Чтобы не заводить переменную и не писать каждый раз длинный вызов
    ' можно воспользоваться блоком With
    With GetCellS("result", 0, CurRow)
        .Value = Name
        .Font.Italic = True
        .Font.Name = "Cambria"
        Select Case Ty
        Case 1 ' Тип
            .Font.Bold = True
            .Font.Size = 16
        Case 2 ' Производитель
            .Font.Size = 12
        End Select
        .HorizontalAlignment = xlCenter
    End With
    CurRow = CurRow + 1
End Sub

Уже лучше:

Осталось только сделать границы. Тут уже нам требуется работать со всеми объединёнными ячейками, иначе бордюр будет только у одной:

Поэтому чуть-чуть меняем код с добавлением стиля границ:

Sub AddHeader(Ty As Integer, Name As String)
    With Sheets("result").Range("A" + CStr(CurRow) + ":C" + CStr(CurRow))
        .Merge
        .Value = Name
        .Font.Italic = True
        .Font.Name = "Cambria"
        .HorizontalAlignment = xlCenterSelect Case Ty
        Case 1 ' Тип
            .Font.Bold = True
            .Font.Size = 16
            .Borders(xlTop).Weight = xlThick
        Case 2 ' Производитель
            .Font.Size = 12
            .Borders(xlTop).Weight = xlMedium
        End Select
        .Borders(xlBottom).Weight = xlMedium ' По убыванию: xlThick, xlMedium, xlThin, xlHairline
    End With
    CurRow = CurRow + 1
End Sub

Осталось лишь добится пропусков перед началом новой группы. Это легко:

В начале FormatPrice

Dim I As Integer ' строка в  data
CurRow = 0 ' чтобы не было пропуска в самом начале
Dim Groups(1 To GroupsCount) As String

В цикле расстановки заголовков

If Groups(I2) <> PrGroups(I2) Then
    CurRow = CurRow + 1
    Dim I3 As Integer

В точности то, что и хотели.

Надеюсь, что эта статья помогла вам немного освоится с программированием для Excel на VBA. Домашнее задание — добавить заголовки «ID, Название, Цена» в результат. Подсказка: CurRow = 0 CurRow = 1.

Файл можно скачать тут (min.us) или тут (Dropbox). Не забудьте разрешить исполнение макросов. Если кто-нибудь подскажет человеческих файлохостинг, залью туда.

Спасибо за внимание.

Буду рад конструктивной критике в комментариях.

UPD: Перезалил пример на Dropbox и min.us.

UPD2: На самом деле, при вызове процедуры с одним параметром скобки можно поставить. Либо использовать конструкцию Call Foo(«bar», 1, 2, 3) — тут скобки нужны постоянно.

Excel VBA. Цикл в макросе

19 мая 2015 10:05

Просмотров: 17657

Создадим самый простой цикл используя VBA в Excel.

В этот раз напишем всё своими руками:

Sub Заполнение()
'Запускаем цикл от 1 до 10
'Начало цикла
For i = 1 To 10
'В первый столбец записываем порядковый номер
Cells(i + 1, 1) = i
'Во второй столбец записываем произведение порядкового номера и значения указанного в ячейке "B1"
Cells(i + 1, 2) = i * Range("b1").Value
'Конец цикла
Next
End Sub

Расшифрую, приведённый выше код VBA:

  • Весь код макроса заключается между Sub и End Sub, после Sub пишется название макроса.
  • Текст после ‘ означает комментарий
  • Цикл заключается между For … to и Next
  • i — в моём случае переменная, Вы можете выбрать любую другую, в том числе поддерживаются и русские обозначения (например: For переменная=1 To 10 …)
  • Cells(строка, столбец) – ячейка в которую хотим что-то записать или из которой хотим извлечь информацию, в нашем случае столбец мы указали константу (1 и 2), а строку сделали переменной (i+1).
  • Range(“b1”) возвращает значение ячейки “B1”

А ещё, можно сразу дописать минимакрос по очистке диапазона от значений

Sub Очистка()
Range("A2:B11").ClearContents
End Sub

Комментарии: 1

О чём пойдёт речь?

Знакомство с объектной моделью 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 — если вы написали пользовательскую функцию рабочего листа, то через это свойство вы можете определить какая конкретно ячейка в данный момент пересчитывает вашу функцию. Об остальных перечисленных объектов речь пойдёт ниже.

Работа с отдельными ячейками

Синтаксическая форма Комментарии по использованию
RangeD5«) или [D5] Ячейка D5 текущего листа. Полная и краткая формы. Тут применим только синтаксис типа A1, но не R1C1. То есть такая конструкция RangeR1C2«) — вызовет ошибку, даже если в книге Excel включен режим формул R1C1.

Разумеется после этой формы вы можете обратиться к свойствам соответствующей ячейки. Например, RangeD5«).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 текущего листа. Удобно, когда вы знаете именно цифровые координаты углов диапазона.

Работа со строками

Синтаксическая форма Комментарии по использованию
Range3:5«) или [3:5] Строки 3, 4 и 5 текущего листа целиком.
RangeA3:XFD3«) или [A3:XFD3] Строка 3, но с указанием колонок. Просто, чтобы вы понимали, что это тождественные формы. XFD — последняя колонка листа.
Rows3:3«) Строка 3 через свойство Rows. Параметр в виде диапазона строк. Двоеточие — это символ диапазона.
Rows(3) Тут параметр — индекс строки в массиве строк. Так можно сослаться только не конкретную строку. Обратите внимание, что в предыдущем примере параметр текстовая строка «3:3» и она взята в кавычки, а тут — чистое число.

Работа со столбцами

Синтаксическая форма Комментарии по использованию
RangeB:B«) или [B:B] Колонка B текущего листа.
RangeB1:B1048576«) или [B1:B1048576] То же самое, но с указанием номеров строк, чтобы вы понимали, что это тождественные формы. 2^20=1048576 — максимальный номер строки на листе.
ColumnsB:B«) То же самое через свойство Columns. Параметр — текстовая строка.
Columns(2) То же самое. Параметр — числовой индекс столбца. «A» -> 1, «B» -> 2, и т.д.

Весь лист

Синтаксическая форма Комментарии по использованию
RangeA1:XFD1048576«) или [A1:XFD1048576] Диапазон размером во всё адресное пространство листа Excel. Воспринимайте эту таблицу лишь как теорию — так работать с листами вам не придётся — слишком большое количество ячеек. Даже современные компьютеры не смогут помочь Excel быстро работать с такими массивами информации. Тут проблема больше даже в самом приложении.
Range1:1048576«) или [1:1048576] То же самое, но через строки.
RangeA: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. Перебор ячеек в диапазоне (вариант 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. Перебор ячеек в диапазоне (вариант 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. Перебор ячеек в диапазоне (вариант 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  
     
  4. Перебор строк диапазона

    В цикле 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  
     
  5. Перебор столбцов

    Перебираем коллекцию 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 
     
  6. Перебор областей диапазона

    Как вы знаете, в Excel можно выделить несвязанные диапазоны и проделать с ними какие-то операции. Поддерживает это и объект Range. Получить диапазон, состоящий из нескольких областей (area) очень легко — достаточно перечислить через запятую адреса соответствующих диапазонов: RangeA1: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

  • Структуры данных и их эффективность

  • Автоматическое скрытие/показ столбцов и строк

На чтение 18 мин. Просмотров 75.3k.

VBA Range

сэр Артур Конан Дойл

Это большая ошибка — теоретизировать, прежде чем кто-то получит данные

Эта статья охватывает все, что вам нужно знать об использовании ячеек и диапазонов в VBA. Вы можете прочитать его от начала до конца, так как он сложен в логическом порядке. Или использовать оглавление ниже, чтобы перейти к разделу по вашему выбору.

Рассматриваемые темы включают свойство смещения, чтение
значений между ячейками, чтение значений в массивы и форматирование ячеек.

Содержание

  1. Краткое руководство по диапазонам и клеткам
  2. Введение
  3. Важное замечание
  4. Свойство Range
  5. Свойство Cells рабочего листа
  6. Использование Cells и Range вместе
  7. Свойство Offset диапазона
  8. Использование диапазона CurrentRegion
  9. Использование Rows и Columns в качестве Ranges
  10. Использование Range вместо Worksheet
  11. Чтение значений из одной ячейки в другую
  12. Использование метода Range.Resize
  13. Чтение Value в переменные
  14. Как копировать и вставлять ячейки
  15. Чтение диапазона ячеек в массив
  16. Пройти через все клетки в диапазоне
  17. Форматирование ячеек
  18. Основные моменты

Краткое руководство по диапазонам и клеткам

Функция Принимает Возвращает Пример Вид
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, начинается и заканчивается ячейками.

Вы делаете три основных вещи с помощью ячеек:

  1. Читаете из ячейки.
  2. Пишите в ячейку.
  3. Изменяете формат ячейки.

В 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, вы должны сначала указать рабочую книгу и рабочий лист, которому она принадлежит.

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

code name worksheet

Следующий код показывает приведенный выше пример с использованием кодового имени рабочего листа, т.е. Лист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 . Есть два отличия:

  1. Cells возвращают диапазон только одной ячейки.
  2. 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).

ImmediateWindow

ImmediateSampeText

Свойство Offset диапазона

У диапазона есть свойство, которое называется Offset. Термин «Offset» относится к отсчету от исходной позиции. Он часто используется в определенных областях программирования. С помощью свойства «Offset» вы можете получить диапазон ячеек того же размера и на определенном расстоянии от текущего диапазона. Это полезно, потому что иногда вы можете выбрать диапазон на основе определенного условия. Например, на скриншоте ниже есть столбец для каждого дня недели. Учитывая номер дня (т.е. понедельник = 1, вторник = 2 и т.д.). Нам нужно записать значение в правильный столбец.

VBA Offset

Сначала мы попытаемся сделать это без использования 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.

VBA 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

Основные моменты

Ниже приводится краткое изложение основных моментов

  1. Range возвращает диапазон ячеек
  2. Cells возвращают только одну клетку
  3. Вы можете читать из одной ячейки в другую
  4. Вы можете читать из диапазона ячеек в другой диапазон ячеек.
  5. Вы можете читать значения из ячеек в переменные и наоборот.
  6. Вы можете читать значения из диапазонов в массивы и наоборот
  7. Вы можете использовать цикл For Each или For, чтобы проходить через каждую ячейку в диапазоне.
  8. Свойства Rows и Columns позволяют вам получить доступ к диапазону ячеек этих типов

Понравилась статья? Поделить с друзьями:
  • Заполнение ячеек автозаполнение в excel
  • Заполнение ячеек excel 2003
  • Заполнение таблиц в excel цена
  • Заполнение таблиц в excel практическая работа
  • Заполнение таблиц в excel онлайн