Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 553
Default vbext_pk_Proc and vbext_pk_Get in Class Modules

If I have a class module and within that module I have the following line of
code:

Public Property Get Name() As String
Name = pName
End Property

In a regular module I can use the following code to extract the name of the
"sub" and pass it to the variable "ProcName"

For Each VBComp In ThisWorkbook.VBProject.VBComponents
ModuleName = VBComp.Name
NumLines = 0
With VBComp.CodeModule
myStartLine = .CountOfDeclarationLines + 1
While myStartLine < .CountOfLines
SubFuncCount = SubFuncCount + 1
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)
myStartLine = myStartLine + NumLines
Wend
End With
Next

?ProcName
Name

Note the use of "vbext_pk_Proc" in:
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)

However the code fails on:
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

I know from Chip Pearson's site that:
vbext_pk_Get (3). A Property Get procedure.
vbext_pk_Let (1). A Property Let procedure.
vbext_pk_Set (2). A Property Set procedure.
vbext_pk_Proc (0). A Sub or Function procedure.

Why does vbext_pk_Proc work in the first instance but not the second?

Thanks

EM
  #2   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 7,247
Default vbext_pk_Proc and vbext_pk_Get in Class Modules

You report that the problem is in the call to ProcCountLines, but the
real problem is in the call to ProcOfLine. The reason is that in
ProcOfLine, the proc type variable must be a ByRef variable declared
as

Dim ProcKind As VBIDE.vbext_ProcKind

Then, you pass ProcKind to ProcOfLine. ProcOfLine then POPULATES the
ProcKind variable with the vbext_ProcKind value that indicates what
kind of proc was found at the specified line. In other words, ProcKind
is an OUTPUT variable of ProcOfLine. If you place a constant value
such as vbext_pk_Proc as the parameter to ProcOfLine, that is a ByRef
pass and there is no location for ProcOfLine to place the value of the
procedure kind of the procedure at ProcOfLine.

It works in the second case because in ProcCountLines, proc kind is an
INPUT parameter to ProcCountLines and is used to distinguish between a
Property Set, Property Get, or Property Let procedure, all of which
can have the same name.

Your code should be something like

Dim ProcKind As VBIDE.vbext_ProcKind
' ......
ProcName = .ProcOfLine(myStartLine, ProcKind) ' ProcKind is OUTPUT
NumLines = .ProcCountLines(ProcName, ProcKind) ' ProcKind is INPUT

It is acceptable to use

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

if you are SURE that ProcName is a Sub or Function procedure. However,
this is not the way to do it if you might have a Property procedure.

If ProcName identifies a Property procedure,

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

will fail because the proc kind of a Property is not equal to
vbext_pk_Proc.

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)

On Thu, 24 Sep 2009 11:16:24 -0700, ExcelMonkey
wrote:

If I have a class module and within that module I have the following line of
code:

Public Property Get Name() As String
Name = pName
End Property

In a regular module I can use the following code to extract the name of the
"sub" and pass it to the variable "ProcName"

For Each VBComp In ThisWorkbook.VBProject.VBComponents
ModuleName = VBComp.Name
NumLines = 0
With VBComp.CodeModule
myStartLine = .CountOfDeclarationLines + 1
While myStartLine < .CountOfLines
SubFuncCount = SubFuncCount + 1
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)
myStartLine = myStartLine + NumLines
Wend
End With
Next

?ProcName
Name

Note the use of "vbext_pk_Proc" in:
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)

However the code fails on:
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

I know from Chip Pearson's site that:
vbext_pk_Get (3). A Property Get procedure.
vbext_pk_Let (1). A Property Let procedure.
vbext_pk_Set (2). A Property Set procedure.
vbext_pk_Proc (0). A Sub or Function procedure.

Why does vbext_pk_Proc work in the first instance but not the second?

Thanks

EM

  #3   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 553
Default vbext_pk_Proc and vbext_pk_Get in Class Modules

Interesting. I saw an example like this on your site and could not figure
out for the life of me where ProcKind was getting its value from as it did
not look as though it was being assigned anywhere. Good to know.

Thanks

EM




"Chip Pearson" wrote:

You report that the problem is in the call to ProcCountLines, but the
real problem is in the call to ProcOfLine. The reason is that in
ProcOfLine, the proc type variable must be a ByRef variable declared
as

Dim ProcKind As VBIDE.vbext_ProcKind

Then, you pass ProcKind to ProcOfLine. ProcOfLine then POPULATES the
ProcKind variable with the vbext_ProcKind value that indicates what
kind of proc was found at the specified line. In other words, ProcKind
is an OUTPUT variable of ProcOfLine. If you place a constant value
such as vbext_pk_Proc as the parameter to ProcOfLine, that is a ByRef
pass and there is no location for ProcOfLine to place the value of the
procedure kind of the procedure at ProcOfLine.

It works in the second case because in ProcCountLines, proc kind is an
INPUT parameter to ProcCountLines and is used to distinguish between a
Property Set, Property Get, or Property Let procedure, all of which
can have the same name.

Your code should be something like

Dim ProcKind As VBIDE.vbext_ProcKind
' ......
ProcName = .ProcOfLine(myStartLine, ProcKind) ' ProcKind is OUTPUT
NumLines = .ProcCountLines(ProcName, ProcKind) ' ProcKind is INPUT

It is acceptable to use

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

if you are SURE that ProcName is a Sub or Function procedure. However,
this is not the way to do it if you might have a Property procedure.

If ProcName identifies a Property procedure,

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

will fail because the proc kind of a Property is not equal to
vbext_pk_Proc.

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)

On Thu, 24 Sep 2009 11:16:24 -0700, ExcelMonkey
wrote:

If I have a class module and within that module I have the following line of
code:

Public Property Get Name() As String
Name = pName
End Property

In a regular module I can use the following code to extract the name of the
"sub" and pass it to the variable "ProcName"

For Each VBComp In ThisWorkbook.VBProject.VBComponents
ModuleName = VBComp.Name
NumLines = 0
With VBComp.CodeModule
myStartLine = .CountOfDeclarationLines + 1
While myStartLine < .CountOfLines
SubFuncCount = SubFuncCount + 1
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)
myStartLine = myStartLine + NumLines
Wend
End With
Next

?ProcName
Name

Note the use of "vbext_pk_Proc" in:
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)

However the code fails on:
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

I know from Chip Pearson's site that:
vbext_pk_Get (3). A Property Get procedure.
vbext_pk_Let (1). A Property Let procedure.
vbext_pk_Set (2). A Property Set procedure.
vbext_pk_Proc (0). A Sub or Function procedure.

Why does vbext_pk_Proc work in the first instance but not the second?

Thanks

EM


  #4   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 553
Default vbext_pk_Proc and vbext_pk_Get in Class Modules

Chip one last question that is mildly related. When you use the code:

ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)

This returns the name of the process. Is their a way to include the
preceding word before the name (i.e. Sub, Function, Get, Let, Set) using the
existing library?

Thanks

EM

"Chip Pearson" wrote:

You report that the problem is in the call to ProcCountLines, but the
real problem is in the call to ProcOfLine. The reason is that in
ProcOfLine, the proc type variable must be a ByRef variable declared
as

Dim ProcKind As VBIDE.vbext_ProcKind

Then, you pass ProcKind to ProcOfLine. ProcOfLine then POPULATES the
ProcKind variable with the vbext_ProcKind value that indicates what
kind of proc was found at the specified line. In other words, ProcKind
is an OUTPUT variable of ProcOfLine. If you place a constant value
such as vbext_pk_Proc as the parameter to ProcOfLine, that is a ByRef
pass and there is no location for ProcOfLine to place the value of the
procedure kind of the procedure at ProcOfLine.

It works in the second case because in ProcCountLines, proc kind is an
INPUT parameter to ProcCountLines and is used to distinguish between a
Property Set, Property Get, or Property Let procedure, all of which
can have the same name.

Your code should be something like

Dim ProcKind As VBIDE.vbext_ProcKind
' ......
ProcName = .ProcOfLine(myStartLine, ProcKind) ' ProcKind is OUTPUT
NumLines = .ProcCountLines(ProcName, ProcKind) ' ProcKind is INPUT

It is acceptable to use

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

if you are SURE that ProcName is a Sub or Function procedure. However,
this is not the way to do it if you might have a Property procedure.

If ProcName identifies a Property procedure,

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

will fail because the proc kind of a Property is not equal to
vbext_pk_Proc.

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)

On Thu, 24 Sep 2009 11:16:24 -0700, ExcelMonkey
wrote:

If I have a class module and within that module I have the following line of
code:

Public Property Get Name() As String
Name = pName
End Property

In a regular module I can use the following code to extract the name of the
"sub" and pass it to the variable "ProcName"

For Each VBComp In ThisWorkbook.VBProject.VBComponents
ModuleName = VBComp.Name
NumLines = 0
With VBComp.CodeModule
myStartLine = .CountOfDeclarationLines + 1
While myStartLine < .CountOfLines
SubFuncCount = SubFuncCount + 1
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)
myStartLine = myStartLine + NumLines
Wend
End With
Next

?ProcName
Name

Note the use of "vbext_pk_Proc" in:
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)

However the code fails on:
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

I know from Chip Pearson's site that:
vbext_pk_Get (3). A Property Get procedure.
vbext_pk_Let (1). A Property Let procedure.
vbext_pk_Set (2). A Property Set procedure.
vbext_pk_Proc (0). A Sub or Function procedure.

Why does vbext_pk_Proc work in the first instance but not the second?

Thanks

EM


  #5   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 7,247
Default vbext_pk_Proc and vbext_pk_Get in Class Modules

I found some code in my standard library that you might find useful:


' Requires a reference to:
' Name: VBIDE
' Description: Microsoft Visual Basic for Applications
Extensibility 5.3
' GUID: {0002E157-0000-0000-C000-000000000046}
' Major: 5 Minor: 3
' Typical Location: C:\Program Files\Common Files\Microsoft
Shared\VBA\VBA6\VBE6EXT.OLB

Public Type TDeclarationInfo
Success As Boolean
ProcName As String
ProcType As String
ProcKind As VBIDE.vbext_ProcKind
Scope As String
ProcBodyLine As Long
ProcStartLine As Long
ProcEndLine As Long
ProcCountLines As Long
Declaration As String
NormalizedDeclaration As String
End Type

Function ProcInfoFromLine(CodeMod As VBIDE.CodeModule, LineNumber As
Long) As TDeclarationInfo

Dim SS As Variant
Dim N As Long
Dim DI As TDeclarationInfo
Dim S As String
Dim T As String


With CodeMod
If LineNumber <= .CountOfDeclarationLines Then
DI.Success = False
ProcInfoFromLine = DI
Exit Function
End If
DI.ProcName = .ProcOfLine(LineNumber, DI.ProcKind)
DI.ProcStartLine = .ProcStartLine(DI.ProcName, DI.ProcKind)
DI.ProcBodyLine = .ProcBodyLine(DI.ProcName, DI.ProcKind)
DI.ProcCountLines = .ProcCountLines(DI.ProcName, DI.ProcKind)
DI.ProcEndLine = DI.ProcStartLine + DI.ProcCountLines - 1
N = 0
S = .Lines(DI.ProcBodyLine + N, 1)
Do Until StrComp(Right(S, 2), " _", vbBinaryCompare) < 0
N = N + 1
T = .Lines(DI.ProcBodyLine + N, 1)
S = S & vbNewLine & T
Loop
DI.Declaration = S
T = S
T = Replace(T, vbNewLine, Space(1))
T = Replace(T, " _ ", Space(1))
N = InStr(1, T, Space(2))
Do Until N = 0
T = Replace(T, Space(2), Space(1))
N = InStr(1, T, Space(2))
Loop
DI.NormalizedDeclaration = T
SS = Split(DI.NormalizedDeclaration, Space(1))
Select Case DI.ProcKind
Case VBIDE.vbext_pk_Get
DI.ProcType = "Property Get"
Select Case LCase(SS(0))
Case "public", "private", "friend"
DI.Scope = SS(0)
Case Else
DI.Scope = "default"
End Select
Case VBIDE.vbext_pk_Let
DI.ProcType = "Property Let"
Select Case LCase(SS(0))
Case "public", "private", "friend"
DI.Scope = SS(0)
Case Else
DI.Scope = "default"
End Select
Case VBIDE.vbext_pk_Set
DI.ProcType = "Property Set"
Select Case LCase(SS(0))
Case "public", "private", "friend"
DI.Scope = SS(0)
Case Else
DI.Scope = "default"
End Select
Case VBIDE.vbext_pk_Proc

Select Case LCase(SS(0))
Case "public", "private", "friend"
DI.Scope = SS(0)
DI.ProcType = SS(1)
Case Else
DI.Scope = "default"
DI.ProcType = SS(0)
End Select
End Select
DI.Success = True
End With
ProcInfoFromLine = DI
End Function

The ProcInfoFromLine function takes as input a reference to a
VBIDE.CodeModule and a LineNumber and loads and returns a
TDeclarationInfo structure with many properties of the procedure that
contains LineNumber in CodeMod.

The elements of the TDeclarationInfo structure are for the most part
self-explanatory. ProcType is a string contain the type of procedure,
eg., "Sub", "Property Get", etc. ProcKind is the vbext_ProcKind value
of the procedure. Scope is "public", "private","friend", or "default
(no scope specified)". Declaration is the complete declaration of the
procedure, including line continuation characters and line breaks, and
padding space if the declaration spans more than one line in the code.
NormalizeDeclaration is the declaration with all lines breaks, and
line continuation characters stripped out, and then it is single
spaced (multiple spaces convert to single spaces).

Once you have the code above, you would call it with code like


Sub AAATest()
Dim VBP As VBIDE.VBProject
Dim CodeMod As VBIDE.CodeModule
Dim LineNum As Long
Dim ModuleName As String
Dim DI As TDeclarationInfo

'<<< CHANGE THE NEXT TWO LINES AS DESIRED
ModuleName = "Module1"
LineNum = 20
'<<< END CHANGE
Set VBP = Application.VBE.ActiveVBProject
Set CodeMod = VBP.VBComponents(ModuleName).CodeModule
DI = ProcInfoFromLine(CodeMod, LineNum)
If DI.Success = False Then
Debug.Print "error"
Else
With DI
Debug.Print "---------------------"
Debug.Print "PROC:", .ProcName
Debug.Print "---------------------"
Debug.Print "Scope", .Scope
Debug.Print "ProcType", .ProcType
Debug.Print "ProcKind", .ProcKind
Debug.Print "ProcStart", .ProcStartLine
Debug.Print "ProcBodyLine", .ProcBodyLine
Debug.Print "ProcCountLines", .ProcCountLines
Debug.Print "ProcEndLine", .ProcEndLine
Debug.Print "NormalizedDeclaration", .NormalizedDeclaration
Debug.Print "Declaration", .Declaration
Debug.Print "---------------------"
End With
End If
End Sub


All this code comes for a project I've been working on to build a
complete VBA code management and control system. The management
project is written in VBNET 2008, NET 3.5.1 and, if all goes well, can
be used in any Office application and using an SQL Server Express
database.

I hope you find the code helpful, or at least amusing.

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)




On Thu, 24 Sep 2009 12:14:13 -0700, ExcelMonkey
wrote:

Chip one last question that is mildly related. When you use the code:

ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)

This returns the name of the process. Is their a way to include the
preceding word before the name (i.e. Sub, Function, Get, Let, Set) using the
existing library?

Thanks

EM

"Chip Pearson" wrote:

You report that the problem is in the call to ProcCountLines, but the
real problem is in the call to ProcOfLine. The reason is that in
ProcOfLine, the proc type variable must be a ByRef variable declared
as

Dim ProcKind As VBIDE.vbext_ProcKind

Then, you pass ProcKind to ProcOfLine. ProcOfLine then POPULATES the
ProcKind variable with the vbext_ProcKind value that indicates what
kind of proc was found at the specified line. In other words, ProcKind
is an OUTPUT variable of ProcOfLine. If you place a constant value
such as vbext_pk_Proc as the parameter to ProcOfLine, that is a ByRef
pass and there is no location for ProcOfLine to place the value of the
procedure kind of the procedure at ProcOfLine.

It works in the second case because in ProcCountLines, proc kind is an
INPUT parameter to ProcCountLines and is used to distinguish between a
Property Set, Property Get, or Property Let procedure, all of which
can have the same name.

Your code should be something like

Dim ProcKind As VBIDE.vbext_ProcKind
' ......
ProcName = .ProcOfLine(myStartLine, ProcKind) ' ProcKind is OUTPUT
NumLines = .ProcCountLines(ProcName, ProcKind) ' ProcKind is INPUT

It is acceptable to use

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

if you are SURE that ProcName is a Sub or Function procedure. However,
this is not the way to do it if you might have a Property procedure.

If ProcName identifies a Property procedure,

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

will fail because the proc kind of a Property is not equal to
vbext_pk_Proc.

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)

On Thu, 24 Sep 2009 11:16:24 -0700, ExcelMonkey
wrote:

If I have a class module and within that module I have the following line of
code:

Public Property Get Name() As String
Name = pName
End Property

In a regular module I can use the following code to extract the name of the
"sub" and pass it to the variable "ProcName"

For Each VBComp In ThisWorkbook.VBProject.VBComponents
ModuleName = VBComp.Name
NumLines = 0
With VBComp.CodeModule
myStartLine = .CountOfDeclarationLines + 1
While myStartLine < .CountOfLines
SubFuncCount = SubFuncCount + 1
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)
myStartLine = myStartLine + NumLines
Wend
End With
Next

?ProcName
Name

Note the use of "vbext_pk_Proc" in:
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)

However the code fails on:
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

I know from Chip Pearson's site that:
vbext_pk_Get (3). A Property Get procedure.
vbext_pk_Let (1). A Property Let procedure.
vbext_pk_Set (2). A Property Set procedure.
vbext_pk_Proc (0). A Sub or Function procedure.

Why does vbext_pk_Proc work in the first instance but not the second?

Thanks

EM




  #6   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 553
Default vbext_pk_Proc and vbext_pk_Get in Class Modules

Yes very helpful. It sure pulls you deep into the minutae. So much to
consder......

Thanks again.

EM

"Chip Pearson" wrote:

I found some code in my standard library that you might find useful:


' Requires a reference to:
' Name: VBIDE
' Description: Microsoft Visual Basic for Applications
Extensibility 5.3
' GUID: {0002E157-0000-0000-C000-000000000046}
' Major: 5 Minor: 3
' Typical Location: C:\Program Files\Common Files\Microsoft
Shared\VBA\VBA6\VBE6EXT.OLB

Public Type TDeclarationInfo
Success As Boolean
ProcName As String
ProcType As String
ProcKind As VBIDE.vbext_ProcKind
Scope As String
ProcBodyLine As Long
ProcStartLine As Long
ProcEndLine As Long
ProcCountLines As Long
Declaration As String
NormalizedDeclaration As String
End Type

Function ProcInfoFromLine(CodeMod As VBIDE.CodeModule, LineNumber As
Long) As TDeclarationInfo

Dim SS As Variant
Dim N As Long
Dim DI As TDeclarationInfo
Dim S As String
Dim T As String


With CodeMod
If LineNumber <= .CountOfDeclarationLines Then
DI.Success = False
ProcInfoFromLine = DI
Exit Function
End If
DI.ProcName = .ProcOfLine(LineNumber, DI.ProcKind)
DI.ProcStartLine = .ProcStartLine(DI.ProcName, DI.ProcKind)
DI.ProcBodyLine = .ProcBodyLine(DI.ProcName, DI.ProcKind)
DI.ProcCountLines = .ProcCountLines(DI.ProcName, DI.ProcKind)
DI.ProcEndLine = DI.ProcStartLine + DI.ProcCountLines - 1
N = 0
S = .Lines(DI.ProcBodyLine + N, 1)
Do Until StrComp(Right(S, 2), " _", vbBinaryCompare) < 0
N = N + 1
T = .Lines(DI.ProcBodyLine + N, 1)
S = S & vbNewLine & T
Loop
DI.Declaration = S
T = S
T = Replace(T, vbNewLine, Space(1))
T = Replace(T, " _ ", Space(1))
N = InStr(1, T, Space(2))
Do Until N = 0
T = Replace(T, Space(2), Space(1))
N = InStr(1, T, Space(2))
Loop
DI.NormalizedDeclaration = T
SS = Split(DI.NormalizedDeclaration, Space(1))
Select Case DI.ProcKind
Case VBIDE.vbext_pk_Get
DI.ProcType = "Property Get"
Select Case LCase(SS(0))
Case "public", "private", "friend"
DI.Scope = SS(0)
Case Else
DI.Scope = "default"
End Select
Case VBIDE.vbext_pk_Let
DI.ProcType = "Property Let"
Select Case LCase(SS(0))
Case "public", "private", "friend"
DI.Scope = SS(0)
Case Else
DI.Scope = "default"
End Select
Case VBIDE.vbext_pk_Set
DI.ProcType = "Property Set"
Select Case LCase(SS(0))
Case "public", "private", "friend"
DI.Scope = SS(0)
Case Else
DI.Scope = "default"
End Select
Case VBIDE.vbext_pk_Proc

Select Case LCase(SS(0))
Case "public", "private", "friend"
DI.Scope = SS(0)
DI.ProcType = SS(1)
Case Else
DI.Scope = "default"
DI.ProcType = SS(0)
End Select
End Select
DI.Success = True
End With
ProcInfoFromLine = DI
End Function

The ProcInfoFromLine function takes as input a reference to a
VBIDE.CodeModule and a LineNumber and loads and returns a
TDeclarationInfo structure with many properties of the procedure that
contains LineNumber in CodeMod.

The elements of the TDeclarationInfo structure are for the most part
self-explanatory. ProcType is a string contain the type of procedure,
eg., "Sub", "Property Get", etc. ProcKind is the vbext_ProcKind value
of the procedure. Scope is "public", "private","friend", or "default
(no scope specified)". Declaration is the complete declaration of the
procedure, including line continuation characters and line breaks, and
padding space if the declaration spans more than one line in the code.
NormalizeDeclaration is the declaration with all lines breaks, and
line continuation characters stripped out, and then it is single
spaced (multiple spaces convert to single spaces).

Once you have the code above, you would call it with code like


Sub AAATest()
Dim VBP As VBIDE.VBProject
Dim CodeMod As VBIDE.CodeModule
Dim LineNum As Long
Dim ModuleName As String
Dim DI As TDeclarationInfo

'<<< CHANGE THE NEXT TWO LINES AS DESIRED
ModuleName = "Module1"
LineNum = 20
'<<< END CHANGE
Set VBP = Application.VBE.ActiveVBProject
Set CodeMod = VBP.VBComponents(ModuleName).CodeModule
DI = ProcInfoFromLine(CodeMod, LineNum)
If DI.Success = False Then
Debug.Print "error"
Else
With DI
Debug.Print "---------------------"
Debug.Print "PROC:", .ProcName
Debug.Print "---------------------"
Debug.Print "Scope", .Scope
Debug.Print "ProcType", .ProcType
Debug.Print "ProcKind", .ProcKind
Debug.Print "ProcStart", .ProcStartLine
Debug.Print "ProcBodyLine", .ProcBodyLine
Debug.Print "ProcCountLines", .ProcCountLines
Debug.Print "ProcEndLine", .ProcEndLine
Debug.Print "NormalizedDeclaration", .NormalizedDeclaration
Debug.Print "Declaration", .Declaration
Debug.Print "---------------------"
End With
End If
End Sub


All this code comes for a project I've been working on to build a
complete VBA code management and control system. The management
project is written in VBNET 2008, NET 3.5.1 and, if all goes well, can
be used in any Office application and using an SQL Server Express
database.

I hope you find the code helpful, or at least amusing.

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)




On Thu, 24 Sep 2009 12:14:13 -0700, ExcelMonkey
wrote:

Chip one last question that is mildly related. When you use the code:

ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)

This returns the name of the process. Is their a way to include the
preceding word before the name (i.e. Sub, Function, Get, Let, Set) using the
existing library?

Thanks

EM

"Chip Pearson" wrote:

You report that the problem is in the call to ProcCountLines, but the
real problem is in the call to ProcOfLine. The reason is that in
ProcOfLine, the proc type variable must be a ByRef variable declared
as

Dim ProcKind As VBIDE.vbext_ProcKind

Then, you pass ProcKind to ProcOfLine. ProcOfLine then POPULATES the
ProcKind variable with the vbext_ProcKind value that indicates what
kind of proc was found at the specified line. In other words, ProcKind
is an OUTPUT variable of ProcOfLine. If you place a constant value
such as vbext_pk_Proc as the parameter to ProcOfLine, that is a ByRef
pass and there is no location for ProcOfLine to place the value of the
procedure kind of the procedure at ProcOfLine.

It works in the second case because in ProcCountLines, proc kind is an
INPUT parameter to ProcCountLines and is used to distinguish between a
Property Set, Property Get, or Property Let procedure, all of which
can have the same name.

Your code should be something like

Dim ProcKind As VBIDE.vbext_ProcKind
' ......
ProcName = .ProcOfLine(myStartLine, ProcKind) ' ProcKind is OUTPUT
NumLines = .ProcCountLines(ProcName, ProcKind) ' ProcKind is INPUT

It is acceptable to use

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

if you are SURE that ProcName is a Sub or Function procedure. However,
this is not the way to do it if you might have a Property procedure.

If ProcName identifies a Property procedure,

NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

will fail because the proc kind of a Property is not equal to
vbext_pk_Proc.

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)

On Thu, 24 Sep 2009 11:16:24 -0700, ExcelMonkey
wrote:

If I have a class module and within that module I have the following line of
code:

Public Property Get Name() As String
Name = pName
End Property

In a regular module I can use the following code to extract the name of the
"sub" and pass it to the variable "ProcName"

For Each VBComp In ThisWorkbook.VBProject.VBComponents
ModuleName = VBComp.Name
NumLines = 0
With VBComp.CodeModule
myStartLine = .CountOfDeclarationLines + 1
While myStartLine < .CountOfLines
SubFuncCount = SubFuncCount + 1
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)
myStartLine = myStartLine + NumLines
Wend
End With
Next

?ProcName
Name

Note the use of "vbext_pk_Proc" in:
ProcName = .ProcOfLine(myStartLine, vbext_pk_Proc)

However the code fails on:
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)

I know from Chip Pearson's site that:
vbext_pk_Get (3). A Property Get procedure.
vbext_pk_Let (1). A Property Let procedure.
vbext_pk_Set (2). A Property Set procedure.
vbext_pk_Proc (0). A Sub or Function procedure.

Why does vbext_pk_Proc work in the first instance but not the second?

Thanks

EM


Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules

Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Class modules: parametrize class object fields Jean-Pierre Bidon Excel Programming 11 August 31st 06 02:49 PM
Basic question - modules and class modules - what's the difference? Mark Stephens[_3_] Excel Programming 9 May 8th 05 11:48 AM
Class Modules vs Modules Jeff Marshall Excel Programming 2 September 28th 03 07:57 PM
Class Modules Siphuncle Excel Programming 2 August 12th 03 06:37 PM


All times are GMT +1. The time now is 01:06 AM.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright ©2004-2024 ExcelBanter.
The comments are property of their posters.
 

About Us

"It's about Microsoft Excel"