Получить имя модуля в excel

Цитата
Для создания и очистки вовсе необязательно иметь имя процедуры. В VBA нет параллельных вычислений, код выполняется линейно.

Когда идет реализация ETL (extract transformation load) процесса с пост обработкой и предварительным высислением скачиваемого URL, где в задаче бизнес процесса может потребоваться скачка не только одного заранее известного файла/файлов из сети, а разнообразных архивов и т.д., то временных фаловых пожитков может быть много и разнообразно

Цитата
В начале процедуры создавать уникальное имя (номер),  обзывать этим именем папку, перед выходом из процедуры папку чистить.
Цитата
Для расширения своего кругозора и имя модуля и имя процедуры

, может быть это возможно, чтобы не плодить новых констант и переменных…. Авось когда-нибудь пригодится в будущем…

Я работаю над вспомогательным макросом, который изучает функцию списка для данного имени модуля в активной книге Excel. Пример: у меня есть имя модуля «Module1». Внутри этого модуля есть следующая функция или подпрограмма

Sub Sub1()
End Sub

Sub Sub2()
End Sub

Function Func1()
End Function

Function Func2()
End Function

Есть ли команда или процедура, которая может возвращать список имен функций и подпрограмм?

4 ответа

Лучший ответ

Вот ссылка на сайт Чипа Пирсона. Я иду сюда, когда мне нужно запрограммировать что-то, что влияет на VBE или использует его. Есть 2 раздела, которые могут вас заинтересовать. Один будет перечислять все модули в проекте. А другой перечислит все процедуры в модуле. Надеюсь, это поможет.

http://www.cpearson.com/excel/vbe.aspx

Код с сайта (обязательно посетите сайт для получения инструкций по добавлению ссылки на библиотеку объектов VBIDE:

Этот код перечислит все процедуры в Module1, начиная с ячейки A1.

Sub ListProcedures()
    Dim VBProj As VBIDE.VBProject
    Dim VBComp As VBIDE.VBComponent
    Dim CodeMod As VBIDE.CodeModule
    Dim LineNum As Long
    Dim NumLines As Long
    Dim WS As Worksheet
    Dim Rng As Range
    Dim ProcName As String
    Dim ProcKind As VBIDE.vbext_ProcKind

    Set VBProj = ActiveWorkbook.VBProject
    Set VBComp = VBProj.VBComponents("Module1")
    Set CodeMod = VBComp.CodeModule

    Set WS = ActiveWorkbook.Worksheets("Sheet1")
    Set Rng = WS.Range("A1")
    With CodeMod
        LineNum = .CountOfDeclarationLines + 1
        Do Until LineNum >= .CountOfLines
            ProcName = .ProcOfLine(LineNum, ProcKind)
            Rng.Value = ProcName
            Rng(1, 2).Value = ProcKindString(ProcKind)
            LineNum = .ProcStartLine(ProcName, ProcKind) + _
                    .ProcCountLines(ProcName, ProcKind) + 1
            Set Rng = Rng(2, 1)
        Loop
    End With

End Sub

Function ProcKindString(ProcKind As VBIDE.vbext_ProcKind) As String
    Select Case ProcKind
        Case vbext_pk_Get
            ProcKindString = "Property Get"
        Case vbext_pk_Let
            ProcKindString = "Property Let"
        Case vbext_pk_Set
            ProcKindString = "Property Set"
        Case vbext_pk_Proc
            ProcKindString = "Sub Or Function"
        Case Else
            ProcKindString = "Unknown Type: " & CStr(ProcKind)
    End Select
End Function


11

Community
9 Май 2018 в 00:48

Также существует бесплатный инструмент под названием «MZ-Tools». Установите его как надстройку, он нумерует ваши строки кода, генерирует стандартный код управления ошибками, проверяет неиспользуемые переменные, упорядочивает ваши функции и подпрограммы и … документирует ваш код, автоматически генерируя список ваших процедур с параметрами, комментариями и т.д …. Отличный инструмент!


3

Philippe Grondier
14 Апр 2010 в 02:45

Для тех, кто ищет функцию, возвращающую коллекцию строк, вот код, адаптированный из ответа guitarthrower:

'Collection of Strings of Sub names in that module
Private Function getAllProcNames(module As VBIDE.CodeModule) As Collection
    Dim lineNum As Integer
    Dim procName As String
    Dim coll As New Collection
    Dim ProcKind As VBIDE.vbext_ProcKind
    With module
        lineNum = .CountOfDeclarationLines + 1
        Do Until lineNum >= .CountOfLines
            procName = .ProcOfLine(lineNum, ProcKind)
            lineNum = .ProcStartLine(procName, ProcKind) + _
                    .ProcCountLines(procName, ProcKind) + 1
            coll.Add Item:=procName
        Loop
    End With
    Set getAllProcNames = coll
End Function

Переменная ProcKind просто выбрасывается — она ​​дает только имена.


2

Colm Bhandal
15 Ноя 2018 в 20:54

' a bit more info for those who like me looking for help
' without Chip Pearson and many others my programming would still be at
' x=x+4

    Option Explicit
'
' to list or sort procedure names
'
'
' on a spare sheet
'
Private Sub CommandButton1_Click()

   Dim URA$, RaSort As Range, ModName$, VBC As VBComponent

   Dim RangeStartAddress$: RangeStartAddress = "H11" ' any spare region

   Set RaSort = Range(RangeStartAddress)

   ' sort and display needs 5 un-bordered columns so best done from spare worksheet

   RaSort(0, 0).Resize(UsedRange.Rows.Count, 7).Clear
   URA = UsedRange.Address                 ' tidy of used range

   ModName = [c6]

   ' from cell C4 ... or whatever is needed name is needed

   ' OR ... to do all modules ... Skipping workbook try something like
   '
   'For Each VBC In ActiveWorkbook.VBProject.VBComponents

     ' Range("G11:N" & UsedRange.Rows.Count).Clear

     ' URA = UsedRange.Address

     'Set RaSort = Range("h11")

      'If Not (VBC.Name Like "Workbook") Then

       ' SortSUBLGFUN VBC.Name, RaSort

      'End If

  ' Next VBC


   SortSUBLGFUN ModName, RaSort

End Sub
'
' in a module
'
' sort the procedure names  for a module

' Reference to VBE  ..    Microsoft Visual Basic for Applications Extensibility

' RaSort as some spare Range CurrentRegion
'
Sub SortSUBLGFUN(ComponentName$, RaSort As Range)

   Dim LineI%, PBLI&, RowI&, RowOut&, LineStr$

   Dim PLSG As vbext_ProcKind              '  0 Fun or Sub 1 Let 2 Set 3 Get
   Dim ProcName$
   Dim StartLineI&, CountLinesI&, LinesOfProc$


   With ActiveWorkbook.VBProject.VBComponents(ComponentName).CodeModule

      LineI = .CountOfDeclarationLines + 1

      While LineI < .CountOfLines
         PLSG = 0
         While PLSG < 3 And LineI < .CountOfLines ' look for all types

            On Error GoTo LookMore         ' msny may not exist

            ProcName = .ProcOfLine(LineI, PLSG)
            CountLinesI = .ProcCountLines(ProcName, PLSG)
            StartLineI = .ProcStartLine(ProcName, PLSG)

            RowOut = RowOut + 1
            RaSort(RowOut, 1) = ProcName
            RaSort(RowOut, 2) = PLSG
            RaSort(RowOut, 3) = StartLineI
            RaSort(RowOut, 4) = CountLinesI


            ' the procedure can have blanks or comment lines at the top
            ' so start line is not always the Procedure body line
            ' the  ProcBodyLine may be extended for over  about 20 lines
            ' using the  line-continuation char  " _"
            ' so it looks a bit complex to find the actual line

            PBLI = .ProcBodyLine(ProcName, PLSG)
            LineStr = .Lines(PBLI, 1)
            While Right(LineStr, 2) = " _" ' if extended get the other lines
               PBLI = PBLI + 1
               LineStr = Left(LineStr, Len(LineStr) - 2) & " " & .Lines(PBLI, 1)
            Wend

            RaSort(RowOut, 5) = LineStr

            LineI = StartLineI + CountLinesI + 1
            If LineI > .CountOfLines Then PLSG = 14 ' > 3
LookMore:

            On Error GoTo 0
            PLSG = PLSG + 1
         Wend

         LineI = LineI + 1
      Wend
      Set RaSort = RaSort.CurrentRegion
      RaSort.Sort RaSort(1, 1), xlAscending
      '
      'bring each to the top  from Z to A results in  sorted alphabetically
      '
      For RowI = RaSort.Rows.Count To 1 Step -1

         ProcName = RaSort(RowI, 1)
         PLSG = RaSort(RowI, 2)
         '
         ' since they have moved need to refind them before moving to top
         '
         CountLinesI = .ProcCountLines(ProcName, PLSG)
         StartLineI = .ProcStartLine(ProcName, PLSG)

         LinesOfProc = .Lines(StartLineI, CountLinesI)
         .DeleteLines StartLineI, CountLinesI
         .InsertLines .CountOfDeclarationLines + 1, LinesOfProc
      Next RowI
   End With


End Sub

'
' you may find the two below of interest
'
Sub TabsAscending()

   Dim I&, J&

   For I = 1 To Application.Sheets.Count

      For J = 1 To Application.Sheets.Count - 1

         If UCase$(Application.Sheets(J).Name) > UCase$(Application.Sheets(J + 1).Name) then
            Sheets(J).Move after:=Sheets(J + 1)
         End If
      Next J
   Next I
End Sub

Sub ResetCodeNames(WkWb As Workbook)

  'Changes the codename conventional name  gets rid of Sheet3 Sheet7 where they have been given a name


   Dim VarItem  As VBIDE.VBComponent

   For Each VarItem In WkWb.VBProject.VBComponents

   'Type 100 is a worksheet

   If VarItem.Type = 100 And VarItem.Name <> "ThisWorkbook" Then

       VarItem.Name = VarItem.Properties("Name").Value

    End If

 Next

End Sub

' hope it helps others


1

Jose R
28 Май 2019 в 00:51

102 / 20 / 0

Регистрация: 02.07.2012

Сообщений: 149

1

Как получить имя текущей процедуры или функции?

29.01.2014, 04:38. Показов 11613. Ответов 17


Студворк — интернет-сервис помощи студентам

Всем доброго времени суток.
Прошерстив просторы интернета не нашел каким образом можно получить имя текущей процедуры или функции?
Все что есть, это возврат имени текущего модуля — Application.VBE.ActiveCodePane.CodeModule.Name (малавато)
……….В окне watches этот функционал (текущий модуль и процедура) очень хорошо реализован

Нужно для обработчика ошибок, хелп плиз



0



влад74

102 / 20 / 0

Регистрация: 02.07.2012

Сообщений: 149

29.01.2014, 20:57

 [ТС]

3

…….там ответа не нашел

Добавлено через 7 часов 4 минуты
Решение очень близко. Вот пример выводимого сообщения:

Visual Basic
1
2
3
MsgBox "МОДУЛЬ " & Chr(13) & Application.VBE.ActiveCodePane.CodeModule.Name & Chr(13) & Chr(13) & "ПРОЦЕДУРА " & Chr(13) & _
Application.VBE.ActiveVBProject.VBComponents(Application.VBE.ActiveCodePane.CodeModule.Name).CodeModule.ProcOfLine(NumLinProc, 0) & Chr(13) & _
Chr(13) & "ОШИБКА " & Chr(13) & Err.Description & "(" & Err.Number & ")", vbCritical, "ПРОЕКТ " & Application.CurrentProject.Name

Осталось автоматизировано переменной NumLinProc присваивать ЛЮБОЙ номер строки кода (в границах строк процедуры)

КАК ЭТО СДЕЛАТЬ? ХЕЛП ПЛИЗ НАРОД!!!!!



0



5561 / 1367 / 150

Регистрация: 08.02.2009

Сообщений: 4,107

Записей в блоге: 30

29.01.2014, 21:14

4

Так глубоко пока не лез*. Выложу что нашёл по ночному вопросу.

Цитата
Сообщение от влад74
Посмотреть сообщение

имя текущей процедуры или функции

___________________
* да вас разве догонишь!

Миниатюры

Как получить имя текущей процедуры или функции?
 



0



SoftIce

es geht mir gut

11264 / 4746 / 1183

Регистрация: 27.07.2011

Сообщений: 11,437

29.01.2014, 22:52

5

Цитата
Сообщение от влад74
Посмотреть сообщение

Осталось автоматизировано переменной NumLinProc присваивать ЛЮБОЙ номер строки кода (в границах строк процедуры)

пронумеровать строки в каждой процедуре

Visual Basic
1
2
3
4
5
6
7
8
9
10
Sub SS()
    Dim a As Integer
    On Error Resume Next
1:
2:  a = 6 / 0
3:  a = 6 / 6
 
    MsgBox "Line " & Erl & "   """ & Err.Description & """"
 
End Sub

Миниатюры

Как получить имя текущей процедуры или функции?
 



0



влад74

102 / 20 / 0

Регистрация: 02.07.2012

Сообщений: 149

30.01.2014, 01:40

 [ТС]

6

Цитата
Сообщение от SoftIce
Посмотреть сообщение

пронумеровать строки в каждой процедуре

Visual Basic
1
2
3
4
5
6
7
8
9
10
Sub SS()
    Dim a As Integer
    On Error Resume Next
1:
2:  a = 6 / 0
3:  a = 6 / 6
 
    MsgBox "Line " & Erl & "   """ & Err.Description & """"
 
End Sub

Спасибо, не совсем то.
хочется «универсально блоково пропастить обработчики ошибок» без харда.

Добавлено через 2 часа 24 минуты
Мужики давай, давай поднатужимся!!!!!!!!!!!!!!!!
чуть осталось
аааааааааааааааааааааааааааааааа!!!!!!!!!!!!!!!



0



es geht mir gut

11264 / 4746 / 1183

Регистрация: 27.07.2011

Сообщений: 11,437

30.01.2014, 07:36

7

Не по теме:

В 3 часа ночи все спят уже:)

Не совсем понятно чего Вы хотите…

Миниатюры

Как получить имя текущей процедуры или функции?
 



0



SoftIce

es geht mir gut

11264 / 4746 / 1183

Регистрация: 27.07.2011

Сообщений: 11,437

30.01.2014, 08:01

8

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Sub SS()
    Dim n As Integer  ' количество строк в модуле
    Dim i As Integer: i = 1
    Dim s As String
    Dim cl As Integer ' количество строк  в процедуре
    Dim pn As String  ' имя процедуры
    n = Application.VBE.ActiveCodePane.CodeModule.CountOfLines
    Do
         pn = Application.VBE.ActiveCodePane.CodeModule.ProcOfLine(i, 0)
         cl = Application.VBE.ActiveCodePane.CodeModule.ProcCountLines(pn, 0)
         s = s & "Имя процедуры: " & pn & _
             "    Количество строк: " & cl & vbCrLf
                 i = i + cl
    Loop Until i > n
    MsgBox s
End Sub



0



shanemac51

Модератор

Эксперт MS Access

11343 / 4661 / 749

Регистрация: 07.08.2010

Сообщений: 13,512

Записей в блоге: 4

30.01.2014, 08:31

9

метод грубой силы

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Sub a140129_0757()
On Error GoTo err00
Dim j1, j2, j3, jx
j1 = 6
j2 = 0
4: jx = 4: j3 = j1 * "w"
5: jx = 5: Debug.Print 5, j1, j2
6: jx = 6: j3 = j1 / j2
Debug.Print 6, j1, j2, j3
Exit Sub
''
err00:
Debug.Print "метка="; jx, Err.Number, Err.Description
Debug.Print Err.Source
j2 = 2
''Resume Next    ''вернуться на следующую строку
Select Case jx
Case 5
Resume 5       ''вернуться на метку 5
Case 6
Resume 6        ''вернуться на метку 6
Case Else
Debug.Print "прервано="; jx, Err.Number, Err.Description
End Select
 
End Sub



0



102 / 20 / 0

Регистрация: 02.07.2012

Сообщений: 149

30.01.2014, 14:21

 [ТС]

10

Цитата
Сообщение от SoftIce
Посмотреть сообщение

Не по теме:

В 3 часа ночи все спят уже:)

Не совсем понятно чего Вы хотите…

Задача элементарна.
При возникновение ошибки нужно выводить сообщение что ошибка произошла :
1. в mdb такой-то
2. в — Модуле5
3. в — Процедуре(function/sub) SS().
4. Ошибка такая то.

А в модуле5 может содержаться несколько десятков function/sub



0



влад74

102 / 20 / 0

Регистрация: 02.07.2012

Сообщений: 149

03.02.2014, 12:34

 [ТС]

11

Сам спросил сам отвечаю.

Пример универсального обработчика ошибок.

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Sub Указание_номера_строки_ошибки2()
Dim i As Long, j As Long
 
On Error GoTo error_handler
 
i = 10
'MsgBox "Деление на ноль!!!"
Debug.Print i  j
 
exit_statements:
Exit Sub
    
error_handler:
'======================================================================================
Dim startline As Long, startcolumn As Long, endline As Long, endcolumn As Long
VBE.ActiveCodePane.GetSelection startline, startcolumn, endline, endcolumn
 
MsgBox "МОДУЛЬ " & Chr(13) & VBE.ActiveCodePane.CodeModule.Name & Chr(13) & Chr(13) & "ПРОЦЕДУРА " & Chr(13) & _
VBE.ActiveVBProject.VBComponents(VBE.ActiveCodePane.CodeModule.Name).CodeModule.ProcOfLine(startline, 0) & Chr(13) & _
Chr(13) & "ОШИБКА " & Chr(13) & Err.Description & "(" & Err.Number & ")", vbCritical, "ПРОЕКТ " & CurrentProject.Name & _
" (" & ver_Module & ")"
 
Resume exit_statements
'======================================================================================
End Sub



5



AMVAS

0 / 0 / 0

Регистрация: 11.06.2015

Сообщений: 6

26.08.2017, 12:37

12

Вообще, я такую проблему решаю немного по-другому
Вот стандартная конструкция

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Public Function SomeFun() As Boolean
Const cS = "SomeFun: "
On Error GoTo 100
SomeFun = True 'Флаг ошибки
 
.... <инструкции> ...
 
SomeFun = False 'флаг корректного выхода (должен быть установлен при любом корректном выходе)
Exit Function
100:
MsgBox cS & Err.Description, vbCritical
'Resume
End Function

Обработчик, само собой, может отличаться.

P.S. Resume бывает нужен, чтобы перейти на конкретную строку с ошибкой



0



_shark

185 / 183 / 31

Регистрация: 11.10.2016

Сообщений: 599

28.08.2017, 11:22

13

вообще-то, если обработчик ошибок внутри процедуры и переход на него осуществляется через On Error GoTo, то имя процедуры и так понятно:

Visual Basic
1
2
3
4
5
6
7
8
9
10
Sub Test
   On Error GoTo ErrCheck
   '...
 
   Exit Sub
 
ErrCheck:
   MsgBox "Error in Sub: Test"
 
End Sub



0



0 / 0 / 0

Регистрация: 11.06.2015

Сообщений: 6

28.08.2017, 20:28

14

вообще-то, если обработчик ошибок внутри процедуры и переход на него осуществляется через On Error GoTo, то имя процедуры и так понятно:
Visual Basic

Неа. Название процедуры может меняться, поэтому называть константой выгоднее. Можно сразу после заголовка заменить её и не прокручивать в конец. К тому же, название может встречаться более одного раза, если в обработчике стоит обработка нескольких вариантов ошибок.



0



2 / 2 / 0

Регистрация: 17.10.2013

Сообщений: 62

01.12.2017, 23:14

15

Цитата
Сообщение от влад74
Посмотреть сообщение

Сам спросил сам отвечаю.
Пример универсального обработчика ошибок.

влад74, у меня, чтоб пошло, пришлось чуть модернизировать код.
В связи с чем два вопроса:
1) Какой references вы подключали?
2) Означает ли подключеный references, то, что на другом компьютере программа VBA может и не сработать?



0



414 / 262 / 82

Регистрация: 27.10.2012

Сообщений: 860

02.12.2017, 10:49

16

Дебаг перестал переходить на строку ошибки?



0



3 / 3 / 0

Регистрация: 03.08.2015

Сообщений: 156

20.03.2021, 14:24

17

Цитата
Сообщение от влад74
Посмотреть сообщение

Сам спросил сам отвечаю.
Пример универсального обработчика ошибок.

влад74, приветствую! Это же должно работать для Access? Подскажите, плиз, нужно ли подключать какой-то references , чтобы этот код исполнялся правильно?
Ибо у меня он возвращает вместо названий Объекта и Функции, в которых произошла ошибка, названия объекта и функции, на которых у меня в данный момент в редакторе VBA «стоит курсор».



0



anton-sf

123 / 59 / 14

Регистрация: 29.03.2015

Сообщений: 265

20.03.2021, 21:44

18

reference:
Microsoft Visual Basic for Applications Extensibility (5.3 у меня)

Добавлено через 13 минут
А нет, не обязательно, всё работает при дефолтных референсах, но надо перед VBE добавить Application.

Visual Basic
1
2
3
4
5
6
MsgBox "МОДУЛЬ " & Chr(13) & _
Application.VBE.ActiveCodePane.CodeModule.Name & Chr(13) & Chr(13) & "ПРОЦЕДУРА " & Chr(13) & _
Application.VBE.ActiveVBProject.VBComponents( _
Application.VBE.ActiveCodePane.CodeModule.Name).CodeModule.ProcOfLine(startline, 0) & Chr(13) & _
Chr(13) & "ОШИБКА " & Chr(13) & Err.Description & "(" & Err.Number & ")", _
vbCritical, "ПРОЕКТ " & Application.VBE.ActiveVBProject.Name

Добавлено через 6 минут
Это я про Excel



1



Хитрости »

3 Август 2013              10046 просмотров


Как узнать существует ли модуль в книге

Продолжая цикл статей про работу с проектом VBA решил что будет не лишним привести пример того, как проверить существует ли определенный компонент VBA в проекте. Возможно, это пригодится при внесении изменений в коды: чтобы проверить присутствует ли нужный модуль в книге и если нет — то добавить или завершить процедуру без возникновения ошибки.

Для работы с кодами VB-проекта программно необходимо, чтобы было проставлено доверие к объектной модели проекта VBA и изменяемый проект не должен быть защищен. Подробнее читайте в статье: Что необходимо для внесения изменений в проект VBA(макросы) программно
Без этого будет невозможно программное вмешательство в проект VBA.

Но для начала, думаю было бы не лишним привести пример кода, который проверяет наличие в книге самого VBA проекта и его доступность для внесения изменений:
ПРОВЕРКА НАЛИЧИЯ ЗАЩИТЫ VBA ПРОЕКТА

'---------------------------------------------------------------------------------------
' Procedure : IsVBProjLock
'             http://www.excel-vba.ru
' Purpose   : Функция проверки наличия защиты у VBA проекта
'             True  - вернет, если проект защищен
'             False - вернет, если проект доступен для внесения изменений
'---------------------------------------------------------------------------------------
Function IsVBProjLock(wbCheck As Workbook) As Boolean
    Dim oVBProj As Object
    Set oVBProj = wbCheck.VBProject
    If Not oVBProj Is Nothing Then
        IsVBProjLock = (oVBProj.Protection <> 0)
    End If
End Function

Вызов функции IsVBProjLock:

Sub Check_VBProjLock()
    MsgBox "VB проект книги " & IIf(IsVBProjLock(ActiveWorkbook), "закрыт", "доступен"), vbInformation
End Sub

Если защита не установлена — функция вернет False и мы можем быть уверены в том, что в данный проект мы сможем внести изменения.

ПРОВЕРКА НАЛИЧИЯ НУЖНОГО МОДУЛЯ

'---------------------------------------------------------------------------------------
' Procedure : IsModuleExists
'             http://www.excel-vba.ru
' Purpose   : Функция проверки наличия нужного модуля в проекте
' Аргументы функции:
'             sModuleName - имя VBA компонента для проверки
'             objVBProj   - если указан, наличие компонента проверяется в указанном VBA проекте
'                           если не указан - в проекте активной книги
' Результат функции:
'             True        - вернет, если модуль существует
'             False       - вернет, если модуль отсутствует
'---------------------------------------------------------------------------------------
Function IsModuleExists(sModuleName As String, Optional ByVal objVBProj As Object = Nothing) As Boolean
    If objVBProj Is Nothing Then
        Set objVBProj = ActiveWorkbook.VBProject
    End If
    On Error Resume Next
    IsModuleExists = CBool(Len(objVBProj.VBComponents(sModuleName).Name))
End Function

Вызов функции IsModuleExists:

Sub Check_VBComponentExists()
    MsgBox "Модуль 'Module1' " & IIf(IsModuleExists("Module2"), "существует", "отсутствует"), vbInformation
End Sub

Подобным образом можно проверить не только наличие стандартного модуля, но и любого иного компонента: модули листов и книг, модули классов и пользовательские формы. Достаточно передать в функцию имя нужного компонента.


Так же можно проверить не только наличие модуля, но и наличие процедуры или функции по её имени:
ПРОВЕРКА НАЛИЧИЯ ФУНКЦИИ/ПРОЦЕДУРЫ

'---------------------------------------------------------------------------------------
' Procedure : IsFunctionExists
'             http://www.excel-vba.ru
' Purpose   : Функция проверки наличия функции/процедуры в проекте
' Аргументы функции:
'             sProcName   - имя функции/процедуры для проверки
'             objVBProj   - если указан, наличие функции/процедуры проверяется в указанном VBA проекте
'                           если не указан - в проекте активной книги
' Результат функции:
'             Имя модуля, в котором найдена искомая процедура или функция
'---------------------------------------------------------------------------------------
Function IsFunctionExists(sProcName As String, Optional ByVal objVBProj As Object = Nothing)
    If objVBProj Is Nothing Then
        Set objVBProj = ActiveWorkbook.VBProject
    End If
    On Error Resume Next
    Dim lProcLineNum As Long, lProcKind As Long, vMdl
    'цикл по всем модулям проекта(стандартные, классы, формы, листы, книги)
    For Each vMdl In objVBProj.VBComponents
        'ProcStartLine требует в обязательном порядке указания типа процедуры
        'Всего 4 типа:
        '   vbext_pk_Proc  = 0 (Sub or Function procedure)
        '   vbext_pk_Let   = 1 (Property Let procedure)
        '   vbext_pk_Set   = 2 (Property Set procedure)
        '   vbext_pk_Get   = 3 (Property Get procedure)
        For lProcKind = 0 To 3
            'ProcStartLine - встроенная функция
            ' ищет в указанном модуле(vMdl) номер строки с именем заданной процедуры
            lProcLineNum = vMdl.CodeModule.ProcStartLine(sProcName, lProcKind)
            'если lProcLineNum не равно 0 - процедура есть в модуле
            If lProcLineNum > 0 Then
                IsFunctionExists = vMdl.Name
                Exit Function
            End If
        Next
    Next
End Function

Вызов функции IsPocedureExists:

Sub IsPocedureExists()
    Dim sFunctionName As String, sRes As String
    'имя искомой процедуры
    sFunctionName = "MessageFrom_Excel_vba_ru"
    'вызов функции для поиска
    sRes = IsFunctionExists(sFunctionName)
    If sRes <> "" Then
        MsgBox "Функция '" & sFunctionName & "' найдена в модуле: " & sRes, vbInformation
    Else
        MsgBox "Функция '" & sFunctionName & "' отсутствует", vbInformation
    End If
End Sub

Также см.:
Как проверить открыта ли книга?
Как узнать существует ли лист в книге?
Как программно снять пароль с VBA проекта?


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам



Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

I’m trying to create a workbook that is used for creating other .xlsm workbooks, but can’t figure out how to get the modules I need so I can add them.

My code as it stands is below (modified from the answer given here: How to add excel 2010 macro programmatically)

The place I need help is in the ImportModules sub, by the comment 'LIST MODULES HERE

How can I get an array of modules that are in the current workbook?

Private Sub SVAmaker_Click()

    Dim file As String
    file = InputBox("SVA Planner file name", "Name", "Name")

    Application.DefaultSaveFormat = xlOpenXMLWorkbookMacroEnabled
    Workbooks.Add
    ActiveWorkbook.SaveAs filename:=file

    Dim WB As Workbook
    WB = ActiveWorkbook
    Call ImportModules(VBA.CStr(WB))

End Sub

Sub ImportModules(sWorkbookname As String)

    Dim cmpComponents As VBIDE.VBComponents
    Dim wbkTarget As Excel.Workbook

    Set wbkTarget = Workbooks.Open(sWorkbookname)

    If wbkTarget.VBProject.Protection = 1 Then
        Debug.Print wbkTarget.Name & " has a protected project, cannot import module"
    GoTo Cancelline
    End If

    Set cmpComponents = wbkTarget.VBProject.VBComponents

    Dim vModules As Variant
    'LIST MODULES HERE

    Dim i As Integer
    For i = LBound(vModules) To UBound(vModules)
        cmpComponents.Import vModules(i)
    Next i

Cancelline:

    If wbkTarget.FileFormat = xlOpenXMLWorkbook Then
        wbkTarget.SaveAs wbkTarget.Name, xlOpenXMLWorkbookMacroEnabled
        wbkTarget.Close SaveChanges:=False
    Else
        wbkTarget.Close SaveChanges:=True
    End If

    Set wbkTarget = Nothing

End Sub

Community's user avatar

asked Apr 22, 2016 at 10:36

JChristen's user avatar

JChristen asked for a list of those modules

I’d create a collection, based on gizlmo’s proposal:

    Dim vbcomp As VBComponent
    Dim modules as Collection

    set modules = new Collection
    For Each vbcomp In ThisWorkbook.VBProject.VBComponents

        'if normal or class module
        If ((vbcomp.Type = vbext_ct_StdModule) _
             Or _
            (VBComp.Type = vbext_ct_ClassModule)) Then 

           modules.add VBcomp.name

        End If
    Next vbcomp

Later on you can use this collection like this:

    Dim module     as Variant
    for each module in modules
        ' e.g. importing the module 
        import module
    next module

hope it helps

answered Oct 13, 2017 at 10:34

Joe Phi's user avatar

Joe PhiJoe Phi

3401 gold badge4 silver badges14 bronze badges

you can go through the modules like this. Create some collection and then iterate over all objects in VBComponents of VBProject (Value of type for module is 1):

'declare some collection, which will contain modules
For Each vbc In ThisWorkbook.VBProject.VBComponents
   if vbc.Type = 1 then
       'add to temporary collection ... for example for name, use vbc.name
   end if
Next

answered Apr 22, 2016 at 10:47

holmicz's user avatar

holmiczholmicz

5774 silver badges15 bronze badges

1

You can loop through all modules with an easy For Each Loop.
Requires a Reference to «Microsoft Visual Basic for Applications Extensibility»!

Dim vbcomp As VBComponent

For Each vbcomp In ThisWorkbook.VBProject.VBComponents

    'if normal Module
    If vbcomp.Type = vbext_ct_StdModule Then

        'Do Stuff
    End If
Next vbcomp

with .Type you can check the type of the Module(Form, Normal Module, ClassModule etc)

answered Apr 22, 2016 at 10:53

gizlmo's user avatar

gizlmogizlmo

1,8621 gold badge14 silver badges14 bronze badges

This code should help. It will export all modules to the desktop, create a new workbook and import them all into it.

Public Sub ExportImportAllModules()

    Dim srcVBA As Variant
    Dim tgtVBA As Variant
    Dim srcModule As Variant
    Dim wrkBk As Workbook
    Dim sDeskTop As String

    On Error GoTo ERROR_HANDLER

    Application.DisplayAlerts = False

    Set srcVBA = ThisWorkbook.VBProject
    sDeskTop = CreateObject("WScript.Shell").specialfolders("Desktop")
    Set wrkBk = Workbooks.Add(xlWBATWorksheet) 'New workbook with 1 sheet.
    Set tgtVBA = wrkBk.VBProject

    For Each srcModule In srcVBA.vbComponents
        'There may be a better way to check it's a module -
        'I'm making it up as I go along.
        If srcModule.Type = 1 Then 'vbext_ct_StdModule
            srcModule.Export sDeskTop & "" & srcModule.Name
            tgtVBA.vbComponents.Import sDeskTop & "" & srcModule.Name
            Kill sDeskTop & "" & srcModule.Name
        End If
    Next srcModule

    Application.DisplayAlerts = True

    On Error GoTo 0
    Exit Sub

ERROR_HANDLER:
    Select Case Err.Number

        Case Else
            MsgBox "Error " & Err.Number & vbCr & _
                " (" & Err.Description & ") in procedure ExportImportAllModules."
            Err.Clear
            Application.EnableEvents = True
    End Select

End Sub

answered Apr 22, 2016 at 11:01

Darren Bartrup-Cook's user avatar

Why not simply make a copy of the «master» workbook you’d import modules from

Option Explicit

Private Sub SVAmaker_Click()

    Dim fso As New FileSystemObject
    Dim myFile As file        
    Dim fileName As String

    fileName = InputBox("SVA Planner file name", "Name", "Name") & ".xlsm"

    Set myFile = fso.GetFile(ActiveWorkbook.FullName)
    fso.CopyFile myFile, myFile.ParentFolder & "" & fileName

End Sub

from here on you have a new workbook with all modules (and sheets) already there.

should you need to delete some worksheets you juts open it and act with «plain» VBA Excel Model Object code

in order to use FileSytemObject API, you need to reference «Microsoft Scripting Runtime»

answered Apr 22, 2016 at 13:02

user3598756's user avatar

user3598756user3598756

28.8k4 gold badges17 silver badges28 bronze badges

1

Понравилась статья? Поделить с друзьями:
  • Получить имя колонки в excel
  • Пользование программой excel для начинающих
  • Получить имена листов в книге excel
  • Пользование впр в excel
  • Получить имена всех листов excel vba