Как в VB определить адрес текущей (выбранной) ячейки на неактивном листе или является ли ячейка на неактивном листе - текущей (выбранной) ? (активировать лист нельзя)
Как в VB определить адрес текущей (выбранной) ячейки на неактивном листе или является ли ячейка на неактивном листе - текущей (выбранной) ? (активировать лист нельзя)psw
Poltava истину глаголит Проще всего перед деактивацией листа по событию Worksheet_Deactivate запоминать ActiveCell.Address(0, 0) в Public-переменную
Poltava истину глаголит Проще всего перед деактивацией листа по событию Worksheet_Deactivate запоминать ActiveCell.Address(0, 0) в Public-переменнуюAlex_ST
Лист может быть вообще никогда не активирован. Во время работы VB-программы (своего рода демон корявый, с тайм-аутами по DoEvents) пользователь "вручную" ходит по листам и "тыкает" в ячейки, оставляя их выбранными. Кроме того, VB-программа может быть остановлена и перестартована после [ручной] деактивации листа. Поэтому и надо определить выбранную ячейку на НЕактивном листе. Неужели VB Excel настолько беден...
Лист может быть вообще никогда не активирован. Во время работы VB-программы (своего рода демон корявый, с тайм-аутами по DoEvents) пользователь "вручную" ходит по листам и "тыкает" в ячейки, оставляя их выбранными. Кроме того, VB-программа может быть остановлена и перестартована после [ручной] деактивации листа. Поэтому и надо определить выбранную ячейку на НЕактивном листе. Неужели VB Excel настолько беден...psw
Во время работы VB-программы ... пользователь "вручную" ходит по листам и "тыкает" в ячейки, оставляя их выбранными. Кроме того, VB-программа может быть остановлена и перестартована после [ручной] деактивации листа.
Если же лист вообще ни разу не "посещался" или новый - то "Текущая ячейка" на нем есть Cells(1,1). Совет
Цитата (Alex_ST)
перед деактивацией листа по событию Worksheet_Deactivate запоминать ActiveCell.Address(0, 0)
вполне подходит - только запоминайте адрес прямо в ячейку на листе.
С другой стороны, сам Excel действительно сохраняет где-то в книге адреса всех последних активных ячеек каждого листа, так что задачка интересная. Быстрое гугление не дало ответа на вопрос
Цитата (psw)
Лист может быть вообще никогда не активирован.
противоречит
Цитата (psw)
Во время работы VB-программы ... пользователь "вручную" ходит по листам и "тыкает" в ячейки, оставляя их выбранными. Кроме того, VB-программа может быть остановлена и перестартована после [ручной] деактивации листа.
Если же лист вообще ни разу не "посещался" или новый - то "Текущая ячейка" на нем есть Cells(1,1). Совет
Цитата (Alex_ST)
перед деактивацией листа по событию Worksheet_Deactivate запоминать ActiveCell.Address(0, 0)
вполне подходит - только запоминайте адрес прямо в ячейку на листе.
С другой стороны, сам Excel действительно сохраняет где-то в книге адреса всех последних активных ячеек каждого листа, так что задачка интересная. Быстрое гугление не дало ответа на вопрос AndreTM
Пользователь и VB-программа (для краткости - демон) работают параллельно. Активация Листа1 демоном ведет к деактивации Листа2 пользователя, на котором пользователь в это время работает. Это недопустимо.
Кроме того, демон м.б. стартован после того как пользователь побывал на Листе1 демона и покинул его - "вручную деактивировал" Лист1. Поэтому демону нечего запоминать "в ячейку на листе"[1]. В процессе совместной работы пользователя и демона, у демона м.б. несколько жизней (от своего старта до своего завершения), и очередной старт жизни м.б. необязательно на Листе1.
Почему-то народ пытается обойти именно изначально сформулированное, главное (и единственное!) условие задачки - запрет активации неактивного листа))))
Пользователь и VB-программа (для краткости - демон) работают параллельно. Активация Листа1 демоном ведет к деактивации Листа2 пользователя, на котором пользователь в это время работает. Это недопустимо.
Кроме того, демон м.б. стартован после того как пользователь побывал на Листе1 демона и покинул его - "вручную деактивировал" Лист1. Поэтому демону нечего запоминать "в ячейку на листе"[1]. В процессе совместной работы пользователя и демона, у демона м.б. несколько жизней (от своего старта до своего завершения), и очередной старт жизни м.б. необязательно на Листе1.
Почему-то народ пытается обойти именно изначально сформулированное, главное (и единственное!) условие задачки - запрет активации неактивного листа))))psw
Вы не понимаете? Excel не поддерживает такого функционала (по крайней мере, стандартными средствами).
Вам же советуют реальный обходной путь. Который исходит из того, что "текущую ячейку" на неактивном листе может изменить только пользователь. Который при этом должен хотя бы раз активировать лист. И затем деактивировать (!) А вы ударяетесь в пояснения, не имеющие отношения к задаче, - видимо, не знаете, как правильно организовать событийную модель своей задачи...
Вы не понимаете? Excel не поддерживает такого функционала (по крайней мере, стандартными средствами).
Вам же советуют реальный обходной путь. Который исходит из того, что "текущую ячейку" на неактивном листе может изменить только пользователь. Который при этом должен хотя бы раз активировать лист. И затем деактивировать (!) А вы ударяетесь в пояснения, не имеющие отношения к задаче, - видимо, не знаете, как правильно организовать событийную модель своей задачи...AndreTM
Skype: andre.tm.007 Donate: Qiwi: 9517375010
Сообщение отредактировал AndreTM - Понедельник, 27.05.2013, 21:01
А может и не понимаю. Вот пользователь открыл файл, активировал Лист1, выбрал там ячейку, перешёл на свой Лист2 (т.е. Лист1 - деактивирован) и работает там, на Листе2. В это время стартовал демон. Как демон может узнать: какая ячейка на ["давно уже"] неактивном Листе1 выбрана пользователем? (без помех для пользователя) Может и не понимаю.
А может и не понимаю. Вот пользователь открыл файл, активировал Лист1, выбрал там ячейку, перешёл на свой Лист2 (т.е. Лист1 - деактивирован) и работает там, на Листе2. В это время стартовал демон. Как демон может узнать: какая ячейка на ["давно уже"] неактивном Листе1 выбрана пользователем? (без помех для пользователя) Может и не понимаю.psw
..и вообще-то при Worksheet_Deactivate для Листа1 в ActiveCell.Address(0, 0) содержится адрес ячейки Листа2 НА который делается переход а не адрес ячейки Листа1 С которого делается переход..
можете проверить)):
[vba]
Код
Private Sub Worksheet_Deactivate() Application.EnableEvents = False Application.ScreenUpdating = False MsgBox (ActiveCell.Address(0, 0)) Application.ScreenUpdating = True Application.EnableEvents = True End Sub
[/vba]
[admin]Оформляйте коды тегами![/admin]
..и вообще-то при Worksheet_Deactivate для Листа1 в ActiveCell.Address(0, 0) содержится адрес ячейки Листа2 НА который делается переход а не адрес ячейки Листа1 С которого делается переход..
можете проверить)):
[vba]
Код
Private Sub Worksheet_Deactivate() Application.EnableEvents = False Application.ScreenUpdating = False MsgBox (ActiveCell.Address(0, 0)) Application.ScreenUpdating = True Application.EnableEvents = True End Sub
psw а что проверять то? все так и должно быть, в чем можно легко убедиться
Цитата (из F1)
Событие SheetDeactivate(Sh As Object). Возникает когда страница перестает быть активной, поскольку активной становится другая страница. Деактивированная страница передается обработчику события в качестве параметра
Так что когда срабатывает SheetDeactivate активным уже является другой лист! Но нам никто не запрещает сделать так
[vba]
Код
Option Explicit Private Sub Worksheet_Deactivate() Application.EnableEvents = False Application.ScreenUpdating = False Dim ShA$, Addr$ ShA = ActiveSheet.Name Me.Activate Addr = ActiveCell.Address(0, 0) Sheets(ShA).Activate Application.ScreenUpdating = True Application.EnableEvents = True MsgBox Addr End Sub
[/vba]
Ну и так сказать мои 5 копеек! Я конечно понимаю что настоящие герои всегда идут в обход но как по мне писать этот код для 20-30 листов в книге это пагубная идея! предлагаю такой вариант в модуль книги. Попробуйте попереключать листы в приложенном файле.
[vba]
Код
Option Explicit Private WithEvents App As Application Public Aws$, AWb$ Private Sub App_SheetDeactivate(ByVal Sh As Object) Aws = Sh.Name AWb = Sh.Parent.Name If AWb = ThisWorkbook.Name Then offcell End Sub Private Sub App_WorkbookDeactivate(ByVal Wb As Workbook) AWb = Wb.Name Aws = Wb.ActiveSheet.Name End Sub Private Sub Workbook_Open() Set App = Application End Sub Private Sub offcell() Dim ShA$, Addr$ Application.EnableEvents = False Application.ScreenUpdating = True ShA = ActiveSheet.Name Sheets(Aws).Activate Addr = ActiveCell.Address(0, 0) Sheets(ShA).Activate Application.ScreenUpdating = True Application.EnableEvents = True MsgBox Addr End Sub
[/vba]
Вместо месенжа используйте Public массив в котором храните текущие значения. Заполнить массив можно при старте перебрав все листы. В качестве номера в массиве можно использовать индекс листа! но это только если пользователь не может перетасовать листы! иначе можно использовать коллекцию и кодовые имена листов. В общем тут уже сами придумаете что удобней
psw а что проверять то? все так и должно быть, в чем можно легко убедиться
Цитата (из F1)
Событие SheetDeactivate(Sh As Object). Возникает когда страница перестает быть активной, поскольку активной становится другая страница. Деактивированная страница передается обработчику события в качестве параметра
Так что когда срабатывает SheetDeactivate активным уже является другой лист! Но нам никто не запрещает сделать так
[vba]
Код
Option Explicit Private Sub Worksheet_Deactivate() Application.EnableEvents = False Application.ScreenUpdating = False Dim ShA$, Addr$ ShA = ActiveSheet.Name Me.Activate Addr = ActiveCell.Address(0, 0) Sheets(ShA).Activate Application.ScreenUpdating = True Application.EnableEvents = True MsgBox Addr End Sub
[/vba]
Ну и так сказать мои 5 копеек! Я конечно понимаю что настоящие герои всегда идут в обход но как по мне писать этот код для 20-30 листов в книге это пагубная идея! предлагаю такой вариант в модуль книги. Попробуйте попереключать листы в приложенном файле.
[vba]
Код
Option Explicit Private WithEvents App As Application Public Aws$, AWb$ Private Sub App_SheetDeactivate(ByVal Sh As Object) Aws = Sh.Name AWb = Sh.Parent.Name If AWb = ThisWorkbook.Name Then offcell End Sub Private Sub App_WorkbookDeactivate(ByVal Wb As Workbook) AWb = Wb.Name Aws = Wb.ActiveSheet.Name End Sub Private Sub Workbook_Open() Set App = Application End Sub Private Sub offcell() Dim ShA$, Addr$ Application.EnableEvents = False Application.ScreenUpdating = True ShA = ActiveSheet.Name Sheets(Aws).Activate Addr = ActiveCell.Address(0, 0) Sheets(ShA).Activate Application.ScreenUpdating = True Application.EnableEvents = True MsgBox Addr End Sub
[/vba]
Вместо месенжа используйте Public массив в котором храните текущие значения. Заполнить массив можно при старте перебрав все листы. В качестве номера в массиве можно использовать индекс листа! но это только если пользователь не может перетасовать листы! иначе можно использовать коллекцию и кодовые имена листов. В общем тут уже сами придумаете что удобнейPoltava
Я придумал немного другой вариант (с доп.переменной в модуле каждого "нужного" листа), построенный на исключениях. Правда, что-то там не дает переключаться на другие открытые книги (есть обход - можно создать новую книгу, а в ней уже открыть нужную, но тогда до закрытия "новооткрытого" - не вернуться в книгу с демоном), хотя и продолжает считать и записывать верно... Что-то там с событиями - надо посмотреть. Зато в рабочей книге даже удаление/добавление/копирование листов (во время работы демона) - без нареканий (при добавлении - надо озаботиться прописыванием переменной, при копировании - достаточно переместить курсор в нужную ячейку. Ибо демон пропускает активный лист при обработке, а пишет только на неактивные. И кода - минимум
Да, ещё. Переменные в модулях листа - Variant с расчетом на Object/Range, поэтому смотрите внимательно, как выполняете присваивание. Зато можно обращаться прямо к "активной" ячейке и её свойствам/методам. Конечно, можно сделать String (будет надёжнее при написании кода), но это уж проблемы разработчика.
Я придумал немного другой вариант (с доп.переменной в модуле каждого "нужного" листа), построенный на исключениях. Правда, что-то там не дает переключаться на другие открытые книги (есть обход - можно создать новую книгу, а в ней уже открыть нужную, но тогда до закрытия "новооткрытого" - не вернуться в книгу с демоном), хотя и продолжает считать и записывать верно... Что-то там с событиями - надо посмотреть. Зато в рабочей книге даже удаление/добавление/копирование листов (во время работы демона) - без нареканий (при добавлении - надо озаботиться прописыванием переменной, при копировании - достаточно переместить курсор в нужную ячейку. Ибо демон пропускает активный лист при обработке, а пишет только на неактивные. И кода - минимум
Да, ещё. Переменные в модулях листа - Variant с расчетом на Object/Range, поэтому смотрите внимательно, как выполняете присваивание. Зато можно обращаться прямо к "активной" ячейке и её свойствам/методам. Конечно, можно сделать String (будет надёжнее при написании кода), но это уж проблемы разработчика.AndreTM
Спасибо всем огромное. Ввиду того, что достаточно простого и "минималистического" [для меня] метода не нашлось, пришлось несколько пересмотреть технологию, и в результате её пересмотра оказалось возможным использовать обработчик события Worksheet_SelectionChange. Тут вообще практически кода нет)). Благодарен..
Спасибо всем огромное. Ввиду того, что достаточно простого и "минималистического" [для меня] метода не нашлось, пришлось несколько пересмотреть технологию, и в результате её пересмотра оказалось возможным использовать обработчик события Worksheet_SelectionChange. Тут вообще практически кода нет)). Благодарен..psw