Страницы: 1 2 След.
RSS
запуск нужного макроса с панели инструментов
 
Сегодня впервые столкнулся с тем, что не могу запустить нужный макрос с кнопки на панели инструментов... Итак, ситуация: 1) есть 3 абсолютно идентичных файла (созданы копированием одного и того же файла), отличающиеся только именем файла - test1.xls, test2.xls, test3.xls 2) каждый файл при запуске формирует панель инструментов с именем, совпадающим с именем файла (это неважно, суть в том, что при запуске 3 файлов создаются 3 идентичные панели инструментов) 3) на каждой панели инструментов - одна кнопка, запускающая простейший макрос (название макроса во всех 3 файлах совпадают, т.к. файлы являются копией друг друга) Задача: добиться того, чтобы каждая кнопка запускала свой макрос (из той книги, к которой принадлежит панель инструментов) Что я делаю: Каждой кнопке в свойство OnAction прописываю "MyMacro" - результат неутешительный (кнопка запускает макрос из первой попавшейся книги Понимаю, что надо указать имя файла, и назначаю кнопкам OnAction в виде 'testX.xls'!MyMacro (соответственно, у каждой кнопки OnAction становится разный) Запускаю - и офигеваю. Кнопки с OnAction = 'test2.xls'!MyMacro и 'test3.xls'!MyMacro запускают макрос из файла test1 Вопросы: 1) почему??? 2) как этого избежать? Пробовал писать PRIVATE sub MyMacro - не помогает (чтобы запускаемый макрос был виден только из своей книги) Во вложении - 3 этих идентичных файла. Проблема - на скриншоте: http://www.ExcelVBA.ru/pictures/20120210-on7-35kb.jpg
 
Как выяснилось при тестировании, проблема проявляется в Excel 2003 и 2007,  
а в 2010 всё работает корректно (запускается нужный макрос)  
 
Мне же необходимо, чтобы нужный макрос запускался во всех версиях Excel...  
 
 
PS: Для чего мне это нужно:  
Я с этого года встраиваю систему обновлений в надстройки, публикуемые на сайте.  
Так вот, надстройки формируют идентичные панели инструментов, и большинство кнопок (типа кнопок «О программе», «backup») ссылаются на одноимённые макросы.  
И я вот только сегодня заметил, что, нажимая кнопку «О программе» в одной программе, открывается форма из другой программы.  
 
PPS: Менять к каждом файле названия макросов на уникальные - не вариант  
(модуль обновления я встраиваю в множество файлов, и каждый раз переименовывать макросы - плохая идея)
 
особо не вникал, option private module, не?
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Спасибо, nerv, не знал про существование такой директивы.  
По идее, должно было помочь, - но, увы, ничего не изменилось (проблема осталась)  
 
Что удивительно - ручной запуск макроса командой, назначенной кнопке,  
выполняется корректно  
(если в окне Immediate набрать run "test3.xls!MyMacro", то запускается макрос из нужного файла - test3)  
 
По идее, кнопке назначена та же самая команда - "test3.xls!MyMacro"  
Почему результат различается?
 
> Может быть это ActionControl глючит, а макрос-то нужный вызывается?  
 
Не, Дима, в том-то и дело, что вызывается "ненужный"  
Я на 2 разных надстройках тестировал - жал кнопку "О программе"  
 
 
Сначала обе кнопки ссылались на один файл, в котором были отображены листы (XLS) - открывали форму из XLS.  
 
Потом я нажал кнопку скрытия листов на панели XLA, но скрылись листы у XLS (т.к. опять макрос не тот запустился)  
 
После этого обе кнопки "О программе" стали запускать макрос уже не из XLS, а их XLA (видимо, потому, что XLS перестал быть активной книгой)  
 
 
Точки останова ставить негде - макрос MyMacro состоит из одной строки кода.  
Код макроса ни при чем - я тестировал на макросах из одной строки типа Msgbox 1, msgbox 2 и т.п.  
 
Так что вопрос пока остаётся открытым...
 
гугл привел меня сюда http://msdn.microsoft.com/en-us/library/aa141695%28v=office.10%29.aspx цитата: When multiple command bar controls use the same OnAction property setting, you can use the ActionControl property and the Parameter property to determine which command bar button is calling the procedure. You can also use VBA code that executes in response to CommandBar and CommandBarControl events. For more information about these events, see "Working with Command Bar Events" later in this chapter. переводчик: Когда несколько элементов управления панели команд использовать те же настройки свойств OnAction, вы можете использовать свойство ActionControl и параметров свойство, чтобы определить, какая кнопка панели команд вызова процедуры. Вы также можете использовать VBA код, который выполняется в ответ на CommandBar и CommandBarControl событий. Для получения дополнительной информации об этих событиях см. в разделе "Работа с панели команд событий" далее в этой главе.  
 
я так понял решить можно через классы http://msdn.microsoft.com/en-us/library/aa141696%28v=office.10%29.aspx [не проверял]
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Можно пару строчек кода? А то не пойму, что именно имеется ввиду.
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
> Я так думаю, что быстрее здесь поможет Application.Run  
 
Я правильно понял, что мы всем кнопкам назначаем один и тот же макрос,  
и в поле TAG у каждой кнопки прописываем что-то типа "test3.xls!MyMacro"  
 
Потом в этом едином макросе смотрим, что за тег у вызвавшей его кнопки (кнопку определяем по ActionControl),    
и через application.Run уже запускаем нужный макрос?  
 
Вариант, конечно, "оригинальный", но, судя по всему, работать будет.  
Спасибо, Дима, за идею. По крайней мере, решение найдено.  
 
Посмотрим, может, кто из спецов придумает (подскажет) решение попроще.  
 
 
nerv, с классами что-то там сильно замудрено,  
а из куска английского текста с переводом, как ни странно, я мало что понял.  
Ща буду вникать)
 
вариант
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
nerv, спасибо за вариант.  
Всё работает - но применить в своих программах этот способ у меня вряд ли получится по 2 причинам:  
 
1) кнопок на панели инструментов у меня много, и в каждой программе - разное количество.  
Прописывать же каждый раз новые переменные, и мудрить с обработчиками - очень не хочется.  
 
2) В своих прогах я не использую глобальные переменные, поэтому часто использую оператор End (при возникновении неисправимых ошибок)  
А после такого оператора (или после сохранения книги) эти переменные могут обнулиться, и кнопки перестанут работать.  
А когда главное меню программы перестаёт откликаться на нажатия - не есть айс...
 
А Application.Caller никак не прикрутить?
 
\  
 
18333
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Игорь, тестировать некогда, но в порядке бреда: может быть так, что кнопки создаются с одинаковыми ID и всем присваивается OnAction последней созданной кнопки с тем же ID?
KL
 
nerv, вот это да... то, что нужно было!  
тот же код, что и у меня, но работает корректно...  
 
пока увидел только одно отличие - контролы (кнопки) добавляются с параметром Temporary = TRUE  
Неужели этого достаточно?  
Или я что-то проглядел?  
 
 
KL, я не проверял ID кнопок, но, по идее, они и должны быть одинаковыми - ведь их создаёт один и тот же макрос, разве нет?  
OnAction точно присваивается какой надо - ActionControl.OnAction выдавал верный результат.  
 
 
Сейчас проверю решение от nerv на своих файлах - надеюсь, всё заработает.  
Ещё раз всем спасибо за помощь!
 
Игорь, что затих-то? Заманил да бросил. Интересно же ;)
KL
 
Увы, nerv, ничего у меня не получилось...  
Всё работает ровно до тех пор, пока листы в файлах видимые.  
 
Достаточно было во всех твоих 3 файлах поставить IsAddin=TRUE, сохранить их, и перезапустить, как все 3 кнопки начали вызывать один и тот же макрос (из файла, который был запущен первым)  
 
 
Кирилл, все кнопки на создаваемых этим кодом панелях инструментов получают один и тот же ID = 1  
Насколько я понимаю, способа изменить этот ID нет.  
Да и не в нём дело - когда файлы XLS работают в режиме IsAddin=FALSE (листы отображаются), ID контролов по-прежнему равны единице, - но ведь всё работает корректно...  
 
УТОЧНЕНИЕ: проблема проявляется во всех версиях Excel  
(я сначала писал, что в 2010 вроде как всё работает, но, как выяснилось, и там такая же история)  
Короче, пока листы книг видны - всё чётко, как только скрываем листы - начинаются проблемы.  
 
 
Для тестирования снова прикрепляю 3 файла XLS со скрытыми листами (IsAddin=TRUE)  
Жду идей, коллеги, как победить проблему.
 
>Насколько я понимаю, способа изменить этот ID нет.  
Я вроде как менял его при создании контрола, но это не помогло.  
 
EducatedFool, может просто оставить листы видимыми и не заморачиваться?
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Конечно, решение, предложенное Дмитрием (The_Prist) работает,  
но хотелось бы всё таки разобраться в проблеме, и решить её другим способом.  
(потому что я использую свойство TAG у контролов для других целей - например, в выпадающих меню я всем контролам назначаю один макрос, а в теге прописываю параметры)  
 
Напомню, Дима предложил такое решение:  
 
Private Sub Workbook_Open()  
   With Application  
       On Error Resume Next  
       .CommandBars(.ThisWorkbook.Name).Delete  
       On Error GoTo 0  
       With .CommandBars.Add(.ThisWorkbook.Name, msoBarTop, False, True)  
           .Visible = True  
           With .Controls.Add(, , , , True)  
               .Caption = Application.ThisWorkbook.Name  
               .Style = msoButtonIconAndCaption  
               .OnAction = "CommonMacro"  
               .Tag = "'" & ThisWorkbook.Name & "'!macro"  
               .FaceId = 487  
           End With  
       End With  
   End With  
End Sub  
 
 
Sub macro()  
   MsgBox 2  
End Sub  
 
Private Sub CommonMacro()  
   On Error Resume Next  
   Run Application.CommandBars.ActionControl.Tag  
End Sub  
 
 
 
Пытался добавить сюда вызов с параметром (свойство .parameter),  
но что-то не работает:  
 
With .Controls.Add(, , , , True)  
               .Caption = Application.ThisWorkbook.Name  
               .Style = msoButtonIconAndCaption  
               .OnAction = "CommonMacro"  
               .Tag = "'" & ThisWorkbook.Name & "'!macro"  
               .FaceId = 487  
               .Parameter = "Parameter = " & ThisWorkbook.Name  
           End With  
 
 
Sub macro(ByVal param As String)  
   MsgBox 3, , param  
End Sub  
 
Sub CommonMacro(ByVal param)  
   On Error Resume Next  
   Run Application.CommandBars.ActionControl.Tag, param  
End Sub
 
{quote}{login=nerv}{date=11.02.2012 12:13}{thema=}{post}  
EducatedFool, может просто оставить листы видимыми и не заморачиваться?{/post}{/quote}  
 
Нет, этот вариант исключается.  
 
В основном панели инструментов я добавляю к надстройкам,  
а пользоваться надстройками (тем более, несколькими одновременно),  
у которых листы не скрыты, - по меньшей мере, неудобно.
 
Может надо установить какое-нибудь свойство книги/приложения? Раз уж IsAddin устанавливается в TRUE.
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
{quote}{login=The_Prist}{date=11.02.2012 01:31}{thema=}{post}не увидел перинятия свойства Parameter от вызываемого контрола:  
Run Application.CommandBars.ActionControl.Tag, Application.CommandBars.ActionControl.Parameter{/post}{/quote}  
 
Я так первым делом попробовал - не получилось.  
Потом понял, что кнопка вызывает макрос CommonMacro уже с параметром.  
 
Но при тестировании выяснилось, что при назначении кнопки свойства Parameter макрос CommonMacro вообще не запускается.  
Почему - не понял, да и разбираться не стал, ибо это очередное усложнение макроса  
(в крайнем случае, пропишу всё в свойство TAG - а в CommonMacro через Split разделю имя макроса от параметров)  
 
Просто ещё есть шанс, что кто-то посоветует простое решение - типа добавить пару символов в OnAction, чтобы всё заработало как при открытых листах книги.
 
Sub macro()  
   Application.Run "'" & Application.Caller(2) & "'!macro"  
End Sub  
 
 
не?
Живи и дай жить..
 
слэн, и что получится?  
макрос вызывает сам себя, и так до бесконечности?
 
Странно... вроде точно также пробовал - не работало.  
Сейчас посмотрел в твоём файле - всё работает.  
 
Что ж, пока буду использовать такой способ запуска.  
Главное - запускается то что нужно (хоть и выглядит код странно)
 
игорь,присмтрись внимательнее  
это не один макрос  
ну ивообще их два должно быть, но мне как всегда лень  
ведь суть не в этом - неужели и тебе готовое решение выкладывать? скажу только что у меня сработало - троечка выскочила, а первонач была единичка
Живи и дай жить..
 
слэн, я присмотрелся.  
разумеется, готовое решение не требуется.  
Мне нужен универсальный код, который будет одинаковым в разных файлах.  
 
Я правильно понял, что в каждую книгу мне надо прописать это?  
 
Sub macro()  
   Application.Run "'" & Application.Caller(2) & "'!macro"  
   MsgBox 1  
End Sub  
 
 
Ну и что получается?  
Я не проверил сначала код - просто увидел, что макрос macro из случайной книги запускает макрос macro из нужной книги.  
 
Кроме того, рекомендованную вами строку кода просто некуда больше засунуть, кроме как в макрос macro.  
А такой способ ни к чему хорошему не приведёт - максимум зацикливание.  
 
Более того, этот вариант даже к зацикливанию не приводит - он просто не работает  
На моём компе вылетает ошибка, поскольку Application.Caller в момент работы макроса представляет собой двумерный массив из 2 элементов следующего содержания:  
Application.Caller(1) = 1  
Application.Caller(2) = 0  
(причем, такие значения у Application.Caller при запуске с любой из 3 кнопок)  
 
Разумеется, Excel не может найти файл '0.xls' - и вылетает ошибка.  
 
--------------  
Впрочем, тему можно считать закрытой, - решение, предложенное Дмитрием, работает стабильно,  
поэтому я решил на нём и остановиться.  
 
Тему имеет смысл продолжать, только если удастся найти или устранить причину столь загадочного поведения Excel, когда кнопки на панелях инструментов корректно работают лишь при видимых листах.
 
вот этот код работает у меня в 2010м мксель( третий дома снес, но вчера, когда писал первый раз, то делал на 2003, но не проверил окончательно - изменил только макрос в первом из загруженных файлов.. - отсюда и недопонимание)  
 
см влож
Живи и дай жить..
 
установил снова 2003й - все работает.
Живи и дай жить..
 
слэн, при нажатии любой из кнопок - результат один и тот же, ошибка (причину я описывал ранее - у вас и у меня application.Caller, судя по всему, имеют разные значения): http://ExcelVBA.ru/pictures/20120212-7s8-40kb.jpg По сути, это то же самое, что предложил Дима (и что я реализовал). Только в том варианте, через RUN application.CommandBars.ActionControl.Tag, или через RUN application.CommandBars.ActionControl.OnAction, всё работает.
 
Стал тестировать вариант с application.Caller - выяснилось, что он всё же работает (но только в Excel 2007 и 2010)  
В 2003-м по-прежнему ошибка.  
 
В любом случае, я остановлюсь на ActionControl - он работает в любой версии.
Страницы: 1 2 След.
Наверх