Есть проблемка с сочетанием клавиш (горячих клавиш) для запуска макроса.
Есть Книга1 с макросом Макрос1, сочетание клавиш "Ctrl+q". и есть Книга2 с макросом Макрос2, сочетание клавиш тоже "Ctrl+q". (макросы при этом находятся в теле модуля)
Активирована Книга1. При нажатии комбинации "Ctrl+q" запускается макрос Книги1. Если активировать Книгу2, и снова нажать "Ctrl+q", то снова запускается макрос Книги1, а не Книги2. Только если закрыть Книгу1, то только тогда при активированной Книги2 запустится Макрос2.
Как решить эту проблемку? Чтобы при нажатии "Ctrl+q" запускался макрос именно тот, который находится в активированной книге (т.е. чтобы макросы других книг при этом не видел Excel)
И ещё, как решить эту проблемку, если названия макросов при этом будут одинаковые? P.S. Задать разные комбинации клавиш не вариант.
Приветствую!
Есть проблемка с сочетанием клавиш (горячих клавиш) для запуска макроса.
Есть Книга1 с макросом Макрос1, сочетание клавиш "Ctrl+q". и есть Книга2 с макросом Макрос2, сочетание клавиш тоже "Ctrl+q". (макросы при этом находятся в теле модуля)
Активирована Книга1. При нажатии комбинации "Ctrl+q" запускается макрос Книги1. Если активировать Книгу2, и снова нажать "Ctrl+q", то снова запускается макрос Книги1, а не Книги2. Только если закрыть Книгу1, то только тогда при активированной Книги2 запустится Макрос2.
Как решить эту проблемку? Чтобы при нажатии "Ctrl+q" запускался макрос именно тот, который находится в активированной книге (т.е. чтобы макросы других книг при этом не видел Excel)
И ещё, как решить эту проблемку, если названия макросов при этом будут одинаковые? P.S. Задать разные комбинации клавиш не вариант.Aleksio
Ok. Вот для примера два файла. Оба они сохранены на компьютере на одном жёстком диске. Откройте их, и нажмите "Ctrl+q". Если нажать в Книге1, то будет запущен макрос Книги1. Если активировать Книгу2, и нажать "Ctrl+q", то снова запустится макрос Книги1, а нужно, чтобы запустился макрос Книги2.
Названия макросов в примере одинаковые, но если разные названия макросов как-то может помочь решить проблему, то можно назвать по-разному (но на деле это файл-шаблон и макросы названы одинаково.
Что касается содержимого файлов, то оно в 95% случаев всегда отличается ячейкой B2. Все остальные данные на листах могут как совпадать, так и различаться.
Ok. Вот для примера два файла. Оба они сохранены на компьютере на одном жёстком диске. Откройте их, и нажмите "Ctrl+q". Если нажать в Книге1, то будет запущен макрос Книги1. Если активировать Книгу2, и нажать "Ctrl+q", то снова запустится макрос Книги1, а нужно, чтобы запустился макрос Книги2.
Названия макросов в примере одинаковые, но если разные названия макросов как-то может помочь решить проблему, то можно назвать по-разному (но на деле это файл-шаблон и макросы названы одинаково.
Что касается содержимого файлов, то оно в 95% случаев всегда отличается ячейкой B2. Все остальные данные на листах могут как совпадать, так и различаться.Aleksio
горячие клавиши прописываются в настройке excel как вариант делать такой код в личной книге макросов, его запускать по горячей клавише ctrl+q
[vba]
Код
Sub ActivMakro() Dim str As String str = "'" & ActiveWorkbook.Name & "'!Макрос1" ActiveWorkbook.Application.Run str End Sub
[/vba]
если в активной книге нет макрос1, будет ошибка выскакивать макрос в обоих книгах должен называться одинаково, и если менять название будете ! знак несотрите
горячие клавиши прописываются в настройке excel как вариант делать такой код в личной книге макросов, его запускать по горячей клавише ctrl+q
[vba]
Код
Sub ActivMakro() Dim str As String str = "'" & ActiveWorkbook.Name & "'!Макрос1" ActiveWorkbook.Application.Run str End Sub
[/vba]
если в активной книге нет макрос1, будет ошибка выскакивать макрос в обоих книгах должен называться одинаково, и если менять название будете ! знак несотритеK-SerJC
Благими намерениями выстелена дорога в АД.
Сообщение отредактировал K-SerJC - Четверг, 12.01.2017, 08:47
В модуле ЭтаКнига каждой книги на событие Workbook_Activate прицепите переназначение горячих клавиш. В Книга1:[vba]
Код
Private Sub Workbook_Activate() Application.OnKey "^q", "Макрос1" ' Ctrl+Q - вызов макроса "Макрос1" из данной книги End Sub
[/vba]В Книга2:[vba]
Код
Private Sub Workbook_Activate() Application.OnKey "^q", "Макрос2" ' Ctrl+Q - вызов макроса "Макрос2" из данной книги End Sub
[/vba]
-------------------- Если не будет срабатывать, то можно ещё и имя книги, где макрос расположен прицепить, как Вам советовали выше. Да и обработчик ошибок не помешает добавить Ну, типа В Книга1:[vba]
Код
Private Sub Workbook_Activate() On Error Resume Next Application.OnKey "^q", "'" & ActiveWorkbook.Name & "'!Макрос1" ' Ctrl+Q - вызов макроса "Макрос1" из активной книги End Sub
[/vba]В Книга2:[vba]
Код
Private Sub Workbook_Activate() On Error Resume Next Application.OnKey "^q", "'" & ActiveWorkbook.Name & "'!Макрос2" ' Ctrl+Q - вызов макроса "Макрос2" из активной книги End Sub
[/vba]
В модуле ЭтаКнига каждой книги на событие Workbook_Activate прицепите переназначение горячих клавиш. В Книга1:[vba]
Код
Private Sub Workbook_Activate() Application.OnKey "^q", "Макрос1" ' Ctrl+Q - вызов макроса "Макрос1" из данной книги End Sub
[/vba]В Книга2:[vba]
Код
Private Sub Workbook_Activate() Application.OnKey "^q", "Макрос2" ' Ctrl+Q - вызов макроса "Макрос2" из данной книги End Sub
[/vba]
-------------------- Если не будет срабатывать, то можно ещё и имя книги, где макрос расположен прицепить, как Вам советовали выше. Да и обработчик ошибок не помешает добавить Ну, типа В Книга1:[vba]
Код
Private Sub Workbook_Activate() On Error Resume Next Application.OnKey "^q", "'" & ActiveWorkbook.Name & "'!Макрос1" ' Ctrl+Q - вызов макроса "Макрос1" из активной книги End Sub
[/vba]В Книга2:[vba]
Код
Private Sub Workbook_Activate() On Error Resume Next Application.OnKey "^q", "'" & ActiveWorkbook.Name & "'!Макрос2" ' Ctrl+Q - вызов макроса "Макрос2" из активной книги End Sub
Кстати, заметил интересную вещь: если ещё была открыта Книга3, в которой есть иной макрос, и ему сочетание клавиш Ctrl+q присвоено обычным способом через Параметры макросов через Alt+F8, то её перебивают макросы Книг1 или Книги2. И даже если закрыть Книгу 1 и 2, то после нажатия Ctrl+q открывается уже закрытая Книга 1 или 2, и выполняется макрос этих книг. Но это не проблема, просто запрограммирую все книги таким способом. Что касается имени книги ActiveWorkbook.Name, то правильно работает что в одном, что в другом случае.
По поводу решения K-SerJC: Прописывать в личную книгу макросов думаю нежелательно, ибо тогда всегда при нажатии клавиш Ctrl+q будет запускаться ActivMakro, который запускает Макрос1. Но возможно в какой-нибудь Книге на это сочетание должен был быть запрограммирован совсем иной макрос, но будет запускаться всё равно Макрос1, который вполне вероятно может там находиться. Выход только назвать не Макрос1, а уникальным названием, чтобы не запустился какой-нибудь Макрос1, который не должен был быть запущен. Но всё равно, даже тогда комбинация клавиш Ctrl+q этого файла будет убита, нужный макрос, запрограммированный на эту комбинацию запускаться не будет.
Попробовал записать предложенный код в Книге1 и в Книге2 в модулях ЭтаКнига. Работает, но до тех пор, пока не открывается Книга3, в которой есть Макрос с иным названием и при этом запрограммированный тоже на Ctrl+q. С этого момента во всех трёх книгах запускается макрос Книги3. Но всё равно спасибо за такое интересное решение.
Думаю тему можно закрывать, решение найдено. Спасибо!
Alex_ST, K-SerJC, ОГРОМНОЕ СПАСИБО!!!
Испытал. Решение Alex_ST как раз то, что нужно.
Кстати, заметил интересную вещь: если ещё была открыта Книга3, в которой есть иной макрос, и ему сочетание клавиш Ctrl+q присвоено обычным способом через Параметры макросов через Alt+F8, то её перебивают макросы Книг1 или Книги2. И даже если закрыть Книгу 1 и 2, то после нажатия Ctrl+q открывается уже закрытая Книга 1 или 2, и выполняется макрос этих книг. Но это не проблема, просто запрограммирую все книги таким способом. Что касается имени книги ActiveWorkbook.Name, то правильно работает что в одном, что в другом случае.
По поводу решения K-SerJC: Прописывать в личную книгу макросов думаю нежелательно, ибо тогда всегда при нажатии клавиш Ctrl+q будет запускаться ActivMakro, который запускает Макрос1. Но возможно в какой-нибудь Книге на это сочетание должен был быть запрограммирован совсем иной макрос, но будет запускаться всё равно Макрос1, который вполне вероятно может там находиться. Выход только назвать не Макрос1, а уникальным названием, чтобы не запустился какой-нибудь Макрос1, который не должен был быть запущен. Но всё равно, даже тогда комбинация клавиш Ctrl+q этого файла будет убита, нужный макрос, запрограммированный на эту комбинацию запускаться не будет.
Попробовал записать предложенный код в Книге1 и в Книге2 в модулях ЭтаКнига. Работает, но до тех пор, пока не открывается Книга3, в которой есть Макрос с иным названием и при этом запрограммированный тоже на Ctrl+q. С этого момента во всех трёх книгах запускается макрос Книги3. Но всё равно спасибо за такое интересное решение.
Думаю тему можно закрывать, решение найдено. Спасибо!Aleksio
Private Sub Workbook_Deactivate() On Error Resume Next Application.OnKey "^q", "" ' Ctrl+Q - сброс End Sub
[/vba] Только это не возврат, а сброс и в моем случае вызова стандартного поиска ctrl+f не происходит. И судя по обсуждению от 2010 у соседей решения не было тогда, так и сейчас.
Alex_ST, пригодилось и мне, я правда дополню[vba]
Код
Private Sub Workbook_Deactivate() On Error Resume Next Application.OnKey "^q", "" ' Ctrl+Q - сброс End Sub
[/vba] Только это не возврат, а сброс и в моем случае вызова стандартного поиска ctrl+f не происходит. И судя по обсуждению от 2010 у соседей решения не было тогда, так и сейчас.bmv98rus
Замечательный Временно просто медведь , процентов на 20.
Сообщение отредактировал bmv98rus - Четверг, 12.01.2017, 21:59
bmv98rus, это, конечно, "по канонам" правильно: "закончил работу - оставь всё как было" , но на практике имеет смысл делать только тогда, когда Вы своим назначением изменяете какой-нибудь стандартный хоткей. Хотя... Освободить даже не стандартный хоткей не помешает - это точно! [offtop](К стати, я уже наверное с 2000 года у себя в Personal.xls Excel'я и в Nоrmal.dot Word'a на хоткей Ctrl+Q прописываю специальную вставку значения без формата и формул. Привык за столько лет до уровня инстинктивной моторики пальцев так же как к стандартным Ctrl+C , Ctrl+V и т.п.)[/offtop]
bmv98rus, это, конечно, "по канонам" правильно: "закончил работу - оставь всё как было" , но на практике имеет смысл делать только тогда, когда Вы своим назначением изменяете какой-нибудь стандартный хоткей. Хотя... Освободить даже не стандартный хоткей не помешает - это точно! [offtop](К стати, я уже наверное с 2000 года у себя в Personal.xls Excel'я и в Nоrmal.dot Word'a на хоткей Ctrl+Q прописываю специальную вставку значения без формата и формул. Привык за столько лет до уровня инстинктивной моторики пальцев так же как к стандартным Ctrl+C , Ctrl+V и т.п.)[/offtop]Alex_ST
С уважением, Алексей MS Excel 2003 - the best!!!
Сообщение отредактировал Alex_ST - Четверг, 12.01.2017, 22:11
bmv98rus, спасибо за дополнение. Теперь можно не беспокоиться, что в каком-нибудь ином файле пользователю вздумается нажать волшебное для него "Ctrl+q" + заодно деактивируются и все другие "Ctrl+q" в других файлах, даже после закрытия Книги1.
P.S. Кстати, до создания этой темы, пока бороздил Интернет в поиске решения, видел ту тему 2010 г. про Application.OnKey, но почему-то в голову не пришло соединить это с Workbook_Activate. А ларчик то оказывается просто открывался.
bmv98rus, спасибо за дополнение. Теперь можно не беспокоиться, что в каком-нибудь ином файле пользователю вздумается нажать волшебное для него "Ctrl+q" + заодно деактивируются и все другие "Ctrl+q" в других файлах, даже после закрытия Книги1.
P.S. Кстати, до создания этой темы, пока бороздил Интернет в поиске решения, видел ту тему 2010 г. про Application.OnKey, но почему-то в голову не пришло соединить это с Workbook_Activate. А ларчик то оказывается просто открывался.Aleksio
Сообщение отредактировал Aleksio - Четверг, 12.01.2017, 22:35
ну да, конечно. Уточнение абсолютно верное. Это именно сброс назначения хоткея. И как раз для того, чтобы можно было восстановить, я в 2010 году спрашивал на Планете как можно считать текущее назначение. Но даже гуру-Планетяне мне тогда не смогли помочь, к сожалению...
ну да, конечно. Уточнение абсолютно верное. Это именно сброс назначения хоткея. И как раз для того, чтобы можно было восстановить, я в 2010 году спрашивал на Планете как можно считать текущее назначение. Но даже гуру-Планетяне мне тогда не смогли помочь, к сожалению...Alex_ST
Aleksio, К стати не все так плохо, при переключении в другие книги стандартный вызов срабатывает после сброса, но в той которой кодил, естественно нет. а так как надо было на одном листе иметь вызов формы, то пришлось [vba]
Код
Private Sub Worksheet_Deactivate() On Error Resume Next Application.OnKey "^f", "StandardFind" End Sub
Sub standardFind() Application.CommandBars.FindControl(ID:=1849).Execute End Sub
[/vba]
Aleksio, К стати не все так плохо, при переключении в другие книги стандартный вызов срабатывает после сброса, но в той которой кодил, естественно нет. а так как надо было на одном листе иметь вызов формы, то пришлось [vba]
Код
Private Sub Worksheet_Deactivate() On Error Resume Next Application.OnKey "^f", "StandardFind" End Sub
Sub standardFind() Application.CommandBars.FindControl(ID:=1849).Execute End Sub
Ох, как же я не люблю вызывать команды по их ID Абсолютно не читаемый с листа код получается. И пусть даже написаны комментарии, но ведь ошибка в указании номера ID абсолютно не отлавливается! А последствия вызова не той команды могут быть самыми плачевными, учитывая ещё, что действие макросов по UnDo не отменяется... Но если уж деваться некуда и от использования встроенных команд Excel отказаться не удаётся, то к точному определению ID относиться нужно очень серьёзно. Для этого я в своё время написал процедуру[vba]
Код
Sub Get_Control_ID_New() ' создать новую книгу и вывести на лист список номеров стандартных команд Dim sTxt$ Dim Arr: Arr = Split("msoControlCustom msoControlButton msoControlEdit msoControlDropdown msoControlComboBox msoControlButtonDropdown msoControlSplitDropdown msoControlOCXDropdown msoControlGenericDropdown msoControlGraphicDropdown msoControlPopup msoControlGraphicPopup msoControlButtonPopup msoControlSplitButtonPopup msoControlSplitButtonMRUPopup msoControlLabel msoControlExpandingGrid msoControlSplitExpandingGrid msoControlGrid msoControlGauge msoControlGraphicCombo msoControlPane msoControlActiveX msoControlSpinner msoControlLabelEx msoControlWorkPane msoControlAutoCompleteCombo") ' подготовка массива-переводчика номера Type в текст msoType Dim oCmBr As CommandBar, oCntrl As CommandBarControl, li As Long, xItem Application.ScreenUpdating = False Dim oDict: Set oDict = CreateObject("Scripting.Dictionary"): oDict.CompareMode = vbTextCompare ' Создаем словарь oDict.Item("header") = Array("Caption", "ID", "Type", "msoType") ' Заголовок таблицы (попытка чтения значения по отсутствующему ключу добавит ключ в словарь) For Each oCmBr In Application.CommandBars For Each oCntrl In oCmBr.Controls oDict.Item(oCntrl.ID) = Array(oCntrl.Caption, oCntrl.ID, oCntrl.Type, Arr(oCntrl.Type)) ' заносим в словарь массивы значений под ключами oCntrl.ID Next oCntrl Next oCmBr Arr = oDict.Items ' передать значения в массив. Arr сейчас массив массивов. Его нельзя просто вывести на лист Arr = Application.Transpose(Application.Transpose(Arr)) ' двойное транспонирование превращает массив массивов в 2D-массив Application.Workbooks.Add ' создаём новую книгу ActiveWorkbook.Sheets(1).Activate ActiveSheet.Cells(1, 1).Resize(UBound(Arr, 1), UBound(Arr, 2)).Value = Arr ' массив - на лист ActiveSheet.Name = "Excel Control ID" ' оформление Set oCmBr = Nothing: Set oCntrl = Nothing Application.ScreenUpdating = True End Sub
[/vba]
Ох, как же я не люблю вызывать команды по их ID Абсолютно не читаемый с листа код получается. И пусть даже написаны комментарии, но ведь ошибка в указании номера ID абсолютно не отлавливается! А последствия вызова не той команды могут быть самыми плачевными, учитывая ещё, что действие макросов по UnDo не отменяется... Но если уж деваться некуда и от использования встроенных команд Excel отказаться не удаётся, то к точному определению ID относиться нужно очень серьёзно. Для этого я в своё время написал процедуру[vba]
Код
Sub Get_Control_ID_New() ' создать новую книгу и вывести на лист список номеров стандартных команд Dim sTxt$ Dim Arr: Arr = Split("msoControlCustom msoControlButton msoControlEdit msoControlDropdown msoControlComboBox msoControlButtonDropdown msoControlSplitDropdown msoControlOCXDropdown msoControlGenericDropdown msoControlGraphicDropdown msoControlPopup msoControlGraphicPopup msoControlButtonPopup msoControlSplitButtonPopup msoControlSplitButtonMRUPopup msoControlLabel msoControlExpandingGrid msoControlSplitExpandingGrid msoControlGrid msoControlGauge msoControlGraphicCombo msoControlPane msoControlActiveX msoControlSpinner msoControlLabelEx msoControlWorkPane msoControlAutoCompleteCombo") ' подготовка массива-переводчика номера Type в текст msoType Dim oCmBr As CommandBar, oCntrl As CommandBarControl, li As Long, xItem Application.ScreenUpdating = False Dim oDict: Set oDict = CreateObject("Scripting.Dictionary"): oDict.CompareMode = vbTextCompare ' Создаем словарь oDict.Item("header") = Array("Caption", "ID", "Type", "msoType") ' Заголовок таблицы (попытка чтения значения по отсутствующему ключу добавит ключ в словарь) For Each oCmBr In Application.CommandBars For Each oCntrl In oCmBr.Controls oDict.Item(oCntrl.ID) = Array(oCntrl.Caption, oCntrl.ID, oCntrl.Type, Arr(oCntrl.Type)) ' заносим в словарь массивы значений под ключами oCntrl.ID Next oCntrl Next oCmBr Arr = oDict.Items ' передать значения в массив. Arr сейчас массив массивов. Его нельзя просто вывести на лист Arr = Application.Transpose(Application.Transpose(Arr)) ' двойное транспонирование превращает массив массивов в 2D-массив Application.Workbooks.Add ' создаём новую книгу ActiveWorkbook.Sheets(1).Activate ActiveSheet.Cells(1, 1).Resize(UBound(Arr, 1), UBound(Arr, 2)).Value = Arr ' массив - на лист ActiveSheet.Name = "Excel Control ID" ' оформление Set oCmBr = Nothing: Set oCntrl = Nothing Application.ScreenUpdating = True End Sub
Согласен, сам не доволен такими жесткими привязками. Но подругому эту форму не вызвать. Сперва сделал по имени и подорвался на том что comandbar("edit") срабатывает на любой локализации. а cotrol сам локализован и "Find... "/"Найти....". Как в меню. Ну конечно сделал ветвление по двум языка, но потом плюнул и по ID сделал, ибо это давно не меняется :-);
Alex_ST,
Согласен, сам не доволен такими жесткими привязками. Но подругому эту форму не вызвать. Сперва сделал по имени и подорвался на том что comandbar("edit") срабатывает на любой локализации. а cotrol сам локализован и "Find... "/"Найти....". Как в меню. Ну конечно сделал ветвление по двум языка, но потом плюнул и по ID сделал, ибо это давно не меняется :-);bmv98rus
Замечательный Временно просто медведь , процентов на 20.