У меня есть надстройка. В нём много кодов. Многим из этих кодов я назначил комбинации клавиш. Теперь появилась потребность сделать такой готовый список: КОМБИНАЦИЯ КЛАВИШ НАЗВАНИЕ МАКРОСА Ctrl+Shift+Q Подготовить_месячный_отчёт Ctrl+E Подготовить_и_распечатать_ежедневные_данные Ctrl+Shift+J Сделать_формат_с_разделителями_и_покрасить_фон_на_желтый … … … … ВОПРОС – Можно ли это сделать макросом? (Чтобы долго и скучно не писать вручную) В поиске я нашёл вот эту тему – http://www.planetaexcel.ru/forum.php?thread_id=12742 В ней знатоки пишут, что наверняка эту задачу не решить макросом, и что скорее всего надо будет делать список вручную. НО: Шаг 1 Вот таким макросом: Sub ExportAllVBComponents() iTempPath$ = Environ("Temp") & "\" 'укажите свою папку For Each iVBComponent In ThisWorkbook.VBProject.VBComponents Select Case iVBComponent.type Case 1: iType$ = ".txt" Case 3: iType$ = ".frm" Case 2, 100: iType$ = ".cls" End Select iVBComponent.Export _ Filename:=iTempPath$ & iVBComponent.Name & iType$ Next End Sub можно все макросы экспортировать в текстовые файлы (.txt) в нужную папку.
Шаг 2 В этой папке выделить все текстовые файлы, нажать F2, написать 1 и нажать Ctrl+Enter Все файлы переименуются на 1 (1).txt, 1 (2).txt, 1 (3).txt, 1 (4).txt, 1 (5).txt, … и т.д.
Шаг 3 Вот таким макросом: Sub qwer() Dim TextLine For s = 1 To 31 i = 1 Open "d:\1\й (" & s & ").txt" For Input As #1 Do While Not EOF(1) Line Input #1, TextLine ThisWorkbook.Worksheets("лист1l").Cells(i, s).Value = TextLine i = i + 1 Loop Close #1 Next End Sub можно импортировать тексты этих самих текстовых файлов в книгу ЭКСЕЛЬ на один лист. При этом, текст 1-го макроса запишется на 1-й столбец, текст 2-го на 2-й, и так далее.
НЬЮАНС в том, что в тексте каждого макроса (если он Sub, и если ему была назначена клавиша) есть такая строка: Attribute Видимые_ячейки.VB_ProcData.VB_Invoke_Func = "е\n14" Или например: Attribute Налево.VB_ProcData.VB_Invoke_Func = "Д\n14" Это значит, что макросу ”Видимые_ячейки“ была назначена комбоклавиш Ctrl+е , а макросу ”Налево “ была назначена комбоклавиш Ctrl+Shift+д (поэтому буква Д написана там большими буквами)
Теперь наверно нетрудно написать макрос, который исходя из этой связи (то есть, имеется название макроса и чуть ниже есть назначенная к ней комбоклавиш) сможет составить ГОТОВЫЙ СПИСОК, который был описан в самом начале вопроса.
ПОСТСКРИПТУМ. Извиняюсь, что изложил вопрос так сложно. Дело в том, что я в VBA ещё не очень силён. Просто в других темах было написано, что сделать требуемый список придётся только вручную. А то что я изложил, ЕСЛИ НЕ ОШИБАЮСЬ, указывает на то, что всё таки можно поставленную задачу решить МАКРОСОМ. Я наверно шёл долгим путём, когда есть наиболее короткие пути, а именно: - может VB_ProcData.VB_Invoke_Func является каким-то свойством макроса, и необязательно заниматься экспорт-импортом - может после экспорта на .txt, необязательно импортировать тексты макросов на эксель, (то есть можно нужную информацию просто взять из .txt не ползуясь импортом) - может вообще не нужно переименовать текстовые файлы (макрос сам будет перебирать их по одному)
Короче, вроде бы обнаруженный мною :-) НЬЮАНС, состоит в том, что после шага №1, когда мы экспортировали тексты макросов на .txt, на этих текстовых файлах появились такие строки Attribute Налево.VB_ProcData.VB_Invoke_Func = "Д\n14" которые подсказывают назначенную к макросу комбоклавиш и которые дают СВЯЗЬ между именем макроса и комбоклавишами. А это уже даёт мысль о том, что поставленную задачу все таки можно решить МАКРОСОМ.
Если получится осуществить эту идею, прошу ответы писать сюда или на 3061916@mail.ru
Заранее выражаю благодарность всем, кто этим заинтересуется и потратит время на изучение.
P.S. №2 Если в одном модуле имеется несколько макросов, то они экспортируются на один файл .txt, но каждый Sub имеет свою строчку Attribute...
P.S. №3 Если получится, то вещь конечно очень удобная и нужная
И впрямь - можно в этот же код дописать чтение полученного текста, выборка строк вида Attribute DelDuplicates.VB_ProcData.VB_Invoke_Func = "l\n14" и из них фрагментов между "Attribute " и точкой, и "VB_Invoke_Func = " и "\n14". Всё это собираем в массив, выгружаем на лист (или сразу на лист, что проще - а скорость тут не нужна). Но конечно лучше бы вообще без экспорта обойтись - но я не знаю как...
суть того, что вы хотите сказать я могу понять прочитав ваше сообщение ещё раз :-) но на то, чтобы осуществить это у меня уйдёт слишком много времени (на чтение разных справок, на метод проб и ошибок, да и в конечном результате наверно получится очень большой код) причина - я ешё не силён в VBA
и вообще догадываюсь, что поставленная мною же задача именно для меня СЛОЖНОВАТА
просто в итоге хотелось получить универсальный готовый макрос. :-)
Ну что ж, завтра сяду на осуществление предоженного вами варианта (если сегодня кто-то не даст полностью готовый ответ) :-)
Ну вот такое получилось из Вашего примера - первые (ну или как получится, смотря где этот код) две строки брак - они тянутся из текста этого же макроса :( Как-то можно шлифануть, но думаю их легко вручную удалить. Попробуйте (у меня горячих нет, так что попробовать особо не на чем, одному макросу для теста задал - вытянуло):
Sub ExportAllVBComponents() Dim sh As Worksheet, x As Long x = 1 Set sh = Workbooks.Add(xlWBATWorksheet).Sheets(1) On Error Resume Next iTempPath$ = Environ("Temp") & "\" 'укажите свою папку For Each iVBComponent In ThisWorkbook.VBProject.VBComponents Select Case iVBComponent.Type Case 1: iType$ = ".txt" Case 3: iType$ = ".frm" Case 2, 100: iType$ = ".cls" End Select iVBComponent.Export _ Filename:=iTempPath$ & iVBComponent.Name & iType$
Dim a, i&, tmp a = Split(CreateObject("Scripting.FileSystemObject").Getfile(iTempPath$ & iVBComponent.Name & iType$).OpenasTextStream(1).readall, vbNewLine) ReDim b(1 To UBound(a), 1 To 2) ii = 0 For i = 0 To UBound(a) If InStr(a(i), "VB_ProcData.VB_Invoke_Func =") Then ii = ii + 1 b(ii, 1) = a(i - 1) b(ii, 2) = "Ctrl + " & Split(Split(a(i), "VB_Invoke_Func = ")(1), "\")(0) End If Next sh.Cells(x, 1).Resize(ii, 2) = b x = x + ii Next End Sub
Исправленный вариант, без лишних строк в результатах (обманул :) ) и без кавычек (предыдущие варианты можно убрать):
Sub ExportAllVBComponents() Dim sh As Worksheet, x As Long x = 1 Set sh = Workbooks.Add(xlWBATWorksheet).Sheets(1) On Error Resume Next iTempPath$ = Environ("Temp") & "\" 'укажите свою папку For Each iVBComponent In ThisWorkbook.VBProject.VBComponents Select Case iVBComponent.Type Case 1: iType$ = ".txt" Case 3: iType$ = ".frm" Case 2, 100: iType$ = ".cls" End Select iVBComponent.Export _ Filename:=iTempPath$ & iVBComponent.Name & iType$
Dim a, i&, tmp a = Split(CreateObject("Scripting.FileSystemObject").Getfile(iTempPath$ & iVBComponent.Name & iType$).OpenasTextStream(1).readall, vbNewLine) ReDim b(1 To UBound(a), 1 To 2) ii = 0 For i = 0 To UBound(a) If InStr(a(i), "VB_ProcData.VB_Invoke_Func =") Then If InStr(a(i), "Then") = 0 Then ii = ii + 1 b(ii, 1) = a(i - 1) b(ii, 2) = "Ctrl + " & Split(Split(a(i), "VB_Invoke_Func = " & """")(1), "\")(0) End If End If Next sh.Cells(x, 1).Resize(ii, 2) = b x = x + ii Next End Sub
Хм, так теперь и ошибки можно не подавлять - в этом варианте у меня их нет:
Sub ExportAllVBComponents() Dim sh As Worksheet, x As Long x = 1 Set sh = Workbooks.Add(xlWBATWorksheet).Sheets(1) iTempPath$ = Environ("Temp") & "\" 'укажите свою папку For Each iVBComponent In ThisWorkbook.VBProject.VBComponents Select Case iVBComponent.Type Case 1: iType$ = ".txt" Case 3: iType$ = ".frm" Case 2, 100: iType$ = ".cls" End Select iVBComponent.Export _ Filename:=iTempPath$ & iVBComponent.Name & iType$
Dim a, i&, tmp a = Split(CreateObject("Scripting.FileSystemObject").Getfile(iTempPath$ & iVBComponent.Name & iType$).OpenasTextStream(1).readall, vbNewLine) ReDim b(1 To UBound(a), 1 To 2) ii = 0 For i = 0 To UBound(a) If InStr(a(i), "VB_ProcData.VB_Invoke_Func =") Then If InStr(a(i), "Then") = 0 Then ii = ii + 1 b(ii, 1) = a(i - 1) b(ii, 2) = "Ctrl + " & Split(Split(a(i), "VB_Invoke_Func = " & """")(1), "\")(0) End If End If Next If ii <> 0 Then sh.Cells(x, 1).Resize(ii, 2) = b x = x + ii Next End Sub
{quote}{login= Б А Х Т И Ё Р}{date=21.03.2012 09:45}{thema=HUGO}{post}МОДЕРАТОРАМ - ОЧЕНЬ ПРОШУ, если можно в копилку.{/post}{/quote}В "Копилку" попадает то, что нужно сотням людей. А если туда помещать решения, которые нужны 2-3 посетителям - "Копилка" превратится в ТАКОЙ сборник, что найти там что-то нужное будет проосто невозможно. Кто мешает Вам создать свой файл-копилку?
иметь всегда под рукой макрос, который быстро сформирует готовый список: Название макроса - Описание макроса - Назначенная клавиша, нужно ИМХО многим. Особенно, кто назначил много клавиш к своим макросам, и кто эти макросы будет распостранять среди других пользователей. Но - решать Вам.
HUGO протестировал, всё нормально. Спасибо ещё раз
Не всё нормально - мне стыдно, но т.к. я горячими клавишами не пользуюсь, то я не учёл, что горячие клавиши могут быть не только Ctr+буква, но и Ctrl+Shift+буква. Нужно в код добавить анализ этих сочетаний, а не тупо делать b(ii, 2) = "Ctrl + " & Split(... Т.к. "кошки" для тренировки нет, а делать неохота - кода тоже нет...
Б А Х Т И Ё Р навёл меня на эту интересную тему. Сейчас на работе затишье. Разбираюсь в работе Игоря. Нашёл ещё одну гадкую не учтённую фенечку: в отличие от Sub, текст экспортированной Function в любом случае сопровождается стрингом-признаком назначения хоткеев "VB_ProcData.VB_Invoke_Func = ", но только там написано VB_ProcData.VB_Invoke_Func = " \n14" , т.е. хоткей вроде бы есть, но он не назначается. Надо убрать и доработать для хоткеев с Ctrl+Shift Тут бы, конечно, проще всего было бы RegExp использовать, но я их очень слабо знаю :( Ну, а пока покручу по-простому Мидами и Инстрингами Через часок, надеюсь, что-нибудь выложу.
С уважением, Алексей(ИМХО: Excel-2003 - THE BEST!!!)
Ну, вот примерно так (оптимизировать лень, но, вроде, все нюансы учтены) Sub ReadHotKeyes() 'считать и вывести на новый лист все программно назначенные горячие клавиши Dim iTempPath$, iType$ Dim iVBComponent As VBComponent Dim WB As Workbook, SH As Worksheet
Dim x&: x = 1 Set SH = ThisWorkbook.Sheets.Add(After:=Sheets(Sheets.Count)) iTempPath$ = Environ("Temp") & "\" ' или укажите свою папку 'iTempPath$ = "C:\Temp\" For Each WB In Application.Workbooks If WB.Name <> ThisWorkbook.Name Then For Each iVBComponent In WB.VBProject.VBComponents Select Case iVBComponent.Type Case 1: iType$ = ".txt" Case 3: iType$ = ".frm" Case 2, 100: iType$ = ".cls" End Select iVBComponent.Export Filename:=iTempPath$ & iVBComponent.Name & iType$
Dim A, B, i&, ii&, s$ A = Split(CreateObject("Scripting.FileSystemObject").Getfile(iTempPath$ & iVBComponent.Name & iType$).OpenasTextStream(1).ReadAll, vbNewLine) ReDim B(1 To UBound(A), 1 To 5) ii = 0 For i = 0 To UBound(A) If InStr(A(i), "VB_ProcData.VB_Invoke_Func =") Then If InStr(A(i), "VB_ProcData.VB_Invoke_Func = "" \n14""") = 0 Then ii = ii + 1 B(ii, 1) = WB.Name B(ii, 2) = iVBComponent.Name B(ii, 3) = Split(Mid(A(i), Len("Attribute ") + 1), ".")(0) ' считать имя макроса после "Attribute " B(ii, 4) = Replace(Split(A(i - 1), """")(1), "\r\n", Chr(10)) ' из предыдущей строки считать Description макроса B(ii, 5) = "Ctrl + " & Split(Split(A(i), "VB_Invoke_Func = """)(1), "\")(0) s = Split(Split(A(i), "VB_Invoke_Func = """)(1), "\")(0) B(ii, 5) = "Ctrl + " & IIf(LCase(s) = s, "", "Shift + ") & s End If End If Next If ii <> 0 Then SH.Cells(x, 1).Resize(UBound(B, 1), UBound(B, 2)) = B x = x + ii Next iVBComponent End If Next WB End Sub
У меня всего пара хоткеев назначена и та только через Ctrl+буква, но отработка Ctrl+Shift+буква тоже должна работать.
С уважением, Алексей(ИМХО: Excel-2003 - THE BEST!!!)
А как на счёт того, чтобы заглянуть в Tools-References и увидеть там, что не подключена библиотека Microsoft Visual Basic for Applications Extensibility 5.3 ? :) Вообще-то, это не обязательно, но удобнее работать если её подключить.
А я пока обедал (да ещё и "Планета" висела) малость причесал процедурку: прошерстил и перевёл на Dictionary - из него удобнее выводить на лист.
Останавливается на строке: sDescr = Replace(Split(Arr(i - 1), """")(1), "\r\n", vbLf) ' предыдущую строку разбить в массив "по кавычкам" и во втором элементе (1) заменить \r\n на перевод строки в Description макроса
Это произошло скорее всего из-за того, что при задании хоткеев не было задано описание (Description) макроса поставьте перед началом всех циклов OnError Resume Next и программа будет игнорировать ошибки.
С уважением, Алексей(ИМХО: Excel-2003 - THE BEST!!!)
{quote}{login=Alex_ST}{date=15.06.2012 09:45}{thema=}{post}...поставьте перед началом всех циклов OnError Resume Next и программа будет игнорировать ошибки...{/post}{/quote} спасибо, теперь всё работает нормально
Sub SetSubShortcut() ' назначение сочетания клавиш для макроса Application.MacroOptions macro:="Sumari", _ HasShortcutKey:=True, ShortcutKey:="q" ' строчная для Ctrl+, заглавная для Ctrl+Shift+ End Sub
Запустить из редактора VBA (F5) и сразу после – Ctrl+S. Я все макросы вытащил в .xla, теперь их по Alt+F8 не видно, к свойствам иначе не докопаться. Ну есть ещё один способ, с ескпортом/импортом .bas, но это извратъ.