Страница: 1 | 2 |
|
Вопрос: Worksheet_Change
|
Добавлено: 01.01.10 19:29
|
|
Автор вопроса: Олег
|
Здравствуйте, Уважаемые!
Всех от души с Новым годом!
У меня такой вопрос (проблема) возник по ходу разработки макроса под Excel.
Дело в следующем... На одном из листов моей рабочей книги имеется ячейка, в которую транслируется значение из ячейки с другого листа. Когда значение в этой ячейке изменяется, программа должна проанализировать изменение и выполнить определённые действия.
Разумеется, я решил воспользоваться событием Worksheet_Change в Коде изменяемого листа. Но не тут-то было! Оказалось, что если этот лист не активен, то макрос никак не реагирует на это событие. Реакцию вызывает только НЕПОСРЕДСТВЕННОЕ изменение значения ячейки в АКТИВНОМ листе!
Подскажите, пожалуйста, можно как-нибудь обойти эту проблему? Мне бы хотелось вообще не заглядывать на тот лист, и чтобы там всё происходило автоматически, без моего участия...
Если я путано объяснил суть своей проблемы, то попробую сейчас показать её на простом примере. Если вы мне подскажете, как надо организовать работу программы в этом примере, то дальше я уже самостоятельно соображу...
Итак, имеются два листа: Лист1 и Лист2.
На Лист2 в ячейку А1 вписана формула "=Лист1!A1". Таким образом, когда мы изменяем значение в ячейке А1 первого листа, автоматически изменяется и значение в ячейке А1 второго листа.
Теперь в Коде второго листа вписываем вот такую процедуру:
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox (Target)
End Sub
После этого при НЕПОСРЕДСТВЕННОМ изменении любой ячейки на Лист2, выскакивает сообщение с тем значением, которое мы вводим.
Но когда мы изменяем ячейку А1 на первом листе, то сообщение не выскакивает (реакции на событие нет!), хотя значение в ячейке А1 второго листа тоже изменилось...
Как заставить программу реагировать на изменение ячеек на НЕАКТИВНОМ в данный момент листе?
Ответить
|
Номер ответа: 4 Автор ответа: Олег
Вопросов: 9 Ответов: 30
|
Профиль | | #4
|
Добавлено: 02.01.10 17:53
|
Большое спасибо, что откликнулись на мою просьбу помочь! Я даже не ожидал, что будет так много откликов, особенно если учесть, что сейчас у всех сейчас "отходняк" после Новогодней ночи
Smith пишет:
Или написать сторожа, правда цикл не есть гуд
Я совсем не опытный программист на VBA, поэтому что такое "сторож" не знаю. Но, на самом деле, хотел бы узнать! Я много программировал (непрофессионально, для своих нужд) на VB5, а в VBA, можно сказать, делаю свои первые шаги
hip пишет:
А сделать все необходимое в коде первого листа нельзя разве? Только переменной Target не удастся воспользоваться в этом случае - в ней будет диапазон с первого листа.
'в коде листа, на котором происходят непосредственные изменения (Лист1):
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox (Sheets("Лист2" .Cells(1,1).value)
End Sub
Да в том-то и проблема, что я постоянно перемещаюсь по всем листам и на всех листах происходят ПОСТОЯННЫЕ быстрые изменения (получение информации из внешних источников, подсчёт, построение диаграмм). А ту ячейку, изменения в которой для меня особенно важны, я специально "вынес" на отдельный лист, чтобы там могла изменяться только она одна! (Чтобы не отфильтровывать "лишних" изменений!) Очень уж я рассчитывал на событие Worksheet_Change, наивно думал, что прога должна реагировать на изменения, даже когда лист не активен...
ADSemenov.ru пишет:
Ну, а если использовать в книге самой событие Workbook_SheetChange?
На данный момент, для меня этот совет звучит самым заманчивым из всех... Сейчас буду экспериментировать... Потом отпишусь!
Хотя сразу вижу большой минус этой затеи в том, что много ресурсов компа будет уходить на реакцию (с последующей отфильтровкой) на ВСЕ изменения, которых в моей книге огромное количество. Боюсь, что тогда комп будет сильно тормозить. Ведь я же для того и собирался транслировать интересующее меня значение в ЕДИНСТВЕННУЮ изменяемую ячейку на ОТДЕЛЬНОМ листе, чтобы избежать затрат ресурсов на лишнюю фильтрацию. Макросы ведь и без того не слишком быстро работают, сами знаете...
Ответить
|
Номер ответа: 8 Автор ответа: Олег
Вопросов: 9 Ответов: 30
|
Профиль | | #8
|
Добавлено: 02.01.10 22:04
|
ADSemenov.ru пишет:
Проверить Sh на предмет идентичности листу с Вашей ячейкой и только после этого что-то делать.
Попробовал вот так вот сделать:
- Private Sub Workbook_SheetChange(ByVal Sh As Object, _
- ByVal Source As Range)
-
- If Not Sh Is Worksheets.Item("Лист2") Then Exit Sub
-
- Beep
-
- End Sub
Почему-то у меня не получается... Бибикает, только когда изменяю что-нибудь только НЕПОСРЕДСТВЕННО на втором листе, когда он активен. А если изменять значение ячейки А1 первого листа (и при этом изменяется ячейка А1 второго листа тоже), то не бибикает... Нужны дополнительные фильтры, наверно... Ниже я описал, как я потом ещё попробовал, но тоже неудачно
ADSemenov.ru пишет:
__ Если машина не тройка [ ] и изменений в книге не десятки тысяч за один раз, то никаких задержек быть не должно.
____ А в чём сомнение?
Машина хоть и не тройка, конечно , но довольно-таки старенькая (Селерон 1400 Мгц)
А изменений, на самом деле, очень много: программа непрерывно получает данные из внешнего источника, обрабатывает их, строит графики, а масштаб хочется покрупнее, чтобы зрение беречь. А крупная графика, разумеется, съедает много ресурсов, а тут ещё и макрос будет... Вот и не уверен я: потянет ли "мой старичок"?!
Хоть на том листе у меня других изменяемых ячеек не предполагается размещать, но всё равно, согласуясь с хорошим стилем программирования, хотелось бы фильтр поставить на возможные случайные изменения в других ячейках интересующего меня листа.
Попробовал вот так вот:
- Private Sub Workbook_SheetChange(ByVal Sh As Object, _
- ByVal Source As Range)
-
- If Not Sh Is Worksheets.Item("Лист2") Then Exit Sub
-
- If Source = Worksheets("Лист2").Cells(1, 1) Then
- Beep
- End If
- End Sub
Почему-то не работает. Отказывается бибикать, когда изменяю значение в ячейке А1 первого листа, хотя при этом значение в ячейке А1 второго листа тоже изменяется... Что я делаю не так, не подскажете?
Ответить
|
Номер ответа: 12 Автор ответа: Олег
Вопросов: 9 Ответов: 30
|
Профиль | | #12
|
Добавлено: 06.01.10 13:42
|
На самом первом этапе разработки программы я предполагал использовать Таймер, по которому макрос будет заглядывать в интересующую меня ячейку каждую секунду, фиксировать изменения (если будут) и реагировать на них соответствующим образом. Но потом я подумал: "Это ж каждую секунду программа будет заглядывать в эту ячейку, ресурсов много будет расходоваться впустую. А кроме того, возможны (хотя это очень маловероятно) резкие изменения значения этой ячейки ВНУТРИ 1-секундного промежутка, которые программа "прозевает"...
А потом меня озарило: "Можно же транслировать значение из этой ячейки на отдельный, "персонально" для неё выделенный лист, а там "ловить" событие Worksheet_Change"... Но оказалось, что не всё так просто Теперь впору снова возвращаться к идее Таймера. Так ресурсов будет расходоваться гораздо меньше относительно вот такого подхода:
- Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
- If Sheets("Лист2").Cells(1, 1).Value = m Then Exit Sub
- m = Sheets("Лист2").Cells(1, 1).Value
- Beep
- End Sub
Кстати, я уже на трёх(!) форумах поднял этот вопрос, и только на одном (на вашем!) хоть как-то пытаются помочь. На самом деле, большое вам спасибо!
Ответить
|
Страница: 1 | 2 |
Поиск по форуму