If not intersect target excel

Пометка элементов списка

Постановка задачи

Имеем на листе список чего-либо. Хотелось бы использовать привычные флажки-чекбоксы или жирные точки-переключатели для отмечания выбранных элементов. Примерно так:

checkboxes-animate.gif

Решение

Щелкните правой кнопкой мыши по ярлычку листа, где находится список, и выберите в контекстном меню Исходный текст (Source Code). Вы должны попасть в редактор Visual Basic.

Скопируйте туда этот код:

'Ставим флажок, если был одиночный щелчок по ячейке
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.Cells.Count > 1 Then Exit Sub
        If Not Intersect(Target, Range("A2:A100")) Is Nothing Then
            Application.EnableEvents = False
            Target.Font.Name = "Marlett"
            Target = "a"
            Application.EnableEvents = True
        End If
End Sub 

'Снимаем флажок, если был двойной щелчок по ячейке
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    If Not Intersect(Target, Range("A2:A100")) Is Nothing Then
        Application.EnableEvents = False
        Cancel = True
        Target.ClearContents
        Application.EnableEvents = True
    End If
End Sub

Первая половина кода проверяет, не было ли одиночного щелчка по ячейкам в диапазоне A2:A100 и если был — то ставит «галочку» — знак, который в шрифте Marlett находится на букве «а». Вторая половина этого кода снимает флажок при двойном щелчке по ячейке. При необходимости замените в этом коде «A2:A100» на Ваш диапазон.

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

=СЧЁТЕСЛИ(A2:A100;»a»)

 =COUNTIF(A2:A100;»a») 

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

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.Cells.Count > 1 Then Exit Sub
        If Not Intersect(Target, Range("A2:A100")) Is Nothing Then
            Application.EnableEvents = False
            Range("A2:A100").ClearContents
            Target.Font.Name = "Marlett"
            Target = "h"
            Application.EnableEvents = True
        End If
End Sub

Этот макрос сначала полностью очищает наш столбец А, а потом вводит в текущую ячейку букву «h», которая в шрифте Marlett даст нам характерный символ выбора по типу «один-из» – жирную точку. Два таких символа поставить, таким образом, не получится – доступен будет только выбор одного элемента из списка. Чтобы извлечь выбранный элемент, можно использовать стандартную функцию ВПР (VLOOKUP), которая будет искать символ точки (т.е. букву «h») в первом столбце нашей таблицы и, найдя, выдавать фамилию из второго:

checkboxes2.png

Ссылки по теме

  • Маркированные и нумерованные списки в Excel как в Word
  • Что такое макрос? Куда вставлять код макроса на VBA? Как их использовать?
  • Что такое функция ВПР (VLOOKUP), как ее использовать для подстановки значений

Событие Worksheet.SelectionChange, используемое в VBA Excel для запуска процедур при выборе диапазона на рабочем листе, в том числе отдельной ячейки.

Синтаксис процедуры, выполнение которой инициируется событием Worksheet.SelectionChange:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

‘Операторы процедуры

End Sub

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

Аргумент Target — это новый выбранный диапазон на рабочем листе.

Шаблон процедуры можно скопировать и вставить в модуль рабочего листа, но не обязательно. Если открыть модуль нужного листа, выбрать в левом верхнем поле объект Worksheet, шаблон процедуры будет добавлен автоматически:

Выбор события Worksheet.SelectionChange в модуле рабочего листа

У объекта Worksheet есть и другие события, которые можно выбрать в правом верхнем поле модуля рабочего листа. Процедура с событием SelectionChange добавляется по умолчанию.

Примеры кода с Worksheet.SelectionChange

Пример разработчика

Замечательный пример дан на сайте разработчика:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

   With ActiveWindow

      .ScrollRow = Target.Row

      .ScrollColumn = Target.Column

   End With

End Sub

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

Эта процедура работает и при выборе ячейки через адресную строку (слева над обозначениями столбцов), и при выборе из кода VBA Excel, например:

Выбор одной отдельной ячейки

Инициируем выполнение основных операторов процедуры с событием Worksheet.SelectionChange выбором одной отдельной ячейки:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    If Target.Address = «$E$5» Then

        MsgBox «Выбрана ячейка E5»

    End If

End Sub

Основной оператор MsgBox "Выбрана ячейка E5" будет выполнен при выборе ячейки E5.

Примечание:
В условии примера используется свойство Address переменной Target, так как в прямом выражении Target = Range("E5") по умолчанию сравниваются значения диапазонов. В результате этого, при выборе другой ячейки со значением, совпадающим со значением ячейки E5, равенство будет истинным и основные операторы будут выполнены, а при выборе более одной ячейки, будет сгенерирована ошибка.

Выбор диапазона с заданной ячейкой

Выполнение основных операторов процедуры при вхождении заданной ячейки в выбранный диапазон:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    If Not Intersect(Target, Range(«B3»)) Is Nothing Then

        MsgBox «Ячейка B3 входит в выбранный диапазон»

    End If

End Sub

Основной оператор MsgBox "Ячейка B3 входит в выбранный диапазон" будет выполнен при выделении диапазона, в который входит ячейка B3, в том числе и при выделении одной этой ячейки.

Выбор ячейки в заданной строке

Инициируем выполнение основных операторов процедуры с событием Worksheet.SelectionChange выбором любой отдельной ячейки во второй строке:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    If Target.Count > 1 Then Exit Sub

        If Target.Row = 2 Then

            MsgBox «Выбрана ячейка во второй строке»

        End If

End Sub

Дополнительный оператор If Target.Count > 1 Then Exit Sub необходим для выхода из процедуры при выделении более одной ячейки. Причина: при выделении произвольного диапазона, ограниченного сверху второй строкой, выражение Target.Row = 2 будет возвращать значение True, и операторы в блоке If ... End If будут выполнены.

Ввод даты в ячейку первого столбца

Автоматическое добавление текущей даты в выбранную ячейку первого столбца при условии, что предыдущая ячейка сверху не пустая, а ячейка снизу – пустая:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    If Target.Count > 1 Or Target.Row = 1 Or Target.Row = ActiveSheet.Rows.Count Then Exit Sub

        If Target.Column = 1 And Target.Offset(1, 0) <> «» And Target.Offset(1, 0) = «» Then

            Target = Format(Now, «DD.MM.YYYY»)

        End If

End Sub

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

Условие If Target.Count > 1 Or Target.Row = 1 Or Target.Row = ActiveSheet.Rows.Count Then Exit Sub завершает процедуру при выборе более одной ячейки, при выборе ячейки A1 и при выборе последней ячейки первого столбца.

Выбор ячейки A1 приводит к ошибке при проверке условия Target.Offset(-1, 0) <> "", так как происходит выход за границы диапазона рабочего листа.

Ошибка выхода за пределы рабочего листа происходит и при проверке условия Target.Offset(1, 0) = "", если выбрать последнюю ячейку первой колонки.

Примечание:
Текущая дата будет введена в следующую пустую ячейку первого столбца при переходе к ней от заполненной в том числе нажатием клавиши «Enter».

Пример без отслеживания Target

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

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    If [B1] > 100 Then

        [A1].Interior.Color = vbGreen

    Else

        [A1].Interior.Color = vbBlue

    End If

End Sub

После ввода значения в ячейку B1, можно нажать Enter или кликнуть по любой другой ячейке рабочего листа, и событие Worksheet.SelectionChange сработает.


Прошу помочь разобраться в макросе с Target и Intersect

light26

Дата: Четверг, 26.04.2012, 22:01 |
Сообщение № 1

Группа: Друзья

Ранг: Старожил

Сообщений: 1341


Репутация:

91

±

Замечаний:
0% ±


2007, 2010, 2013

Всем привет.
[vba]

Code

Private Sub Worksheet_Change(ByVal Target As Range)       ‘тут не совсем понятно
         If Target.Cells.Count > 1 Then Exit Sub                    ‘тут совсем не понятно
           If Not Intersect(Target, Range(«A:A»)) Is Nothing Then                  ‘тут ясно, что следим за изменениями в столбце А. Хотелось бы подробней
              With Target(1, 5)                    ‘тут указываем ячейку, куда будут вводиться результат вычисления следующей строки
                .Value = Now                    ‘если по-русски, то =ТДАТА()
                 Columns(«e:e»).NumberFormat = «[$-F400]h:mm:ss AM/PM»  ‘формат ячеек столбца Е — время (ч,мм,сс). Только вот что значит [$-F400]?
                 .EntireColumn.AutoFit                    ‘автовыравнивание
              End With
                With Target(1, 6)                    ‘
                   .Value = Now                    ‘
                    Columns(«f:f»).NumberFormat = «d/m/yyyy»                       ‘формат ячеек столбца F — дата (д,м,ггг)
                   .EntireColumn.AutoFit                    ‘
                End With
               End If
            End Sub

[/vba]
Вот что у меня получилось после доработки уже готового макроса строками, полученными в результате использования макрорекордера
Для пущей ясности прошу знатоков разъяснить вопросы, которые я указал выше.
Спасибо.


Я не волшебник. Я только учусь

Сообщение отредактировал light26Пятница, 27.04.2012, 14:43

 

Ответить

Саня

Дата: Пятница, 27.04.2012, 01:27 |
Сообщение № 2

Группа: Друзья

Ранг: Ветеран

Сообщений: 1067


Репутация:

560

±

Замечаний:
0% ±


XL 2016

вот твой код:
[vba]

Code

‘ это обработчик события изменений на листе, _
    Target — это диапазон, который был изменен
Private Sub Worksheet_Change(ByVal Target As Range)
‘ если изменили диапазон, состоящий более чем из одной ячейки, то выходим
      If Target.Cells.Count > 1 Then Exit Sub

      ‘тут ясно, что следим за изменениями в столбце А. Хотелось бы подробней…
      ‘…пересечение Таргета с первым столбцом не есть ничто, _
        т.е., есть что-то, т.е., Таргет пересекается с 1-м столбцом
      If Not Intersect(Target, Range(«A:A»)) Is Nothing Then
          »’If Target.Column = 1 Then ‘ я бы так написал, т.к. Таргет — это одна ячейка, на этой строчке уже точно!

          With Target(1, 5)  ‘тут указываем ячейку, куда будут вводиться результат вычисления следующей строки
              ‘ Target(1, 5) — трудноинтерпретируемое выражение, для меня во всяком случае. _
                 более осмысленно было бы: Target.Offset(0,4) _
                 или Target.Offset(,4)   <— это тот же х… только сбоку  

              ‘строка (***) вызовет этот обработчик еще раз, я думаю, это не планировалось, _
                поэтому здесь нужно отключить события
              Application.EnableEvents = False    ‘ <==================
              .Value = Now   ‘если по-русски, то =ТДАТА()               (***)
              Application.EnableEvents = True    ‘ <================== включаем обратно!

              Columns(«e:e»).NumberFormat = «[$-F400]h:mm:ss AM/PM»  ‘формат ячеек столбца Е — время (ч,мм,сс). Только вот что значит [$-F400]?
              .EntireColumn.AutoFit   ‘автовыравнивание   (АВТОПОДБОР ШИРИНЫ СТОЛБЦА)
          End With

          With Target(1, 6)
              Application.EnableEvents = False    ‘ <==================
              .Value = Now
              Application.EnableEvents = True    ‘ <================== включаем обратно!
              Columns(«f:f»).NumberFormat = «d/m/yyyy»  ‘формат ячеек столбца F — дата (д,м,ггг)
              .EntireColumn.AutoFit
              ‘ Columns(«f:f») в этом контексте идентично .EntireColumn _
               при каждом изменении листа каждый раз задавать формат одного и того же столбца _
               это неразумно, меняй формат только одной ячейки
          End With
      End If
End Sub

[/vba]

предложу как вариант
[vba]

Code

Private Sub Worksheet_Change(ByVal Target As Range)
      If Target.Cells.Count > 1 Then Exit Sub

      If Target.Column = 1 Then
          Application.EnableEvents = False
          With Target
              With .Offset(, 4)
                  .Value = Time
                  .NumberFormat = «[$-F400]h:mm:ss AM/PM»
                  .EntireColumn.AutoFit
              End With

                              With .Offset(, 5)
                  .Value = Date
                  .NumberFormat = «d/m/yyyy»
                  .EntireColumn.AutoFit
              End With
          End With
          Application.EnableEvents = True
      End If
End Sub

[/vba]

 

Ответить

Alex_ST

Дата: Пятница, 27.04.2012, 09:46 |
Сообщение № 3

Группа: Друзья

Ранг: Участник клуба

Сообщений: 3176


Репутация:

604

±

Замечаний:
0% ±


2003

Да уж, Вадим, по поводу Target(1, 5) и Target(1, 6) когда Target — одна ячейка, это уж как-то не очень корректно. Правильно сказал Саша, что корректнее использовать Offset
Саш, я тут на досуге твой код для Вадима откомментировал. Надеюсь, ты не против?
[vba]

Code

Private Sub Worksheet_Change(ByVal Target As Range)   ‘ обработка события изменения на листе
    If Target.Cells.Count > 1 Then Exit Sub   ‘ если изменение было больше, чем в одной ячейке — выход
‘ дальше Target — это одна ячейка
    If Target.Column = 1 Then   ‘ если Target (изменение на листе) в первом столбце (столбце А)
       Application.EnableEvents = False   ‘ запретить обработку событий чтобы производимые далее изменения на листе не приводили к повторному циклическому вызову этой же процедуры
       With Target.Offset(0, 4)   ‘ в ячейке, сдвинутой от ячейки Target на 0 строк и 4 столбца (т.е. с столбце Е)
          .Value = Time   ‘ значение — текущее время
          .NumberFormat = «h:mm:ss»   ‘ формат представления чисел в ячейке (время в 24-часовом формате ч:мм:сс)
          .EntireColumn.AutoFit   ‘ во всём столбце установить выравнивание «Автоподбор ширины»
       End With

       With Target.Offset(0, 5)  ‘ в ячейке, сдвинутой от ячейки Target на 0 строк и 5 столбцов (т.е. с столбце F)
          .Value = Date  ‘ значение — текущая дата
          .NumberFormat = «d/m/yyyy»   ‘ формат представления чисел в ячейке (дата Д.М.ГГГГ)
          .EntireColumn.AutoFit  ‘ во всём столбце установить выравнивание «Автоподбор ширины»
       End With
       Application.EnableEvents = True   ‘ разрешить обработку событий
    End If
End Sub

[/vba]



С уважением,
Алексей
MS Excel 2003 — the best!!!

 

Ответить

RAN

Дата: Пятница, 27.04.2012, 10:12 |
Сообщение № 4

Группа: Друзья

Ранг: Экселист

Сообщений: 5645

Quote (Alex_ST)

Target(1, 6) когда Target — одна ячейка, это уж как-то не очень корректно

Это еще мягко сказано.
Когда Target = [A1:F2], то Target(1, 6) = [F1] б/м понятно
A вот когда Target = [A1], и Target(1, 6) = [F1] ???


Быть или не быть, вот в чем загвоздка!

 

Ответить

light26

Дата: Пятница, 27.04.2012, 14:36 |
Сообщение № 5

Группа: Друзья

Ранг: Старожил

Сообщений: 1341


Репутация:

91

±

Замечаний:
0% ±


2007, 2010, 2013

Безусловно, огромное спасибо, господа.
Но… Ряд вопросов остался без ответа, ряд разъяснений так и остался за пределами моего понимания, а на ряд ответов возникли новые вопросы )))
Это ни в коем случае, не упрек в ваш адрес. Это обоснование причин, по которым я продолжаю диалог на эту тему smile
Итак:
В строке Columns(«e:e»).NumberFormat = «[$-F400]h:mm:ss AM/PM» что же все-таки значит [$-F400]? (эта строка получена в результате применения макрорекордера, — включил макрорекордер, изменил свойства ячейки, остановил запись, отредактировал, вставил в имеющийся код)
Что касается:

Quote (RAN)

Когда Target = [A1:F2], то Target(1, 6) = [F1] б/м понятно
A вот когда Target = [A1], и Target(1, 6) = [F1]

Это просто грубая ошибка или такая запись вообще не приемлема, т.к. может в дальнейшем привести к ошибке?

Quote (Alex_ST)

If Target.Cells.Count > 1 Then Exit Sub ‘ если изменение было больше, чем в одной ячейке — выход
‘ дальше Target — это одна ячейка

Как понять «если изменение было больше, чем в ОДНОЙ ячейке»?

Quote (Alex_ST)

Application.EnableEvents = False ‘ запретить обработку событий чтобы производимые далее изменения на листе не приводили к повторному циклическому вызову этой же процедуры

Тут совсем не понял. Без этой строки (по крайней мере в моем макросе) все работает так же, как и с этой строкой. Можно разжевать, в рот положить и еще и проглотить помочь ))) про эту строку макроса?
в чем разница между

Quote (Саня)

NumberFormat = «[$-F400]h:mm:ss AM/PM»

и

Quote (Alex_ST)

.NumberFormat = «h:mm:ss»

Ну и с этой строкой я так ничего и не понял

Quote (Саня)

If Not Intersect(Target, Range(«A:A»)) Is Nothing Then


Я не волшебник. Я только учусь

Сообщение отредактировал light26Пятница, 27.04.2012, 14:39

 

Ответить

Serge_007

Дата: Пятница, 27.04.2012, 14:44 |
Сообщение № 6

Группа: Админы

Ранг: Местный житель

Сообщений: 15888


Репутация:

2623

±

Замечаний:
±


Excel 2016

Quote (light26)

что же все-таки значит [$-F400]

Это код формата локали твоего Excel


ЮMoney:41001419691823 | WMR:126292472390

 

Ответить

Hugo

Дата: Пятница, 27.04.2012, 14:46 |
Сообщение № 7

Группа: Друзья

Ранг: Участник клуба

Сообщений: 3140


Репутация:

670

±

Замечаний:
0% ±


2010, теперь уже с PQ

Про [$-F400] читаем первоисточник:
http://office.microsoft.com/en-us….35.aspx

Про Application.EnableEvents = False — это только кажется, что работает как и без неё. Вы пошагово выполните код — увидите, что на изменение, вызванное кодом, сам же код и реагирует, но проверку это изменение не проходит.
Иначе бы оно зациклилось. Но зачем нам код гонять впустую?

«Как понять «если изменение было больше, чем в ОДНОЙ ячейке»? » — закопипастили например диапазон 10х10…

[vba]

Code

If Not Intersect(Target, Range(«A:A»)) Is Nothing Then

[/vba]
Если Не Пересечение(Цель, Диапазон) Есть Ничего То
=
Если Не (Пересечение(Цель, Диапазон) Есть Ничего) То
сокращаем как в алгебре:
Если Пересечение(Цель, Диапазон) Есть То


excel@nxt.ru
webmoney: R418926282008 Z422237915069

 

Ответить

RAN

Дата: Пятница, 27.04.2012, 15:00 |
Сообщение № 8

Группа: Друзья

Ранг: Экселист

Сообщений: 5645

Quote (light26)

Как понять «если изменение было больше, чем в ОДНОЙ ячейке»?

Так и понимай. Скопировал 4 ячейки, вставил. Сколько изменилось? 1 или 4?
Если строки
[vba]

Code

If Target.Cells.Count > 1 Then Exit Sub

[/vba]
нет, то при изменении сразу 4 ячеек макрос сработает, а если есть — не сработает.

Application.EnableEvents — изменения происходят не в столбце А, поэтому и без отключения обработки событий повторного запуска макроса не видно.

[vba]

Code

If Not Intersect(Target, Range(«A:A»)) Is Nothing Then

[/vba]

Переводю! biggrin

Если Не пересечение(изменяемого диапазона, столбца «А») отсутствует, Тогда…


Быть или не быть, вот в чем загвоздка!

 

Ответить

light26

Дата: Пятница, 27.04.2012, 15:05 |
Сообщение № 9

Группа: Друзья

Ранг: Старожил

Сообщений: 1341


Репутация:

91

±

Замечаний:
0% ±


2007, 2010, 2013


Ага я по-английски только yes знаю как переводится. )))


Я не волшебник. Я только учусь

 

Ответить

RAN

Дата: Пятница, 27.04.2012, 15:21 |
Сообщение № 10

Группа: Друзья

Ранг: Экселист

Сообщений: 5645

Тогда изучай 1С.
Там весь код на русском! biggrin


Быть или не быть, вот в чем загвоздка!

 

Ответить

Alex_ST

Дата: Пятница, 27.04.2012, 15:24 |
Сообщение № 11

Группа: Друзья

Ранг: Участник клуба

Сообщений: 3176


Репутация:

604

±

Замечаний:
0% ±


2003

Вадим,
1. Запись Target(1, 5) означает ячейку, находящуюся в ДИАПАЗОНЕ ЯЧЕЕК Target в первой строке и пятом столбце.
НО ведь у вас в первом же операторе если в Target больше, чем 1 ячейка — выход. Т.е. Target — это ОДНА ЯЧЕЙКА. И о какой тогда ячейке идёт речь в записи Target(1, 5) если там нет ни столбцов, ни строк?
Самое интересное и непонятное, что я сейчас попробовал и выяснил, что [vba][/vba] не понятно почему, но вопреки всякой логике РАБОТАЕТ точно так же как вполне корректное[vba]

Code

With Target.Offset(0, 4)

[/vba] surprised
Но вполне может работать не везде. И не надо привыкать к такому недокументированному обращению. Тем более, что оно просто не логично (я выше, надеюсь, объяснил, почему?)

2. Target в данной процедуре — это диапазон ячеек, в котором произошло изменение. Изменение могло быть не в одной ячейке, а сразу в нескольких. Например, вы вставили значения сразу в несколько ячеек или выделили какой-то диапазон и нажали Delete. Тогда количество ячеек в Target будет больше одной.

3. Опять же хоть без этого и почему-то работает, но:
в процессе ввода макросом времени и даты в ячейки на листе происходят события Worksheet_Change, которые вы собственно этим же макросом и обрабатываете. Т.е. вполне может получиться, что в результате работы макроса он начнёт вызывать сам себя и войдёт в бесконечный цикл.
Поэтому перед тем как начать что-то писать в ячейки листа мы запрещаем приложению реагировать на события : Application.EnableEvents = False, а после того, как изменения ячеек макросом закончим, разрешаем обработку событий опять: Application.EnableEvents = True

4. Не люблю и не знаю я эти текстовые описания цифровых форматов… Потому и стараюсь не использовать. В принципе, это есть у Уокенбаха. Если интересно, почитайте.

5. А про Intersect неужели в справке так не понятно написано? Там же всего-то несколько строк:

Quote

Intersect Method
Returns a Range object that represents the rectangular intersection of two or more ranges.
expression.Intersect(Arg1, Arg2, …)
expression Optional. An expression that returns an Application object.
Arg1, Arg2, … Required Range. The intersecting ranges. At least two Range objects must be specified.

Т.е. в нашем случае: если диапазоны столбца А:А и Target не пересекаются (изменения произошли не в столбце А) и, следовательно, метод Intersect(Target, Range(«A:A»)) вернёт значение Nothing, то выйти из процедуры.



С уважением,
Алексей
MS Excel 2003 — the best!!!

 

Ответить

light26

Дата: Пятница, 27.04.2012, 15:25 |
Сообщение № 12

Группа: Друзья

Ранг: Старожил

Сообщений: 1341


Репутация:

91

±

Замечаний:
0% ±


2007, 2010, 2013

Quote (RAN)

Тогда изучай 1С.
Там весь код на русском!

Ну спасибо, добрый человек )))))


Я не волшебник. Я только учусь

 

Ответить

shanemac51

Дата: Пятница, 27.04.2012, 15:25 |
Сообщение № 13

Группа: Проверенные

Ранг: Новичок

Сообщений: 33


Репутация:

4

±

Замечаний:
0% ±


[vba]

Code

Private Sub Worksheet_Change(ByVal Target As Range)
‘тут не совсем понятно
»»target —грубо говоря —копия ячеек, измененных на данном листе

Debug.Print Target.Row, Target.Column
If Target.Cells.Count > 1 Then Exit Sub
‘тут совсем не понятно
»если выделено более 1 ячейки—выход
If Not Intersect(Target, Range(«A:A»)) Is Nothing Then
‘тут ясно, что следим за изменениями в столбце А. Хотелось бы подробней
»если диапазон а:а не выделен   —выход  
»
   With Target(1, 5)
   ‘тут указываем ячейку, куда будут вводиться результат вычисления следующей строки
   »»»»» причем 1,5 означает вывод
»1—в первую строку таргета
»5—столбец
»»»»»»»»»»»»»»»’
   .Value = Now
   ‘если по-русски, то =ТДАТА()
   ‘Columns («e:e»)   »’не нужна
   .NumberFormat = «[$-F400]h:mm:ss AM/PM»
   ‘формат ячеек столбца Е — время (ч,мм,сс). Только вот что значит [$-F400]?
   »’вы запросили формат—только время
   .EntireColumn.AutoFit
   ‘автовыравнивание
   End With
   »»»»»»»»»»»»»»»’
   With Target(1, 6)                    ‘
   .Value = Now                    ‘
   ‘Columns(«f:f»)    »’не нужна
   .NumberFormat = «d/m/yyyy»
   ‘формат ячеек столбца F — дата (д,м,ггг)
   »здесь формат день(1 или 2 цифры), месяц (1 или 2) и год(4)
   .EntireColumn.AutoFit                    ‘
   End With
End If
End Sub

[/vba]

Сообщение отредактировал shanemac51Пятница, 27.04.2012, 15:26

 

Ответить

light26

Дата: Пятница, 27.04.2012, 15:27 |
Сообщение № 14

Группа: Друзья

Ранг: Старожил

Сообщений: 1341


Репутация:

91

±

Замечаний:
0% ±


2007, 2010, 2013

Quote (Alex_ST)

не понятно почему, но вопреки всякой логике РАБОТАЕТ точно так же как вполне корректное

Я поэтому и уточнил.
Работает вообще весь макрос, несмотря на то, что я над ним «поколдовал» )))


Я не волшебник. Я только учусь

 

Ответить

Alex_ST

Дата: Пятница, 27.04.2012, 15:30 |
Сообщение № 15

Группа: Друзья

Ранг: Участник клуба

Сообщений: 3176


Репутация:

604

±

Замечаний:
0% ±


2003

Quote (light26)

я по-английски только yes знаю

Безотказный Вы наш! Что бы такое попросить-то …? biggrin



С уважением,
Алексей
MS Excel 2003 — the best!!!

 

Ответить

light26

Дата: Пятница, 27.04.2012, 15:39 |
Сообщение № 16

Группа: Друзья

Ранг: Старожил

Сообщений: 1341


Репутация:

91

±

Замечаний:
0% ±


2007, 2010, 2013

Quote (shanemac51)

‘Columns(«f:f») »’не нужна

то-есть строка With Target(1, 6) подразумевает, что все записи ниже будут относиться к шестому столбцу, то-есть к столбцу F. до тех пор, пока выполнение процедуры не дойдет до End With. А каждая новая строка должна начинаться с точки. Я правильно понял?


Я не волшебник. Я только учусь

 

Ответить

light26

Дата: Пятница, 27.04.2012, 15:40 |
Сообщение № 17

Группа: Друзья

Ранг: Старожил

Сообщений: 1341


Репутация:

91

±

Замечаний:
0% ±


2007, 2010, 2013

Quote (Alex_ST)

Что бы такое попросить-то …?

yes… )))


Я не волшебник. Я только учусь

 

Ответить

light26

Дата: Пятница, 27.04.2012, 15:48 |
Сообщение № 18

Группа: Друзья

Ранг: Старожил

Сообщений: 1341


Репутация:

91

±

Замечаний:
0% ±


2007, 2010, 2013

Quote (Alex_ST)

Т.е. в нашем случае: если диапазоны столбца А:А и Target не пересекаются (изменения произошли не в столбце А) и, следовательно, метод Intersect(Target, Range(«A:A»)) вернёт значение Nothing, то выйти из процедуры.

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


Я не волшебник. Я только учусь

 

Ответить

light26

Дата: Пятница, 27.04.2012, 15:57 |
Сообщение № 19

Группа: Друзья

Ранг: Старожил

Сообщений: 1341


Репутация:

91

±

Замечаний:
0% ±


2007, 2010, 2013

Quote (light26)

удаление из кода этой строки

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


Я не волшебник. Я только учусь

 

Ответить

RAN

Дата: Пятница, 27.04.2012, 20:04 |
Сообщение № 20

Группа: Друзья

Ранг: Экселист

Сообщений: 5645

И еще о Target
Target.Cells.Count > 1 работает точно так-же, как и Target.Count > 1


Быть или не быть, вот в чем загвоздка!

 

Ответить

I spent a lot of time researching this and learning how it all works, after really messing up the event triggers. Since there was so much scattered info I decided to share what I have found to work all in one place, step by step as follows:

1) Open VBA Editor, under VBA Project (YourWorkBookName.xlsm) open Microsoft Excel Object and select the Sheet to which the change event will pertain.

2) The default code view is «General.» From the drop-down list at the top middle, select «Worksheet.»

3) Private Sub Worksheet_SelectionChange is already there as it should be, leave it alone. Copy/Paste Mike Rosenblum’s code from above and change the .Range reference to the cell for which you are watching for a change (B3, in my case). Do not place your Macro yet, however (I removed the word «Macro» after «Then»):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
End Sub

or from the drop-down list at the top left, select «Change» and in the space between Private Sub and End Sub, paste If Not Intersect(Target, Me.Range("H5")) Is Nothing Then

4) On the line after «Then» turn off events so that when you call your macro, it does not trigger events and try to run this Worksheet_Change again in a never ending cycle that crashes Excel and/or otherwise messes everything up:

Application.EnableEvents = False

5) Call your macro

Call YourMacroName

6) Turn events back on so the next change (and any/all other events) trigger:

Application.EnableEvents = True

7) End the If block and the Sub:

    End If
End Sub

The entire code:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("B3")) Is Nothing Then
        Application.EnableEvents = False
        Call UpdateAndViewOnly
        Application.EnableEvents = True
    End If
End Sub

This takes turning events on/off out of the Modules which creates problems and simply lets the change trigger, turns off events, runs your macro and turns events back on.

Run a macro in Excel when a specific cell is changed; this also covers when a cell within a range of cells is changed or updated.

Sections:

Run Macro When a Cell Changes (Method 1)

Run Macro When a Cell Changes (Method 2)

Run Macro when a Cell in a Range of Cells is Changed

Notes

Run Macro When a Cell Changes (Method 1)

This works on a specific cell and is the easiest method to use.

Go to the VBA Editor (Alt + F11) and double-click the name of the spreadsheet that contains the cell that will change or just right-click the worksheet tab and click View Code. In the window that opens, select Worksheet from the left drop-down menu and Change from the right drop-down menu.
You should now see this:

For more info on creating macros, view our tutorial on installing a macro in Excel.

Excel will actually run the code that we input here each time a cell within the worksheet is changed, regardless of which cell is changed. As such, we need to make sure that the cell that we want to check is the one that the user is changing. To do this, we use an IF statement and, in this example, Target.Address.

Sample code:

This checks if cell A1 was the cell that was changed and, if it was, a message box appears.

This is a very simple and easy-to-use template. Just change $A$1 to whichever cell you want to check and then put the code that you want to run inside the IF statement.

$A$1 refers to cell A1 and the dollar signs are just another way to reference a cell using what’s called an absolute reference. You will always need to include the dollar signs in the cell reference when you use this method.

Target.address is what gets the address of the cell that was just changed.

Get the value of the Cell

You will probably want to reference the new value of the cell that was changed and you do that like this:

Target.Value

To output the new value of the cell in the message box, I can do this:

If Target.Address = "$A$1" Then

    MsgBox Target.Value

End If

Target is the object that contains all of the information about the cell that was changed, including its location and value.

In the below examples you can also use Target to get the value of a cell the same way as here, though it may not be covered in those sections.

Run Macro When a Cell Changes (Method 2)

(Read the Method 1 example for a full explanation of the setup for the macro. This section covers only the code for the second method.)

The second way to check if the desired cell was changed is a little bit more complicated, but it’s not difficult.

If Not Intersect(Target, Range("A1")) Is Nothing Then

    MsgBox "Hi!"

End If

This method uses Intersect(Target, Range(«A1»)) to find out if the desired cell is being changed.

Just change A1 to the cell that you want to check. For this method, you do not need to include dollar signs around the range reference like you did for method 1.

This method uses the Intersect() function in VBA which determines if the cell that was edited «intersects» with the cell that we are checking.

Reference the value of the cell the same way as the first example.

Run Macro when a Cell in a Range of Cells is Changed

This uses the same syntax as the previous example but with a slight modification.

Here, we want to check if a cell that is within a range of cells has been changed; it could be one of many cells.

If Not Intersect(Target, Range("A1:A5")) Is Nothing Then

    MsgBox "Hi!"

End If

This uses Intersect() just like the previous example to find out if one of the desired cells has been changed.

In this example, the message box appears if any cell in the range A1:A5 is changed. All you have to do is change A1:A5 to the desired range.

Notice that you also don’t need dollar signs in the range reference here like you did in the very first example.

Reference the value of the cell the same way as the first example.

Notes

Knowing which cell was edited and what the new value is for that cell is, as you can see, quite simple. Though simple, this will allow you to make interactive worksheets and workbooks that update and do things automatically without the user having to click a button or use keyboard shortcuts to get a macro to run.

Download the workbook attached to this tutorial and play around with the examples and you will understand them in no time!

Similar Content on TeachExcel

Run a Macro when a User Does Something in the Worksheet in Excel

Tutorial: How to run a macro when a user does something in the worksheet, everything from selecting …

Run a Macro when a User Does Something in the Workbook in Excel

Tutorial:
How to run a macro when a user does something within the Workbook in Excel, such as openi…

Automatically Run a Macro When a Workbook is Opened

Tutorial:
How to make a macro run automatically after a workbook is opened and before anything els…

Stop Excel Events from Triggering when Running a Macro

Tutorial: Create a macro that will run without triggering events, such as the Change event, or Activ…

Automatically Run a Macro at a Certain Time — i.e. Run a Macro at 4:30PM every day

Macro: Automatically run an Excel macro at a certain time. This allows you to not have to worry a…

Subscribe for Weekly Tutorials

BONUS: subscribe now to download our Top Tutorials Ebook!

Worksheet Change Event in VBA and Preventing Event Loops

Related Links: 

Excel VBA Events, Event Handlers, Trigger a VBA Macro.

Worksheet Selection Change Event, Excel VBA.

————————————————————————   

Contents:

Worksheet_Change Event

Preventing Event Loops with Application.EnableEvents = False

————————————————————————   

Worksheet_Change Event:

You can auto run a VBA code, when content of a worksheet cell changes, with the Worksheet_Change event. The change event occurs when cells on the worksheet are changed either by the user, or by any VBA application or by an external link, but not when a cell changes due to recalculation as a result from formula or due to format change. For changes made by calculation, use Worksheet_Calculate event.

Worksheet change procedure is installed with the worksheet, ie. it must be placed in the code module of the appropriate Sheet object. To create a worksheet change event: use the Visual Basic Editor -> in the Project Explorer, double click on the appropriate sheet (under ‘Microsoft Excel Objects’ which is under the VBAProject/name of your workbook) -> in the Code window, select «Worksheet» from the left-side «General» drop-down menu and then select «Change» from the right-side «Declarations» drop-down menu. You will get a procedure «shell» in the code window as follows:

Private Sub Worksheet_Change(ByVal Target As Range)

End Sub

Target is a parameter of data type Range (ie. Target is a Range Object). It refers to the changed Range and can consist of one or multiple cells. If Target is in the defined Range, and its value or content changes, it will trigger the vba procedure. If Target is not in the defined Range, nothing will happen in the worksheet. In this manner, you can limit the events to a particular range for both the Change and SelectionChange events. This can be done in multiple ways:

Using Target Address. Trigger the procedure, if a single cell (A5) value is changed:

If Target.Address = «$A$5» Then MsgBox «Success»

If Target.Address = Range(«$A$5»).Address Then MsgBox «Success»

If Target.Address = Range(«A5»).Address Then MsgBox «Success»

Using Target Address. If cell (A1) or cell (A3) value is changed:

If Target.Address = «$A$1» Or Target.Address = «$A$3» Then MsgBox «Success»

Using Target Address. If any cell(s) value other than that of cell (A1) is changed:

If Target.Address <> «$A$1» Then MsgBox «Success»

The following use of Target.Address is not correct, and the code will not run:

If Target.Address = «$a$5» Then MsgBox «Success»

If Target.Address = «A1» Then MsgBox «Success»

If Target.Address = «$A$1:$A$10» Then MsgBox «Success»

If Target.Address = Range(«$A$1:$A$10») Then MsgBox «Success»

Note: Target.Address should be an absolute reference [unless used as Range(«A5»).Address — see above] and in Caps. Use this to run code when content of a single cell is changed or when any cell(s) other than a specific cell is changed.

Trigger the procedure, if any cell in a column(s) is changed, say for any change in a cell in column B or column C:

If Target.Column = 2 Or Target.Column = 3 Then MsgBox «Success»

Intersect method for a single cell. If Target intersects with the defined Range of A1 ie. if cell (A1) value is changed, the code is triggerred:

If Not Application.Intersect(Target, Range(«A1»)) Is Nothing Then MsgBox «Success»

Trigger the procedure, if at least one cell of Target is A1,B2,C3:

If Not Application.Intersect(Target, Range(«A1,B2,C3»)) Is Nothing Then MsgBox «Success»

At least one cell of Target is within the range C5:D25:

If Not Application.Intersect(Target, Me.Range(«C5:D25»)) Is Nothing Then MsgBox «Success»

If you want the code to run when only a single cell in Range(«C1:C10») is changed and do nothing if multiple cells are changed:

Private Sub Worksheet_Change(ByVal Target As Range)

If Intersect(Target, Range(«C1:C10»)) Is Nothing Or Target.Cells.Count > 1 Then

Exit Sub

Else

MsgBox «Success»

End If

End Sub

Preventing Event Loops with Application.EnableEvents = False

Example of a recursive loop code:

Private Sub Worksheet_Change(ByVal Target As Range)

If Not Application.Intersect(Target, Range(«A1:A10»)) Is Nothing Then

Range(«A5»).Value = Range(«A5»).Value + 1

End If

End Sub

Recursive Event Loop:

If, at each runtime, the worksheet_change event changes the content of a cell which itself is part of the Target Range (ie. which triggers the change event), it will result in reprocessing the change event repeatedly.  Recursion is the process of repeating in a similar way viz. when the procedure calls itself. Refer to above example of a recursive loop code, if any cell content in Range(«A1:A10») is changed by the user, the cell A5 value will change and increment by 1; this will again trigger the change event [because of change in value of cell A5 which is in the Target Range(«A1:A10»)] and will in turn change the cell A5 value by incrementing it by 1; and then this change in cell A5 will again trigger the change event and change the cell A5 value by incrementing it by 1; and so on. This will result in a recursive loop which might result in a ‘Out Of Stack Space’ untrappable error, or depending on the Excel setting, the loop might terminate at a threshold limit of say 100. To prevent this, enter the following at the beginning of the code: Application.EnableEvents = False. This means that any change made by the VBA code will not trigger any event and will not enable restarting the worksheet_change event. EnableEvents is not automatically changed back to True, this should be specifically done in your code, by adding the following line at the end of the code: Application.EnableEvents = True. Meanwhile, if during runtime, your code encounters an error, you will need an ErrorHandler (to change EnableEvents back to True) because events have been disabled in the beginning of the code. This can be done as follows. 

ErrorHandler, Example 1:

Private Sub Worksheet_Change(ByVal Target As Range)

‘on the occurrence of an error procedure flow is directed to the error-handling routine (ie. ErrHandler) which handles the error
On Error GoTo ErrorHandler
 

‘to prevent recursion — so that any change made by code will not trigger an event to restart the Worksheet_Change event 

Application.EnableEvents = False

‘on changing cell A1 or B1, go to ErrorHandler which reverts EnableEvents to True & then exit sub

If Target.Address = «$A$1» Or Target.Address = «$B$1» Then GoTo ErrorHandler

‘if value of any cell in column 1 or 2 is changed

If Target.Column = 1 Or Target.Column = 2 Then

‘if changed cell value is numeric ie. new value is not text

If IsNumeric(Target) Then

‘increment cell B2 value by 1

Range(«B2»).Value = Range(«B2»).Value + 1

End If

End If

‘EnableEvents is not automatically changed back to True & hence this needs to be done specifically at the end of the code before exit.

‘because an exit statement (ex. Exit Sub) is not placed above, the error-handling routine will also execute when there is no error.

ErrorHandler:

Application.EnableEvents = True

End Sub

ErrorHandler, Example 2:

Private Sub Worksheet_Change(ByVal Target As Range)

On Error Resume Next  ‘skip all run-time errors

If Target.Address = «$A$1» Or Target.Address = «$B$1» Then Exit Sub

Application.EnableEvents = False

 
If Target.Column = 1 Or Target.Column = 2 Then

If IsNumeric(Target) Then

Range(«B2»).Value = Range(«B2»).Value + 1

End If

End If

Application.EnableEvents = True

On Error GoTo 0  ‘Turn off error trapping and re-allow run time errors

End Sub

On Error Statements explained:

On Error Resume Next: Specifies that when a run-time error occurs, control goes to the statement immediately following the statement where the error occurred, and execution continues from that point.

The On Error GoTo 0 statement turns off error trapping.  It disables enabled error handler in the current procedure and resets it to Nothing.

On Error GoTo Line: Enables the error-handling routine that starts at the specified Line. The On Error GoTo statement traps all errors, regardless of the exception class.

Throughout your VBA practices, you would get the need to run macros when a certain range or cell changes. In that case, to run macros when a change is made to a target range, we use the change event. Events in VBA enables us to run the macros when a certain event occurs.

Syntax VBA Range Change Event

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("your_range")) Is Nothing Then
      call your_macro
    End If
End Sub

The Event does not work in modules. You need to write them into objects (worksheet, charts, workbook).

Lat’s have an example to learn how to run a macro when a change is made in a specified range.

Example: Run a VBA Macro When A change is made in range A2:A100

First, we choose the sheet on which the event will occur. Double click on that sheet in VBA editor and copy below code or generic code above and make changes as per your requirement.

In this example, I want to run a macro/VBA code when a change is made in range A2: A100 on sheet 2. To do so, I double click on sheet2 in project explorer. It opens the coding page for that sheet. You can right-click on the sheet and click on the view code to do the same.

I need to use the change event. For that, we use default subroutine Worksheet_Change(ByVal Target As Range). It triggers when a specified change is made. So our code is this:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("A2:A100")) Is Nothing Then
      Call TestEvent
    End If
End Sub

When you make any changes in range A2:A100 on Sheet2, the subroutine TestEvent will be called, as you can see in the gif above.

The TestEvent is the public subroutine in module2. It simply pops up a message that the Event is working.

Sub TestEvent()
 MsgBox "Event is working!"
End Sub

How does it work?

We have put a condition :

If Not Intersect(Target, Range(«A2:A100»)) Is Nothing Then

Here Intersect(Target, Range(«A2:A100»)) Is Nothing returns True if no change is made in Range A2:A100. We put a Not operator before this statement that reverses the output given by «Intersect(Target, Range(«A2:A100″))». Hence, if no change is made in range A2:A100, the expression returns Falls and the sub TestEvent doesn’t get the call. If you do make a change in any cell in range A2:A100, the expression will return True and the event will occur. And that’s what happening here.

Note: You can put any subroutine in this block. It can be from any module. But it should be a public subroutine. You can set the range to any extent. The whole sheet is the limit.

So yeah guys, this how you can call a subroutine or run a macro/VBA code when a change is made in a specified range. It was a basic event example. This event will trigger only when the change is text-based. By text-based I mean if you write anything in the cells or delete, the event will trigger. If you change the formatting of the cells, it will not trigger. There are other methods to do that.

I hope it was helpful. If you have any queries related to this VBA topic or any other excel related topic, let me know the comments section below. And check out our other related and popular posts mentioned below.

Related Articles:

Run Macro When any Change is Made On Sheet | So to run your macro whenever the sheet updates, we use the Worksheet Events of VBA.

Simplest VBA Code to Highlight Current Row and Column Using | Use this small VBA snippet to highlight the current row and column of the sheet.

The Worksheet Events in Excel VBA | The worksheet event are really useful when you want your macros run when a specified event occurs on the sheet.

Popular Articles:

50 Excel Shortcuts to Increase Your Productivity | Get faster at your task. These 50 shortcuts will make you work even faster on Excel.

The VLOOKUP Function in Excel | This is one of the most used and popular functions of excel that is used to lookup value from different ranges and sheets. 

COUNTIF in Excel 2016 | Count values with conditions using this amazing function. You don’t need filter your data to count specific value. Countif function is essential to prepare your dashboard.

How to Use SUMIF Function in Excel | This is another dashboard essential function. This helps you sum up values on specific conditions.

Понравилась статья? Поделить с друзьями:
  • If not error formula in excel
  • If not conditional formatting excel
  • If not condition in excel vba
  • If not command in excel
  • If mid function excel