Макрос указать на ячейку excel

Всё о работе с ячейками в 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

Обращение к ячейке на листе Excel из кода VBA по адресу, индексу и имени. Чтение информации из ячейки. Очистка значения ячейки. Метод ClearContents объекта Range.

Обращение к ячейке по адресу

Допустим, у нас есть два открытых файла: «Книга1» и «Книга2», причем, файл «Книга1» активен и в нем находится исполняемый код VBA.

В общем случае при обращении к ячейке неактивной рабочей книги «Книга2» из кода файла «Книга1» прописывается полный путь:

Workbooks(«Книга2.xlsm»).Sheets(«Лист2»).Range(«C5»)

Workbooks(«Книга2.xlsm»).Sheets(«Лист2»).Cells(5, 3)

Workbooks(«Книга2.xlsm»).Sheets(«Лист2»).Cells(5, «C»)

Workbooks(«Книга2.xlsm»).Sheets(«Лист2»).[C5]

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

Теперь предположим, что у нас в активной книге «Книга1» активны «Лист1» и ячейка на нем «A1». Тогда обращение к ячейке «A1» можно записать следующим образом:

ActiveCell

Range(«A1»)

Cells(1, 1)

Cells(1, «A»)

[A1]

Точно также можно обращаться и к другим ячейкам активного рабочего листа, кроме обращения ActiveCell, так как активной может быть только одна ячейка, в нашем примере – это ячейка «A1».

Если мы обращаемся к ячейке на неактивном листе активной рабочей книги, тогда необходимо указать этот лист:

‘по основному имени листа

Лист2.Cells(2, 7)

‘по имени ярлыка

Sheets(«Имя ярлыка»).Cells(3, 8)

Имя ярлыка может совпадать с основным именем листа. Увидеть эти имена можно в окне редактора VBA в проводнике проекта. Без скобок отображается основное имя листа, в скобках – имя ярлыка.

Обращение к ячейке по индексу

К ячейке на рабочем листе можно обращаться по ее индексу (порядковому номеру), который считается по расположению ячейки на листе слева-направо и сверху-вниз.

Например, индекс ячеек в первой строке равен номеру столбца. Индекс ячеек во второй строке равен количеству ячеек в первой строке (которое равно общему количеству столбцов на листе, зависящему от версии Excel) плюс номер столбца. Индекс ячеек в третьей строке равен количеству ячеек в двух первых строках плюс номер столбца. И так далее.

Для примера, Cells(4) та же ячейка, что и Cells(1, 4). Используется такое обозначение редко, тем более, что у разных версий Excel может быть разным количество столбцов и строк на рабочем листе.

По индексу можно обращаться к ячейке не только на всем рабочем листе, но и в отдельном диапазоне. Нумерация ячеек осуществляется в пределах заданного диапазона по тому же правилу: слева-направо и сверху-вниз. Вот индексы ячеек диапазона Range(«A1:C3»):

Индексы ячеек в диапазоне Range("A1:C3")

Обращение к ячейке Range("A1:C3").Cells(5) соответствует выражению Range("B2").

Обращение к ячейке по имени

Если ячейке на рабочем листе Excel присвоено имя (Формулы –> Присвоить имя), то обращаться к ней можно по присвоенному имени.

Допустим одной из ячеек присвоено имя – «Итого», тогда обратиться к ней можно – Range("Итого").

Запись информации в ячейку

Содержание ячейки определяется ее свойством «Value», которое в VBA Excel является свойством по умолчанию и его можно явно не указывать. Записывается информация в ячейку при помощи оператора присваивания «=»:

Cells(2, 4).Value = 15

Cells(2, 4) = 15

Range(«A1») = «Этот текст записываем в ячейку»

ActiveCell = 28 + 10*36

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

Чтение информации из ячейки

Считать информацию из ячейки в переменную можно также при помощи оператора присваивания «=»:

Sub Test()

Dim a1 As Integer, a2 As Integer, a3 As Integer

Range(«A3») = 6

Cells(2, 5) = 15

a1 = Range(«A3»)

a2 = Cells(2, 5)

a3 = a1 * a2

MsgBox a3

End Sub

Точно также можно обмениваться информацией между ячейками:

Cells(2, 2) = Range(«A4»)

Очистка значения ячейки

Очищается ячейка от значения с помощью метода ClearContents. Кроме того, можно присвоить ячейке значение нуля. пустой строки или Empty:

Cells(10, 2).ClearContents

Range(«D23») = 0

ActiveCell = «»

Cells(5, «D») = Empty

In this guide, we’re going to show you how to refer a range or a cell in Excel VBA.

VBA Basics

Before diving into the code, let’s start with a cell or a range means in VBA. First, VBA is an object-based programming language, which means that the language refers each element as objects. Objects have properties that define them, and they can encapsulate other objects, or codes. Thus, a single cell, a range of cells, a worksheet, or Excel software as a whole is an object for VBA. You can think this as a hierarchical model.

The image illustrates only a small portion of Excel objects in VBA. An Excel instance contains a Workbooks collection. A collection is a group of related objects. For example, if you open two workbooks, the Workbooks collection has two Workbook object. Each Workbook object has its own worksheets under a Worksheets collection. This structure applies to all.

VBA envelops all cell and cell-based references in an object called Range. In theory, when a particular object is referenced, you also need to specify its parents. In VBA syntax, a dot (.) operator is used to move through object hierarchy. For example, to access the Range object, the code should be:

Application.Workbooks.Worksheets.Range

However, this reference is ambiguous when it comes to specify which Excel workbook or worksheet you are referring to. In order to do this, you must supply the name or the index number (starting with 1) of the particular object you are referring. This approach is like in Excel formulas — the argument is given in parentheses. For example to refer the range object in the worksheet “Sheet1” of the workbook “Book1.xlsm”:

Application.Workbooks("Book1.xlsm").Worksheets("Sheet1").Range

or

Application.Workbooks(1).Worksheets(1).Range

You do not have to specify all parents for Range object every time. If your intention is to work on the active sheet of the active workbook, you can simply use Range.

Range Object

The Range object allows you to refer a cell or cells just like in any Excel formula. For example,

Range("A1") 'Refers the cell A1
Range("A2:D11") 'Refers the range of cells between A2:D11
Range("A3,B4:E6,F12") 'Refers all cells in the cells A3, F12 and the range B4:E6
Range("2:2") 'Entire 2nd row
Range("E:E") 'Entire column E
Range("Input") 'Named range "Input"

Using square brackets to refer a range or a cell

You can use square brackets ([]) instead of the “Range” keyword and double quotes (“). This approach as essentially a shortcut, and the outcome is the same.

[A1] 'Refers the cell A1
[A2:D11] 'Refers the range of cells between A2:D11
[A3,B4:E6,F12] 'Refers all cells in the cells A3, F12 and the range B4:E6
[2:2] 'Entire 2nd row
[E:E] 'Entire column E
[Input] 'Named range "Input"

Cells property to refer a range or a cell

Cells is the name of a property of both Worksheet and Range objects. It is neither a collection nor an object. Thus, there are no objects named Cell.

In other words, the Cells property returns a Range object as well. Each Cells property in Worksheet and Range objects work in its parent’s context only. This behavior might make more sense within examples.

Syntax

The Cells property can be used in two ways:
With row and column index numbers:

Cells(row number,column number) 

With index number of the cell:

Cells(cell number) ‘refers the 23rd cell in the range

Examples

Worksheet.Cells

Cells property of a Worksheet object returns the cell in a specific location in the worksheet.
With row and column index numbers:

Cells(3,2) 'refers the cell at third row and second column in the active sheet (B3)

How to refer a range or a cell in Excel VBA 02
With index number of the cell:

Cells(5) 'refers the 5th cell in the range (E1)

The numbering of cells starts from 1, and increases from left to right and from top to bottom. This means that A1 is the first cell.

Range.Cells

On the other hand, the Cells property of a Range object returns the cell in specified location in the range.
With row and column index numbers:

Range(&quot;C4:F9&quot;).Cells(3,2) 'refers the cell at third row and second column in the active range (D6)


With index number of the cell:

Range(&quot;C4:F9&quot;).Cells(5) ‘refers the 5th cell in the range (C5)

Active objects to refer a range or a cell

There are keywords in VBA to reference active(selected) objects when the code is running.

ActiveCell 'Refers the selected cell
Selection 'Refers any selected object. This can be cells or a chart
ActiveSheet 'Refers the active worksheet
ActiveWorkbook 'Refers the active worksheet

Содержание

  1. Как записать макрос в Excel? Пошаговая инструкция.
  2. Что такое макрос?
  3. Отображение вкладки «Разработчик» в ленте меню
  4. Запись макроса в Excel
  5. Что записывает макрос?
  6. Абсолютная и относительная запись макроса
  7. Что нельзя сделать с помощью макрорекодера?
  8. Расширение файлов Excel, которые содержат макросы

Как записать макрос в Excel? Пошаговая инструкция.

Что такое макрос?

Для начала немного о терминологии.

Макрос — это код, написанный на встроенном в Excel языке VBA (Visual Basic for Application). Макросы могут создаваться как вручную, так и записываться автоматически с помощью так называемого макрорекодера.

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

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

Теперь давайте погрузимся и посмотрим, как записать макрос в Excel.

Отображение вкладки «Разработчик» в ленте меню

Перед тем как записывать макрос, нужно добавить на ленту меню Excel вкладку «Разработчик». Для этого выполните следующие шаги:

  1. Щелкните правой кнопкой мыши по любой из существующих вкладок на ленте и нажмите «Настроить ленту». Он откроет диалоговое окно «Параметры Excel».
  2. В диалоговом окне «Параметры Excel» у вас будут параметры «Настроить ленту». Справа на панели «Основные вкладки» установите флажок «Разработчик».
  3. Нажмите «ОК».

В результате на ленте меню появится вкладка «Разработчик»

Запись макроса в Excel

Теперь давайте запишем очень простой макрос, который выбирает ячейку и вводит в нее текст, например «Excel».

Вот шаги для записи такого макроса:

  1. Перейдите на вкладку «Разработчик».
  2. В группе «Код» нажмите кнопку «Запись макроса». Откроется одноименное диалоговое окно.
  3. В диалоговом окне «Запись макроса» введите имя для своего макроса, например «ВводТекста». Есть несколько условий именования, которые необходимо соблюдать при назначении макроса. Например, вы не можете использовать пробелы между ними. Обычно я предпочитаю сохранять имена макросов как одно слово, с разными частями с заглавным первым алфавитом. Вы также можете использовать подчеркивание для разделения двух слов — например, «Ввод_текста».
  4. Если вы хотите, то можете задать сочетание клавиш. В этом случае мы будем использовать ярлык Ctrl + Shift + N. Помните, что сочетание, которое вы указываете, будет отменять любые существующие горячие клавиши в вашей книге. Например, если вы назначили сочетание Ctrl + S, вы не сможете использовать это для сохранения рабочей книги (вместо этого, каждый раз, когда вы его используете, он выполняет макрос).
  5. В поле «Сохранить в» убедитесь, что выбрана опция «Эта книга». Этот шаг гарантирует, что макрос является частью рабочей книги. Он будет там, когда вы сохраните его и снова откроете, или даже если вы поделитесь файлом с кем-то.
  6. Введите описание при необходимости. Обычно я этого не делаю, но если у вас много макросов, лучше указать, чтобы в будущем не забыть что делает макрос.
  7. Нажмите «ОК». Как только вы нажмете OK, Excel начнет записывать ваши действия. Вы можете увидеть кнопку «Остановить запись» на вкладке «Разработчик», которая указывает, что выполняется запить макроса.
  8. Выберите ячейку A2.
  9. Введите текст «Excel» (или вы можете использовать свое имя).
  10. Нажмите клавишу Enter. Вы попадете на ячейку A3.
  11. Нажмите кнопку «Остановить запись» на вкладке «Разработчик».

Поздравляем! Вы только что записали свой первый макрос в Excel. Хотя макрос не делает ничего полезного, но он поможет нам понять как работает макрорекордер в Excel.

Теперь давайте рассмотрим код который записал макрорекодер. Выполните следующие действия, чтобы открыть редактор кода:

  1. Удалите текст в ячейке A2. Это нужно, чтобы проверить будет ли макрос вставлять текст в ячейку A2 или нет.
  2. Выберите любую ячейку — кроме A2. Это нужно проверить, выбирает ли макрос ячейку A2 или нет.
  3. Перейдите на вкладку «Разработчик».
  4. В группе «Код» нажмите кнопку «Макросы».
  5. В диалоговом окне «Макрос» щелкните макрос «ВводТекста».
  6. Нажмите кнопку «Выполнить».

Вы увидите, что как только вы нажмете кнопку «Выполнить», текст «Excel» будет вставлен в ячейку A2 и выбрана ячейка A3. Это происходит за миллисекунды. Но на самом деле макрос последовательно выполнил записанные действия.

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

Что записывает макрос?

Теперь перейдем к редактору кода и посмотрим что у нас получилось.

Вот шаги по открытию редактора VB в Excel:

  1. Перейдите на вкладку «Разработчик».
  2. В группе «Код» нажмите кнопку «Visual Basic».

Вы также можете использовать комбинацию клавиш Alt + F11 и перейти в редактор кода VBA.

Рассмотрим сам редактор кода. Далее коротко опишем интерфейс редактора.

  • Панель меню: содержит команды, которые можно использовать во время работы с редактором VB.
  • Панель инструментов — похожа на панель быстрого доступа в Excel. Вы можете добавить к ней дополнительные инструменты, которыми часто пользуетесь.
  • Окно проектов (Project Explorer) — здесь Excel перечисляет все книги и все объекты в каждой книге. Например, если у нас есть книга с 3 рабочими листами, она появится в Project Explorer. Здесь есть несколько дополнительных объектов, таких как модули, пользовательские формы и модули классов.
  • Окно кода — собственно сам код VBA размещается в этом окне. Для каждого объекта, указанного в проводнике проекта, есть окно кода, например, рабочие листы, книги, модули и т. д. В этом уроке мы увидим, что записанный макрос находится в окне кода модуля.
  • Окно свойств — вы можете увидеть свойства каждого объекта в этом окне. Я часто использую это окно для обозначения объектов или изменения их свойств.
  • Immediate Window (окно предпросмотра) — На начальном этапе оно вам не пригодится. Оно полезно, когда вы хотите протестировать шаги или во время отладки. Он по умолчанию не отображается, и вы можете его отобразить, щелкнув вкладку «View» и выбрав опцию «Immediate Window».

Когда мы записали макрос «ВводТекста», в редакторе VB произошли следующие вещи:

  • Был добавлен новый модуль.
  • Макрос был записан с именем, которое мы указали — «ВводТекста»
  • В окне кода добавлена новая процедура.

Поэтому, если вы дважды щелкните по модулю (в нашем случае модуль 1), появится окно кода, как показано ниже.

Вот код, который записан макрорекодером:

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

Теперь давайте пробежим по каждой строке кода и опишем что и зачем.

Код начинается с Sub, за которым следует имя макроса и пустые круглые скобки. Sub — сокращение для подпрограммы. Каждая подпрограмма (также называемая процедурой) в VBA начинается с Sub и заканчивается End Sub.

  • Range(«A2»).Select — эта строка выбирает ячейку A2.
  • ActiveCell.FormulaR1C1 = «Excel» — эта строка вводит текст «Excel» в активной ячейке. Поскольку мы выбрали ячейку A2 в качестве первого шага, она становится нашей активной ячейкой.
  • Range(«A3»).Select — выбор ячейки A3. Это происходит, когда мы нажимаем клавишу Enter после ввода текста, результатом которого является выбор ячейки A3.

Надеюсь, что у вас есть некоторое базовое понимание того, как записывать макрос в Excel.

Обращаем внимание, что код, записанный через макрорекордер, как правило, не является эффективным и оптимизированным кодом. Макрорекордер часто добавляет дополнительные ненужные действия. Но это не значит, что не нужно пользоваться макрорекодером. Для тех, кто только изучает VBA , макрорекордер может быть отличным способом проанализировать и понять как все работает в VBA.

Абсолютная и относительная запись макроса

Вы уже знаете про абсолютные и относительные ссылки в Excel? Если вы используете абсолютную ссылку для записи макроса, код VBA всегда будет ссылаться на те же ячейки, которые вы использовали. Например, если вы выберете ячейку A2 и введете текст «Excel», то каждый раз — независимо от того, где вы находитесь на листе и независимо от того, какая ячейка выбрана, ваш код будет вводить текст «Excel» в ячейку A2.

Если вы используете параметр относительной ссылки для записи макроса, VBA не будет привязываться к конкретному адресу ячейки. В этом случае программа будет «двигаться» относительно активной ячейки. Например, предположим, что вы уже выбрали ячейку A1, и вы начинаете запись макроса в режиме относительной ссылки. Теперь вы выбираете ячейку A2, вводите текст Excel и нажмите клавишу Enter. Теперь, если вы запустите этот макрос, он не вернется в ячейку A2, вместо этого он будет перемещаться относительно активной ячейки. Например, если выбрана ячейка B3, она переместится на B4, запишет текст «Excel» и затем перейдет к ячейке K5.

Теперь давайте запишем макрос в режиме относительных ссылок:

  1. Выберите ячейку A1.
  2. Перейдите на вкладку «Разработчик».
  3. В группе «Код» нажмите кнопку «Относительные ссылки». Он будет подсвечиваться, указывая, что он включен.
  4. Нажмите кнопку «Запись макроса».
  5. В диалоговом окне «Запись макроса» введите имя для своего макроса. Например, имя «ОтносительныеСсылки».
  6. В опции «Сохранить в» выберите «Эта книга».
  7. Нажмите «ОК».
  8. Выберите ячейку A2.
  9. Введите текст «Excel» (или другой как вам нравится).
  10. Нажмите клавишу Enter. Курсор переместиться в ячейку A3.
  11. Нажмите кнопку «Остановить запись» на вкладке «Разработчик».

Макрос в режиме относительных ссылок будет сохранен.

Теперь сделайте следующее.

  1. Выберите любую ячейку (кроме A1).
  2. Перейдите на вкладку «Разработчик».
  3. В группе «Код» нажмите кнопку «Макросы».
  4. В диалоговом окне «Макрос» кликните на сохраненный макрос «ОтносительныеСсылки».
  5. Нажмите кнопку «Выполнить».

Как вы заметите, макрос записал текст «Excel» не в ячейки A2. Это произошло, потому что вы записали макрос в режиме относительной ссылки. Таким образом, курсор перемещается относительно активной ячейки. Например, если вы сделаете это, когда выбрана ячейка B3, она войдет в текст Excel — ячейка B4 и в конечном итоге выберет ячейку B5.

Вот код, который записал макрорекодер:

Обратите внимание, что в коде нет ссылок на ячейки B3 или B4. Макрос использует Activecell для ссылки на текущую ячейку и смещение относительно этой ячейки.

Не обращайте внимание на часть кода Range(«A1»). Это один из тех случаев, когда макрорекодер добавляет ненужный код, который не имеет никакой цели и может быть удален. Без него код будет работать отлично.

Что нельзя сделать с помощью макрорекодера?

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

  • Вы не можете выполнить код без выбора объекта. Например, если вы хотите, чтобы макрос перешел на следующий рабочий лист и выделил все заполненные ячейки в столбце A, не выходя из текущей рабочей таблицы, макрорекодер не сможет этого сделать. В таких случаях вам нужно вручную редактировать код.
  • Вы не можете создать пользовательскую функцию с помощью макрорекордера. С помощью VBA вы можете создавать пользовательские функции, которые можно использовать на рабочем листе в качестве обычных функций.
  • Вы не можете создавать циклы с помощью макрорекордера. Но можете записать одно действие, а цикл добавить вручную в редакторе кода.
  • Вы не можете анализировать условия: вы можете проверить условия в коде с помощью макрорекордера. Если вы пишете код VBA вручную, вы можете использовать операторы IF Then Else для анализа условия и запуска кода, если true (или другой код, если false).

Расширение файлов Excel, которые содержат макросы

Когда вы записываете макрос или вручную записываете код VBA в Excel, вам необходимо сохранить файл с расширением файла с поддержкой макросов (.xlsm).

До Excel 2007 был достаточен один формат файла — .xls. Но с 2007 года .xlsx был представлен как стандартное расширение файла. Файлы, сохраненные как .xlsx, не могут содержать в себе макрос. Поэтому, если у вас есть файл с расширением .xlsx, и вы записываете / записываете макрос и сохраняете его, он будет предупреждать вас о сохранении его в формате с поддержкой макросов и покажет вам следующее диалоговое окно:

Если вы выберете «Нет», Excel сохранить файл в формате с поддержкой макросов. Но если вы нажмете «Да», Excel автоматически удалит весь код из вашей книги и сохранит файл как книгу в формате .xlsx. Поэтому, если в вашей книге есть макрос, вам нужно сохранить его в формате .xlsm, чтобы сохранить этот макрос.

Источник

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

Обращение к конкретной ячейке

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

Полный путь к ячейке A1 в Книге1 на Листе1 можно записать двумя вариантами:

  • С помощью Range
  • С помощью Cells

Пример 1: Обратиться к ячейке A3 находящейся в Книге1 на Листе1

Workbooks("Книга1.xls").Sheets("Лист1").Range("A3") ' Обратиться к ячейке A3
Workbooks("Книга1.xls").Sheets("Лист1").Cells(3, 1) ' Обратиться к ячейке в 3-й строке и 1-й колонке (A3)

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

Пример 2: Обратиться к ячейке A1 в текущей книге на активном листе

Range("A1")
Cells(1, 1)

Если всё же путь к книге или листу необходим, но не хочется его писать при каждом обращении к ячейкам, можно использовать конструкцию With End With. При этом, обращаясь к ячейкам, необходимо использовать в начале «.» (точку).

Пример 3: Обратиться к ячейке A1 и B1 в Книге1 на Листе2.

With Workbooks("Книга1").Sheets("Лист2")
  ' Вывести значение ячейки A1, которая находится на Листе2
  MsgBox .Range("A1")
  ' Вывести значение ячейки B1, которая находится на Листе2
  MsgBox .Range("B1")
End With

Так же, можно обратиться и к активной (выбранной в данный момент времени) ячейке.

Пример 4: Обратиться к активной ячейке на Листе3 текущей книги.

Application.ActiveCell ' полная запись
ActiveCell ' краткая запись

Чтение значения из ячейки

Есть 3 способа получения значения ячейки, каждый из которых имеет свои особенности:

  • Value2 — базовое значение ячейки, т.е. как оно хранится в самом Excel-е. В связи с чем, например, дата будет прочтена как число от 1 до 2958466, а время будет прочитано как дробное число. Value2 — самый быстрый способ чтения значения, т.к. не происходит никаких преобразований.
  • Value — значение ячейки, приведенное к типу ячейки. Если ячейка хранит дату, будет приведено к типу Date. Если ячейка отформатирована как валюта, будет преобразована к типу Currency (в связи с чем, знаки с 5-го и далее будут усечены).
  • Text — визуальное отображение значения ячейки. Например, если ячейка, содержит дату в виде «число месяц прописью год», то Text (в отличие от Value и Value2) именно в таком виде и вернет значение. Использовать Text нужно осторожно, т.к., если, например, значение не входит в ячейку и отображается в виде «#####» то Text вернет вам не само значение, а эти самые «решетки».

По-умолчанию, если при обращении к ячейке не указывать способ чтения значения, то используется способ Value.

Пример 5: В ячейке A1 активного листа находится дата 01.03.2018. Для ячейки выбран формат «14 марта 2001 г.». Необходимо прочитать значение ячейки всеми перечисленными выше способами и отобразить в диалоговом окне.

MsgBox Cells(1, 1)        ' выведет 01.03.2018
MsgBox Cells(1, 1).Value  ' выведет 01.03.2018
MsgBox Cells(1, 1).Value2 ' выведет 43160
MsgBox Cells(1, 1).Text   ' выведет 01 марта 2018 г.

Dim d As Date
d = Cells(1, 1).Value2    ' числовое представление даты преобразуется в тип Date
MsgBox d                  ' выведет 01.03.2018

Пример 6: В ячейке С1 активного листа находится значение 123,456789. Для ячейки выбран формат «Денежный» с 3 десятичными знаками. Необходимо прочитать значение ячейки всеми перечисленными выше способами и отобразить в диалоговом окне.

MsgBox Range("C1")        ' выведет 123,4568
MsgBox Range("C1").Value  ' выведет 123,4568
MsgBox Range("C1").Value2 ' выведет 123,456789
MsgBox Range("C1").Text   ' выведет 123,457р.

Dim c As Currency
c = Range("C1").Value2    ' значение преобразуется в тип Currency
MsgBox c                  ' выведет 123,4568

Dim d As Double
d = Range("C1").Value2    ' значение преобразуется в тип Double
MsgBox d                  ' выведет 123,456789

При присвоении значения переменной или элементу массива, необходимо учитывать тип переменной. Например, если оператором Dim задан тип Integer, а в ячейке находится текст, при выполнении произойдет ошибка «Type mismatch». Как определить тип значения в ячейке, рассказано в следующей статье.

Пример 7: В ячейке B1 активного листа находится текст. Прочитать значение ячейки в переменную.

Dim s As String
Dim i As Integer
s = Range("B1").Value2 ' успех
i = Range("B1").Value2 ' ошибка

Таким образом, разница между Text, Value и Value2 в способе получения значения. Очевидно, что Value2 наиболее предпочтителен, но при преобразовании даты в текст (например, чтобы показать значение пользователю), нужно использовать функцию Format.

Запись значения в ячейку

Осуществить запись значения в ячейку можно 2 способами: с помощью Value и Value2. Использование Text для записи значения не возможно, т.к. это свойство только для чтения.

Пример 8: Записать в ячейку A1 активного листа значение 123,45

Range("A1") = 123.45
Range("A1").Value = 123.45
Range("A1").Value2 = 123.45

Все три строки запишут в A1 одно и то же значение.

Пример 9: Записать в ячейку A2 активного листа дату 1 марта 2018 года

Cells(2, 1) = #3/1/2018#
Cells(2, 1).Value = #3/1/2018#
Cells(2, 1).Value2 = #3/1/2018#

В данном примере тоже запишется одно и то же значение в ячейку A2 активного листа.

Визуальное отображение значения на экране будет зависеть от того, какой формат ячейки выбран на листе.

 

Lizard2

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

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

Здравствуйте ребята.

Подскажите как в макросе — назначить конкретную целевую ячейку.
Есть очень мудреный макрос, в котором ищется выход из лабиринта.
Из ячейки G9 — закрашивается путь к этому выходу.

Но мне нужно как-то задать этому макросу — в качестве цели — не какой-то выход, а конкретную ячейку — например ячейку AW12.
Подскажите — как это сделать ?

Прикрепленные файлы

  • 1.xlsm (34.35 КБ)

 

PDO

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

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

Как вариант загнать весь диапазон в массив, и начать сравнивать, в зависимости от положения начальной точки и каких-то условий двигаться, т.е. по сути производить сравнение элементов массива с конечной точкой, соответственно массив должен быть, как минимум двумерным (координаты х,у).

Обращение к ячейке Range(«AW12»)

Изменено: PDO20.04.2019 17:42:52

 

Sanja

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

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

#3

20.04.2019 17:30:24

Точнее

Код
Range("AW12")

Согласие есть продукт при полном непротивлении сторон.

 

Sanja

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

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

Пишите макросы с WinAPI, а как к ячейке обратиться не знаете!?

Согласие есть продукт при полном непротивлении сторон.

 

Lizard2

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

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

PDO, понятно.
А как это сделать ?

 

Ivan.kh

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

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

в моделе листа найти  —- MChWave [G9]   …. дальше думаю понятно

Изменено: Ivan.kh20.04.2019 18:41:44

 

Lizard2

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

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

Ivan.kh,[G9] — это точка начала пути.

Я же спрашивал — как задать конечную ячейку (то есть [AW12]) ?

 

Ivan.kh

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

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

Ну так и сделайте выход в той ячейке …

 

Lizard2

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

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

Ivan.kh, нет, мне этот адрес — нужно именно задать.
Чтобы алгоритм просто двигал бы ячейку к конкретному адресу, а не искал выход откуда-то.

 

Ivan.kh

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

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

Где Вы его задавать собираетесь?

Изменено: Ivan.kh20.04.2019 19:07:53

 

Ivan.kh

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

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

Там так написано, что он ищет именно выход.
Если нужно что-то другое — переписывайте алгоритм

 

Lizard2

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

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

#12

20.04.2019 19:36:51

Цитата
Ivan.kh написал:
Где Вы его задавать собираетесь?

Ivan.kh

, я не знаю.
Это мой вопрос в первом сообщении — где его задавать ?

Изменено: Lizard220.04.2019 19:37:12

 

Ivan.kh

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

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

Lizard2, Я Вам дал ответ, он в коде явно не задается … он вычисляется/определяется …  в том то и суть лабиринта … его можно изменить поменяв выход, что я Вам и показал на скрине

 

Lizard2

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

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

Ivan.kh, ну понятно.

А как без лабиринта обойтись, чтобы ячейка просто шла к конкретной цели.
Мне не нужен лабиринт, я поэтому и спрашиваю.
Как подобный макрос должен выглядеть ?

 

Ivan.kh

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

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

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

 

Lizard2

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

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

#16

20.04.2019 21:16:21

Цитата
Ivan.kh написал:
описывайте, по какому маршруту

Ivan.kh, имеется ввиду маршрут от ячейки G9 к целевой ячейке AW12, с огибанием препятствий.

Вот вы бы какой алгоритм предложили ?
У вас есть какая-нибудь теория на этот счет ?

 

Ivan.kh

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

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

Есть теория. если применять к примеру лабиринта, то в процедуре MChWave:
Изменить mx на колонку W
И если в цикле дошли до колонки W, то все ячейки кроме 12 приравниваем к препятствию …

 

Lizard2

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

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

#18

20.04.2019 22:48:45

Цитата
Ivan.kh написал:
Изменить mx на колонку W

Вы имеете ввиду mx = UBound(a, 2)

А что за колонку в нее вписывать (в смысле столбец W) ?
Почему именно этот столбец, чем он отличается от других  ?

 

Ivan.kh

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

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

Lizard2, ошибся не W, а AW

 

Lizard2

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

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

#20

20.04.2019 23:33:58

Цитата
Ivan.kh написал:
Изменить mx на колонку AW

А как эту переменную изменить ?

Я вот заменил ее с
   mx = UBound(a, 2)
На
   mx = Range(«AW:AW»)

Что-то не работает.

 

Александр

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

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

#21

21.04.2019 00:19:28

Lizard2,
как вариант вставить до начала выполнения всего

Код
Range("aw6:aw32")=1
Range("aw12")=""

у меня простая версия Экселя, в ней нет кнопки «Прочитать мысли и сгенерировать файл пример»

 

Ivan.kh

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

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

Александр, это будет тоже, что я предлагал в

8 посте

Lizard2, Вы понимаете, для чего в коде используется переменная mx? в нее помещена граница лабиринта (правая) — число. Вы в нее запихиваете диапазон ячеек …

Для чего нужно Вам необходима прорисовка маршрута в ячейку AW12?

Изменено: Ivan.kh21.04.2019 08:40:41

 

Lizard2

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

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

#23

21.04.2019 11:31:35

Ivan.kh, а как тогда записать ?

Пробовал вот так

Код
mx = UBound([AW].Column, 2)
и вот так
mx = UBound([AW].Column)
mx = UBound([AW12].Column)
mx = UBound([AW12].Column, 2)

Все равно не работает.

 

Lizard2

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

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

 

Ivan.kh

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

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

Вы так и не ответили для чего это нужно?
Сделал проще (в лоб, на основании советов по изменению границ лабиринта, т.к. лень ковыряться в циклах)

 

Lizard2

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

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

#26

22.04.2019 13:22:37

Цитата
Ivan.kh написал:
Вы так и не ответили для чего это нужно?

Чтобы прочертить аналогичный путь — не привязываясь к границам лабиринта.

Цитата
Ivan.kh написал:
по изменению границ лабиринта

Мой вопрос заключался в том — что нет границ лабиринта и лабиринта самого нет. Их вообще нет, ни с измененным цветом или обозначенными другим образом.
Есть только начальная ячейка, конечная ячейка и препятствия между ними.

 

Ivan.kh

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

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

Lizard2, Ну так показывайте пример структуры реального задания, что там за препятствия и т.д.
З.Ы. Я понимаю что нужно прочертить аналогичный путь, мне не понятны прикладная польза — зачем этот путь строить…

 

CATS

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

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

Прошу прощения возможно тупой ответ, а это не подходит? Application.ThisWorkbook.Sheets(1).Cells(4, 8)
Смайлик рисует там 4, 8 ) без пробела последнего
4 и 8 это получается строка и столбец
вначале столбец после строка
в данном случае: Application.ThisWorkbook.Sheets(1).Cells(56, 14)

Изменено: CATS22.04.2019 13:36:11

 

Lizard2

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

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

#29

22.04.2019 13:31:43

Цитата
Ivan.kh написал:
показывайте пример структуры реального задания, что там за препятствия и т.д.

Так вот же они — показаны.
Это вот эти вертикальные черточки, которые путь огибает.

Цитата
Ivan.kh написал:
прикладная польза — зачем этот путь строить.

Цель — практическое применение данного алгоритма в задачах другого типа (не связанных с поиском выхода из лабиринта).

 

Ivan.kh

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

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

#30

22.04.2019 13:42:30

Вы же Сами указали, что это не реальная структура. У Вас не лабиринт, а что тогда?
Я на этом примере могу показать как выйти в конкретной точке см. вложение…

Прикрепленные файлы

  • !!!!!!!!!!!!!!.xlsm (33.67 КБ)

всем привет!

у меня наверное глупый вопрос, но все же, как назначить макрос на простую ячейку, т.е. не на какой-либо объект, а именно на

простую

ячейку, в которой написан текст.

никак не могу понять как это сделать. excel 2007.

заранее спасибо


Цитата: Jim от 14.03.2011, 13:13
всем привет!

у меня наверное глупый вопрос, но все же, как назначить макрос на простую ячейку, т.е. не на какой-либо объект, а именно на

простую ячейку, в которой написан текст.

никак не могу понять как это сделать. excel 2007.

заранее спасибо

Судя по всему: Событие

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

End Sub

Путей к вершине — множество. Этот один из многих!


я не силен в макросах..
можете выложить какой-нить пример.
буду очень благодарен


Вот код:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    Dim stroka As String

    nR = Target.Row
    nC = Target.Column

        If nC > 5 Or nR <> 3 Then: Cancel = True: Exit Sub

    stroka = Trim(Cells(nR, 1).Text)

        Select Case Sh.Name
        Case «ZajawKOM»
            If Len(stroka) > 12 Then

                                MsgBox «Нет ФИО подотчетника, для преобразования его в Фамилия И.О.!», vbInformation + vbOKOnly, «До свидания!»: Exit Sub

                                fio = famIO(Mid(stroka, 13))

                                Application.EnableEvents = False

                                Cells(12, 1) = «Подотчетник: _______________________________ / » & fio & » /»

                                Application.EnableEvents = True

                                fio = «»
            End If
    End Select
End Sub

На скрепке пример. Пошагово отследите нажатие на кнопку Сохранить. Увы, пришлось выложить проект. Если нужно подготовлю пример специально.

Путей к вершине — множество. Этот один из многих!


Может так понятней будет!

Может и я на что сгожусь … Если сгодился, можете меня по+благодарить+.


Цитата: Wasilic от 14.03.2011, 21:23
Может так понятней будет!

Полагаю, что Вы правы, ув. Wasilic!
Если не против, добавлю к Вашему примеру следующее:
Ваш код:
Private Sub Worksheet_Change(ByVal Target As Range)
   AD = Target.Address ‘Адрес ячейки
   KL = Target.Column  ‘ № КОЛОНКИ
   ST = Target.Row     ‘ № СТРОКИ
   SD = Target        ‘ Содержание ячейки
   ‘с этими данными и пляшем
   MsgBox «АДРЕС ячейки — » & Target.Address
   MsgBox «номер СТРОКИ — » & Target.Row
   MsgBox «номер КОЛОНКИ — » & Target.Column
   MsgBox «содержание ячейки — » & Target
   ‘AA = Cells(10, 10).Address ‘Адрес ячейки в 10-й строке и 10-й колонки
   ‘MsgBox AA
End Sub

если его записать не в модуль листа, а в модуль «ЭтаКнига», при том что он будет выполнять то же самое — реагировать на изменение состояния ячейки, позволит ползователю, если нужно, сохранять лист БЕЗ МАКРОСОВ! А это иногда оч. актуально. Например при пересылке листа с информацией из одной книги в другую, где с теми же ячейками будут работать другие макросы (или другой пользователь «добъет» задачу формулами листа), ну или для того что бы заполнить форму и сохранить ее в качестве отчетного документа в отдельном файле, где какая-либо обработка не желательна.
Ну, вообщем, ситуации могут быть самые разные. А организовать код можно так:

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
   ‘Установим общие условия для любого листа: _
    определим номер строки столбца ячейки в которой произошли изменения:
    nR = Target.Row     ‘- номер строки
    nC = Target.Column  ‘- номер колонки
   ‘Для разных листов книги зададим разные условия выполнения
   Select Case Sh.Name
        Case «Лист1»
            ‘на этом листе, нас будет интересовать состояние ячеек _
             в 3-й колонке («C») и с 4-й строки:
             If nR > 4 And nC = 3 Then
                MsgBox «Диапазон: строка = » & nR & «;» & Chr(10) & _
                       »          колонка = » & nC, vbInformation + vbOKOnly, «Я работаю в заданном диапазоне!»
             End If
             ‘если же мы планируем отслеживать изменения во множестве строк-столбцов листа, _
              то по такой конструкции (можно, конечно и с If … End If -ами сделать):
             Select Case nC
                Case 3
                    If nR > 4 Then
                        MsgBox «Диапазон: строка = » & nR & «;» & Chr(10) & _
                               »          колонка = » & nC, vbInformation + vbOKOnly, «Я работаю в заданном диапазоне!»
                    End If
                Case 5
                    If nR = 5 Then
                        MsgBox «Ячейка:   строка = » & nR & «;» & Chr(10) & _
                               »          колонка = » & nC, vbInformation + vbOKOnly, «Я работаю в заданной ячейке!»
                    End If
             End Select
        Case «Лист2»
            ‘то что хотим выполнить
        Case «_»
            ‘то что хотим выполнить
   End Select
End Sub

Просто скопируйте код в модуль «ЭтаКнига». И добавте в книгу листы с именами «Лист2» и «_».

Путей к вершине — множество. Этот один из многих!


Зачастую требуется в функциях ввести дополнительный параметр, где пользователь может задать ссылку на ячейку
(например, место для вставки данных)

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

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

Sub ПримерИспользования_GetCell()
    ' вставляем значение в первую пустую ячейку столбца A
    ' (вставка производится ниже всех данных в первом столбце листа)
    GetCell("a").Value = Now
 
    ' то же самое, но с другими вариантами параметра функции (все 4 способа равнозначны)
    GetCell("a:a").Value = 111
    GetCell(Columns(1)).Value = 222
    GetCell([a:a]).Value = 333
 
    '  ============ вставка в первую незаполненную ячейку третьей строки =================
    GetCell(Destination:=3).Value = 1
    ' то же самое, но с другими вариантами параметра функции (все 4 способа равнозначны)
    GetCell("3").Value = 2
    GetCell(Rows(3)).Value = 3
    GetCell([3:3]).Value = 4
 
    '  ============ другие варианты использования =================
    GetCell().Value = "активная ячейка"    ' вставка в заданную ячейку (вызов без параметра)
    GetCell("NewSheet").Value = "на новый лист в ячейку A1"    ' создаётся новый лист
    GetCell("NewWorkbook").Value = "в новую книгу в ячейку A1"    ' создаётся новая книга Excel
End Sub

Как вы заметили, в качестве параметра функции можно использовать предопределённые текстовые константы «NewSheet» и «NewWorkbook«

Код функции GetCell:

Function GetCell(Optional ByRef Destination As Variant) As Range
    ' Функция получает в качестве параметра ссылку на диапазон
    ' Возвращает ячейку для вставки данных в зависимости от параметра:
    '   если параметр не задан - возвращается активная ячейка текущей книги
    '   если параметр является ссылкой на ячейку - возвращается эта ячейка
    '   если параметр является ссылкой на строку - возвращается первая незаполненная ячейка этой строки
    '   если параметр является ссылкой на столбец - возвращается первая незаполненная ячейка этого столбца

    On Error Resume Next: Err.Clear
    If IsMissing(Destination) Then
        If ActiveWorkbook Is Nothing Then Workbooks.Add(xlWBATWorksheet).Worksheets(1).Name = "Данные"
        Set GetCell = ActiveCell: Exit Function
    End If
 
    If Not IsObject(Destination) Then If IsNumeric(Destination) Then Destination = Val(Destination)
 
    Select Case TypeName(Destination)
        Case "String"
            If Destination = "NewWorkbook" Then Workbooks.Add(xlWBATWorksheet).Worksheets(1).Name = "Данные"
            If ActiveWorkbook Is Nothing Then Workbooks.Add(xlWBATWorksheet).Worksheets(1).Name = "Данные"
 
            If Destination = "NewSheet" Then ActiveWorkbook.Worksheets.Add , ActiveSheet
 
            Set GetCell = Range(Destination)
            If Err.Number = 1004 Then
                If Destination Like String(Len(Destination), "[A-z]") Then _
                   Err.Clear: Set GetCell = Range(Destination & ":" & Destination)
                'Debug.Print Err.Number, Err.Description
                If Err Then Set GetCell = ActiveCell: Exit Function    ' неопознанная ошибка
            End If
        Case "Integer", "Long", "Double"
            If ActiveWorkbook Is Nothing Then Workbooks.Add(xlWBATWorksheet).Worksheets(1).Name = "Данные"
            Err.Clear: If Val(Destination) > 0 Then Set GetCell = Rows(Val(Destination))
            If Err Then Set GetCell = ActiveCell: Exit Function    ' неопознанная ошибка

        Case "Range": Set GetCell = Destination
        Case "Workbook": Set GetCell = Destination.Worksheets(1).[a:a]
        Case "Worksheet": Set GetCell = Destination.[a:a]
 
        Case Else
            Debug.Print "Another parameter type: ", TypeName(Destination)
            Set GetCell = ActiveCell: Exit Function    ' неопознанная ошибка
    End Select
 
    If GetCell Is Nothing Then Set GetCell = ActiveCell: Exit Function
    Select Case True
        Case GetCell.Address = GetCell.EntireColumn.Address
            Set GetCell = GetCell.Columns(1).Cells(GetCell.Rows.Count).End(xlUp).Offset(1)
        Case GetCell.Address = GetCell.EntireRow.Address
            Set GetCell = GetCell.Rows(1).Cells(GetCell.Columns.Count).End(xlToLeft).Offset(, 1)
        Case Else: Set GetCell = GetCell.Cells(1)
 
    End Select
End Function

Понравилась статья? Поделить с друзьями:
  • Макросов в excel по выгрузке данных
  • Макросы excel для openoffice
  • Макрос удаляющий листы excel
  • Макросов microsoft word скачать бесплатно для windows 10
  • Макросы excel для android