Welcome to the COE Discussion Forum! 

 

To participate in the discussion forum, you must be logged in to the website.  If you forget your login information, please contact COE Headquarters at coe@coe.org or (800) 263-2255.

If you are new to the COE Discussion Forum and would like to participate, please register.


Register Today
COE 2009 Annual PLM Conference & TechniFair

COE DISCUSSION FORUM
Subject: Recursivity and Excel

You are not authorized to post a reply.   
Author Messages
Mowgli_70

28 Nov 2008 05:34 AM

Gentlemen -

I am addressing you to ask your help concerning the following problem. I am given a CATProduct, consisting of other CATProducts, CATParts or Components. Some of the them may appear many times and on different levels. There are some components which have a user defined Boolean property, called Prop and set to True. 

My ambitious plan is analyze the Product tree, see how many components with the property Prop, set to True I have, and after, pass the results into an Excel file. I managed to do something which works, but just for the first level.

I am stuck when I try to go deeper and to analyze other sublevels using recursivity. Please help me and make the following code work for all levels.

I inspired myself in my work from the following topics and I want to thank Dream_Weaver and Brian Roach for their work:
1)http://www.coe.org/Collaboration/DiscussionForum/ActiveDiscussions/tabid/210/view/topic/forumid/10/postid/109025/Default.aspx

2)http://www.coe.org/Collaboration/DiscussionForum/ActiveDiscussions/tabid/210/view/topic/forumid/10/postid/111200/Default.aspx

Here is my code:

'Assumption: the active CATIA document is a CATProduct, having a multilevel structure: product of 'products, parts or components. Some of the components have a user defined Boolean property, called 'Prop, set to true.

'Language CATScript

Option Explicit

 

'Declaring global variables

'oCurrentTreeNode represents the CATProduct, CATPart or Component which is currently analyzed

Dim oCurrentTreeNode As Product

'If oCurrentNode is a CATProduct or a Component, then n  is the number of its sub-components

Dim n As Integer

'As we walk through the Product tree, Index will count the number of CATProducts, CATParts or 'Components which have not yet been analyzed. Of course, they must have the Prop property set to True. 'In the end, Index is the number which will tell me how many components with the Prop property set to 'True are in the Product being analyzed.  I DECLARED Index AS GLOBAL BECAUSE I DO NOT KNOW 'OTHER METHOD IN CATSCRIPT TO PRESERVE ITS VALUE BETWEEN TWO SUCCESIVE CALLS TO 'THE METHOD GetNextNode. IN OTHER PROGRAMMING LANGUAGES, TO OBTAIN A VARIABLE 'WITH SUCH PROPERTY, YOU DECLARED IT STATIC.

Dim Index As Integer

Index = 0

'I am using a dictionary object in order to keep track of my components

Dim QtyDict As Variant

Set QtyDict = CreateObject("Scripting.Dictionary"

'Based on Index, Counter will help me to fill in the Excel cells with the information about the analyzed 'components.

Dim Counter As Integer

'Declare a dynamic array whose elements will memorize the components of interest

Dim ProductList() As Product

 

 

Sub CATMain()

 

                'Setting up Excel

Dim Excel As Object

                Dim workbooks As workbooks

                Dim workbook As workbook

                Dim Sheets As Object

                Dim Sheet As Object

                Dim worksheet As Excel.worksheet

               

                Err.Clear

                On Error Resume Next

                Set Excel = GetObject(, "EXCEL.Application"

                If Err.Number <> 0 Then

                Err.Clear

                Set Excel = CreateObject("EXCEL.Application"

                End If

                Excel.Visible = True

                Set workbooks = Excel.Application.workbooks

                Set myworkbook = workbooks.Add

 

                Dim EXCELWSH As Worksheet

                Set EXCELWSH = EXCEL.ActiveSheet

                EXCEL.ActiveSheet.Name = "Analyze"

                EXCELWSH.cells(1,1).Value= "Index"

                EXCELWSH.cells(1,2).Value= "Components with True Prop"

                EXCELWSH.cells(1,10).Value= "Quantity"

               

               

                'Call the GetNextNode method

GetNextNode CATIA.ActiveDocument.Product

 

                'When job is done in Catia, pass the results to Excel

For Counter = 1 To Index

                       EXCELWSH.cells(Counter+1,1).Value = Counter   'Index

                       EXCELWSH.cells(Counter+1,2).Value = ProductList(Counter).PartNumber  'Part Number

                       EXCELWSH.cells(Counter+1,10).Value = QtyDict.Item(ProductList(Counter).PartNumber)  'Quantity

                Next

End Sub

 

'RECURSIVE DEFINITION of GetNextNode method

Sub GetNextNode(oCurrentProduct As Product)

                MsgBox "Enter GetNextNode and the number of sub-components is: " & oCurrentProduct.Products.Count

                'Loop through every tree node for the current product. Use Preserve keyword in order to memorize the previous results.

                ReDim Preserve ProductList(oCurrentProduct.Products.Count)  'Total number of products for this sub-component

                For n = 1 To oCurrentProduct.Products.Count

                                Set oCurrentTreeNode = oCurrentProduct.ReferenceProduct.Products.Item(n)

                                                ‘Verify if the Prop is set to True

                                                If (oCurrentTreeNode.ReferenceProduct.UserRefProperties.Item("Prop".Value <> False) Then

                                                                Select Case QtyDict.Exists(oCurrentTreeNode.PartNumber)

                                                                Case True  ‘The component has already been analyzed but it is 'present in another sub-component. In this case, just increase its quantity with one.

                                                                                MsgBox oCurrentTreeNode.PartNumber & " Seen already!"

                                                                                QtyDict.Item(oCurrentTreeNode.PartNumber) = QtyDict.Item(oCurrentTreeNode.PartNumber) + 1

                                                                Case False 'The component has not been  analyzed yet.

                                                                                Index = Index + 1

                                                                                MsgBox oCurrentTreeNode.PartNumber & " Has not been seen yet!"

                                                                                QtyDict.Add oCurrentTreeNode.PartNumber, 1

                                                                                MsgBox "Index = " & Index

                                                                                Set ProductList(Index) = oCurrentTreeNode

                                                                End Select

                                                End If

‘If sub-nodes exist below the current tree node, call GetNextNode recursively. If I comment the following 'four lines, the macro works, but, as expected,  just for the first Product level.

 If oCurrentTreeNode.Products.Count > 0 Then

                MsgBox "It works recursively!"

                GetNextNode oCurrentTreeNode

End If

    

Next

MsgBox "Get out from GetNextNode!"         

End Sub

 

KBOLEN

19 Dec 2008 12:48 PM
I was able to do this in CATVBA. Personally, I don't like to program in CATScript (it's much harder to debug :o).

Enjoy,
Ken


'Assumption: the active CATIA document is a CATProduct, having a multilevel
' structure: product of 'products, parts or components. Some of the components
' have a user defined Boolean property, called 'Prop', set to true.

'Language CATVBA

Option Explicit

'I am using a dictionary object in order to keep track of my components
Dim QtyDict As Variant

'Declare a dynamic array whose elements will memorize the components of interest
Dim ProductList() As Product

Sub CATMain()

Dim iCounter As Integer

Set QtyDict = CreateObject("Scripting.Dictionary")
ReDim ProductList(0)

'Setting up Excel
Dim Excel As Object
Dim workbooks As workbooks
Dim xlWkbk As workbook
Dim Sheets As Object
Dim Sheet As Object
Dim worksheet As Excel.worksheet

Err.Clear
On Error Resume Next
Set Excel = GetObject(, "EXCEL.Application")
If (Err.Number) <> 0 Then
Err.Clear
Set Excel = CreateObject("EXCEL.Application")
End If
On Error GoTo 0
Excel.Visible = True
Set workbooks = Excel.Application.workbooks
Set xlWkbk = workbooks.Add

Dim xlWksht As worksheet
Set xlWksht = Excel.ActiveSheet
Excel.ActiveSheet.Name = "Analyze"
xlWksht.cells(1, 1).Value = "Index"
xlWksht.cells(1, 2).Value = "Components with True Prop"
xlWksht.cells(1, 10).Value = "Quantity"

'Call the GetNextNode method
Call GetNextNode(CATIA.ActiveDocument.Product)

'When job is done in Catia, pass the results to Excel
For iCounter = 1 To UBound(ProductList())
xlWksht.cells(iCounter + 1, 1).Value = iCounter 'Index
xlWksht.cells(iCounter + 1, 2).Value = ProductList(iCounter).PartNumber 'Part Number
xlWksht.cells(iCounter + 1, 10).Value = QtyDict.Item(ProductList(iCounter).PartNumber) 'Quantity
Next iCounter

End Sub

'RECURSIVE DEFINITION of GetNextNode method
Sub GetNextNode(oCurrentProduct As Product)

'oCurrentTreeNode represents the CATProduct, CATPart or Component which is currently analyzed
Dim oCurrentTreeNode As Product
Dim nCnt As Long
Dim bStat As Boolean

MsgBox "Enter GetNextNode and the number of sub-components is: " & oCurrentProduct.Products.Count

'Loop through every tree node for the current product. Use Preserve keyword in order to memorize the previous results.
For nCnt = 1 To oCurrentProduct.Products.Count

Set oCurrentTreeNode = oCurrentProduct.ReferenceProduct.Products.Item(nCnt)
MsgBox "Current node: " & oCurrentTreeNode.PartNumber

'Verify 'Prop' exists
bStat = False
On Error Resume Next
bStat = oCurrentTreeNode.ReferenceProduct.UserRefProperties.Item("Prop").Value
If (Err.Number) <> 0 Then
MsgBox oCurrentTreeNode.PartNumber & Chr(13) & Chr(13) & "Missing 'Prop' value!"
Err.Clear
End If
On Error GoTo 0

'Verify if the Prop is set to True
If (bStat) Then
Select Case QtyDict.Exists(oCurrentTreeNode.PartNumber)
Case True 'The component has already been analyzed but it is present in another sub-component.
'In this case, just increase its quantity with one.
MsgBox oCurrentTreeNode.PartNumber & Chr(13) & Chr(13) & "Seen already!"

QtyDict.Item(oCurrentTreeNode.PartNumber) = QtyDict.Item(oCurrentTreeNode.PartNumber) + 1
Case False 'The component has not been analyzed yet.
ReDim Preserve ProductList(UBound(ProductList()) + 1)
Set ProductList(UBound(ProductList())) = oCurrentTreeNode

MsgBox oCurrentTreeNode.PartNumber & Chr(13) & Chr(13) & "Has not been seen yet!"
QtyDict.Add oCurrentTreeNode.PartNumber, 1
MsgBox "Index = " & UBound(ProductList())
End Select
End If

'If sub-nodes exist below the current tree node, call GetNextNode recursively. If I comment the following 'four lines, the macro works, but, as expected, just for the first Product level.
If (oCurrentTreeNode.Products.Count > 0) Then
MsgBox "It works recursively!"
Call GetNextNode(oCurrentTreeNode)
End If

Next nCnt

MsgBox "Get out from GetNextNode!"
End Sub
Mowgli_70

21 Dec 2008 08:19 AM
Hello Ken!

Thank you very much for your help. Frankly speaking, I was skeptical about receiving an answer to my problem.
I think that once the bugs were taken out, the above program can be used and modified to serve for a multitude of purposes and creating a bill of material with the result in Excel is just a few steps away.
I agree with you on catvba, it gives you more flexibility than CATScript does.

Good luck!
Mowgli_70
You are not authorized to post a reply.
Forums > COE Forums > CATIA V5 Programming > Recursivity and Excel



ActiveForums 3.6

    

401 North Michigan Avenue, Chicago, IL 60611-4267 | (312) 321-5153 | (800) COE-CALL (U.S.)