Как перехватить события Applicat при открытом окне Application.InputBox(...,Type:=8)?

Весь MS Office, программирование на Visual Basic for Applications и MS VB

Модератор: Naeel Maqsudov

Ответить
Pavl
Сообщения: 5
Зарегистрирован: 07 июл 2010, 22:24

Уважаемые форумчане-знатоки!Как заставить работать в любых возможных случаях следующий код VBA:
Dim rg As Range
Set rg=Application.InputBox _
("Выделите на нужном листе требуемую прямоугольную область ячеек или активируйте нужный лист и подтвердите правильность ранее сделанного выделения кликом по кнопке OK.", "Ввод области ячеек", _
Selection.Address(RowAbsolute:=False, ColumnAbsolute:=False), _
Type:=8)
Проблема возникает в ситуации: указанный код находится в стандартном модуле Книги1xls, пользователь до запуска указанного кода открывает Книгу2, выделяет интересующий его фрагмент ячеек на Листе 2, "уходит" на Лист1 Книги2 (с целью не принципиальной для постановки задачи), открывает Книгу1, выбирает в имеющемся там ListBox из всех открытых книг Книгу2, запускает иакрос, содержащий указанный код, после появления окна ImputBox и автоматической активации книги2, пользователь кликает по ярлычку Листа2 Книги2 (т.к. при активации Книги2 активным будет Лист1) и хочет нажатием кнопки OK подтвердить адрес ранее выделенной им области. Но вместо этого адреса в поле ввода ImputBox он вмдит: "Лист2!". И нажатие на кнопку OK приводит, естественно, к ошибке.
Попытки стандартного перехвата события активации другого листа на уровне Application с созданием модуля класса, похоже, не проходят, т.к. при открытом окне
Application.InputBox перехвата при таком способе не происходит, хотя Excel и замечает клик по ярлычку Листа2, т.к. содержимое поля ввода при клике меняется на Лист2!.
Как "влезть" в это событие, замечаемое Excel, и "подправить" его так, чтобы вводился адрес выделения на Листе2 Книги2?
Для облегчения поиска ренения прилагаю архив с файлами: Книга1.xls и Книга2.xls. В Книге2 на каждом из двух её листов выделен фрагмент ячеек, и изначально активен Лист1. В Книге1 содержится модельный код, необходимый для перехвата события активации листа на уровне Application, а также в стандартном модуле процедура SelectRegions(),
Процедура SelectRegions (по замыслу) позволяет пользвателю ввести для последующей обработки макросами Книги1 (которые опущены): либо заранее (до открытия Книги1) выделенную на Листе2 открытой Книги2 область, либо выделить на Листе2 область вручную (для чего и нужен Application.ImputBox).
Вложения
ImputBox.ZIP
(17.88 КБ) 36 скачиваний
Pavl
Сообщения: 5
Зарегистрирован: 07 июл 2010, 22:24

[quote="Pavl"]Уважаемые форумчане-знатоки!Как заставить работать в любых возможных случаях следующий код VBA:
Dim rg As Range
Set rg=Application.InputBox _
("Выделите на нужном листе требуемую прямоугольную область ячеек или активируйте нужный лист и подтвердите правильность ранее сделанного выделения кликом по кнопке OK.", "Ввод области ячеек", _
Selection.Address(RowAbsolute:=False, ColumnAbsolute:=False), _
Type:=8)
Проблема возникает ....QUOTE]
Здравствуйте, уважаемые форумчане!
Времени прошло много, а ответа (хотя бы отрицательного - о невозможности перехвата события, указанного в приведённой выше постановке проблемы) не появилось. Неужели признаем поражение?
nilem
Сообщения: 112
Зарегистрирован: 14 ноя 2008, 01:59
Откуда: Уфа

Вот так не подойдет?

Код: Выделить всё

Sub SelectRegions() 'в модуле Книга1.xls
    Dim rng As Range, wb As Workbook, x
    Set wb = Workbooks.Open(ThisWorkbook.Path & "\Книга2.xls")
    wb.Sheets("Лист2").Activate
    On Error Resume Next
A:
    Set rng = Application.InputBox("Выделите диапазон", "Выбор области", Type:=8)
    If rng Is Nothing Then GoTo A
    On Error GoTo 0
    x = rng.Value
    wb.Close False: Set wb = Nothing
    [a1].Resize(UBound(x, 1), UBound(x, 2)).Value = x
End Sub
Pavl
Сообщения: 5
Зарегистрирован: 07 июл 2010, 22:24

nilem писал(а):Вот так не подойдет?
.....]
Спасибо за быстрый отклик. Так быстро я даже не ожидал и не сразу посмотрел форум.
Сейчас временно занят другим делом, поэтому пока ничего не проверял. Позже (не слишком скоро) обязательно подробно напишу что и как получилось.
С уважением, Pavl.
Pavl
Сообщения: 5
Зарегистрирован: 07 июл 2010, 22:24

nilem писал(а):Вот так не подойдет?

Код: Выделить всё

Sub SelectRegions() 'в модуле Книга1.xls
    Dim rng As Range, wb As Workbook, x
    Set wb = Workbooks.Open(ThisWorkbook.Path & "\Книга2.xls")
    wb.Sheets("Лист2").Activate
    On Error Resume Next
A:
    Set rng = Application.InputBox("Выделите диапазон", "Выбор области", Type:=8)
    If rng Is Nothing Then GoTo A
    On Error GoTo 0
    x = rng.Value
    wb.Close False: Set wb = Nothing
    [a1].Resize(UBound(x, 1), UBound(x, 2)).Value = x
End Sub

К сожалению, не проходит по причинам:
1) названия "Книга2" и "Лист2" могут быть любыми и заранее не известны;
2) код должен обеспечивать ввод адреса выделения, заранее сделанного пользователем в какой-то книге (скажем, в Книге2) на каком-то её листе (например, на Листе2) без каких-либо дополнительных действий клиента (не считая двух кликов: по ярлычку Листа2 и по кнопке [OK] в открытом к этому моменту окне ImputBox в подтверждение выбора заранее выделенного диапазона) даже в том случае, когда при активации Книги2 (а это происходит после выбора пользователем в пользовательской форме Книги1 [опущенной в моём коде] нужной ему книги [Книги2] из всех открытых книг) в ней активен Лист1. При этом, на случай возможной ошибки пользователя при предварительном выделении на Листе2 Книги2 нужного ему диапазона, у него должна быть возможность исправить свою ошибку выделения диапазона ячеек или вообще передумать и вручную выбрать другой диапазон ячеек Листа2 или на каком-нибудь другом листе. Именно для реализации этой возможности и нужен ImputBox( , Type:=8). Однако, открытое окно ImputBox( , Type:=8) мешает стандартному перехвату события активации пользователем Листа2 (и вообще любого листа Книги2). Отсюда проблема с перехватом, сформулированная чуть иными словами в начале темы в первом моём посте.
Замечу ещё, что передумать и из окна ImputBox( , Type:=8) выбрать другой диапазон всегда получается.
Pavl
Сообщения: 5
Зарегистрирован: 07 июл 2010, 22:24

Добрый вечер, уважаемые форумчане!
nilem писал(а):Вот так не подойдет?

Код: Выделить всё

Sub SelectRegions() 'в модуле Книга1.xls
    Dim rng As Range, wb As Workbook, x
    Set wb = Workbooks.Open(ThisWorkbook.Path & "\Книга2.xls")
    wb.Sheets("Лист2").Activate
    On Error Resume Next
A:
    Set rng = Application.InputBox("Выделите диапазон", "Выбор области", Type:=8)
    If rng Is Nothing Then GoTo A
    On Error GoTo 0
    x = rng.Value
    wb.Close False: Set wb = Nothing
    [a1].Resize(UBound(x, 1), UBound(x, 2)).Value = x
End Sub

К сожалению, не проходит по причинам:
1) названия "Книга2" и "Лист2" могут быть любыми и заранее не известны;
2) код процедуры SelectRegions() (запускаемой в моём модельном коде вручную) должен обеспечивать ввод адреса выделения, заранее сделанного пользователем в какой-то книге (скажем, в Книге2) на каком-то её листе (например, на Листе2) без каких-либо дополнительных действий клиента {не считая двух кликов: по ярлычку Листа2 Книги2 (активируемой при её выборе в пользовательской форме Книги1, показывающей список всех открытых книг [эта форма опущена в моём модельном коде]) и по кнопке [OK] в открытом (как было сказано вручную [в моём модельном коде]) окне ImputBox - в подтверждение выбора заранее выделенного диапазона} даже в том случае, когда при активации Книги2 (а это происходит после выбора её пользователем из списка всех открытых книг в пользовательской форме Книги1 [опущенной в моём модельном коде]) в ней активен Лист1, а не Лист2. При этом, на случай возможной ошибки пользователя при предварительном выделении на Листе2 Книги2 нужного ему диапазона, у него должна быть возможность исправить свою ошибку выделения диапазона ячеек или же передумать и вручную выбрать другой диапазон ячеек Листа2 или какого-нибудь другого листа. Именно для реализации этой возможности и нужен ImputBox( , Type:=8). Однако, открытое окно ImputBox( , Type:=8) мешает стандартному перехвату события активации пользователем Листа2 (и вообще любых событий). Отсюда проблема с перехватом, сформулированная чуть иными словами в начале темы в первом моём посте.
Замечу ещё, что передумать и из окна ImputBox( , Type:=8) выбрать другой диапазон всегда получается.
По сути нужно как-то вмешаться в исполнение "внутреннего" кода метода ImputBox с целью заставить его учисывать после открытия окна ImputBox( ..,default,Type:=8) изменение значения default=sa, где sa=Selection.Address(RowAbsolute:=False, ColumnAbsolute:=False), после клика по ярлыку Листа2. Само это изменение должно происходить в результате какой-то нестандартной организации перехвата события Application, т.к. стандартный метод, как показывает выложенный ранее модельный код, не работает при открытом окне ImputBox( ..,Type:=8). "Протокольно" ImputBox( ..,Type:=8) перехватывает только клик по ярлыку неактивного листа, т.к. при этом в поле ввода вместо исходного (до клика по ярлыку) значения default появляется имя изначально не активного листа, по ярлыку каторого был клик, но этого мне мало.
Ответить