0

I have an .stp file, exported with a different CAD-software, which I can open with CATIA. CATIA will then list the product/part tree as if it were a native CATIA .CATProduct.

My goal is to automate opening such an .stp file with CATIA and saving all contained parts/products with a name that is extracted from one of the UserRefProperties in each of these parts/products. Therefore I want to create a macro with VBA which when completed will run in batch mode.

My first problem arises when I try to save the parts/products in this .stp file, Catia's save function handles my file as desired and will save each part/product as a separate file. However, using VBA I can't seem to be able to save any of these parts/products since the .ExportData and .SaveAs methods only seem to work on .PartDocument or .ProductDocument objects instead of the objects which I've been trying to save: .Product objects.

Example of what I'm trying to do:

Sub catmain()

Dim oProdDoc As ProductDocument
Set oProdDoc = CATIA.ActiveDocument

Dim oRootProd As Product
Set oRootProd = oProdDoc.Product

Dim oInstances As Products
Set oInstances = oRootProd.Products

For k = 1 To oInstances.Count

Dim oInst As Product
Set oInst = oInstances.Item(k)

oInst.ExportData "X:\path", ".CATPart"

next

end sub

If CATIA can save my .stp file's contents as desired, surely I can do the same with VBA, right?

Any help would be greatly appreciated.

Laurens Ruben
  • 109
  • 5
  • 22

1 Answers1

1

The Product at the root of the tree can be saved as a CATProduct document. Any sub-products within the tree can also be saved as a CATProduct. The Parts, which are the leaves of the tree can be saved as CATParts.

You can save the root Product like this:

Dim rootProdDoc As ProductDocument
set rootProdDoc = CATIA.ActiveDocument
rootProdDoc.SaveAs "C:\Temp\" & rootProd.PartNumber & ".CATProduct"

However, when you do this, CATIA will complain that "This activates other save operations, do you want to continue?" It does this because the Parts are not yet saved. Answering yes CATIA will save your assembly and all the parts. However because you are not in control of the part saving it will preclude you from setting the names for those documents you want.

And because you have to answer a dialog, it will prevent you from making a batch program.

The right way to do this is to first save the leaf documents and then work "up" the tree the root level by level. Then everything will be saved when you need it to be.

----------Class clsSaveInfo definition--------------

Public level As Integer
Public prod As Product


-----------------(module definition)--------------- 

Option Explicit


Sub CATMain()

    CATIA.DisplayFileAlerts = False

    'get the root product
    Dim rootProd As Product
    Set rootProd = CATIA.ActiveDocument.Product

    'make a dictionary to track product structure
    Dim docsToSave As Scripting.Dictionary
    Set docsToSave = New Scripting.Dictionary

    'some parameters
    Dim level As Integer
    Dim maxLevel As Integer

    'read the assembly
    level = 0
    Call slurp(level, rootProd, docsToSave, maxLevel)

    Dim i
    Dim kx As String
    Dim info As clsSaveInfo

    Do Until docsToSave.count = 0
        Dim toRemove As Collection
        Set toRemove = New Collection
        For i = 0 To docsToSave.count - 1
           kx = docsToSave.keys(i)

           Set info = docsToSave.item(kx)

           If info.level = maxLevel Then
                Dim suffix As String
               If TypeName(info.prod) = "Part" Then
                    suffix = ".CATPart"
               Else
                    suffix = ".CATProduct"
                End If
                Dim partProd As Product
                Set partProd = info.prod
                Dim partDoc As Document
                Set partDoc = partProd.ReferenceProduct.Parent
                partDoc.SaveAs ("C:\Temp\" & partProd.partNumber & suffix)
                toRemove.add (kx)
            End If

        Next

     'remove the saved products from the dictionary
        For i = 1 To toRemove.count
            docsToSave.Remove (toRemove.item(i))
        Next

        'decrement the level we are looking for
        maxLevel = maxLevel - 1
    Loop


End Sub


Sub slurp(ByVal level As Integer, ByRef aProd As Product, ByRef allDocs As Scripting.Dictionary, ByRef maxLevel As Integer)

'increment the level
    level = level + 1

'track the max level
    If level > maxLevel Then maxLevel = level

 'see if the part is already in the save list, if not add it
    If allDocs.Exists(aProd.partNumber) = False Then
        Dim info As clsSaveInfo
        Set info = New clsSaveInfo
        info.level = level
        Set info.prod = aProd
        Call allDocs.add(aProd.partNumber, info)
    End If

'slurp up children
    Dim i
    For i = 1 To aProd.products.count
        Dim subProd As Product
        Set subProd = aProd.products.item(i)
        Call slurp(level, subProd, allDocs, maxLevel)
    Next

End Sub
C R Johnson
  • 964
  • 1
  • 5
  • 12
  • Yes I had already figured I'd need to save all lower level parts first and then work my way up. I did not expect an entire script to be supplied to me with just this one question. If this works I'd be very grateful indeed. I'll test it tomorrow morning. – Laurens Ruben Jan 10 '18 at 19:30
  • So I've pasted your code in the VBA environment I use to make macros for CATIA. The first thing I notice is the very first line appears red and the macro won't run. I delete the first set of dashes and I'm immediately prompted with "Compile error: Expected: end of statement", the word "definition" is highlighted. I delete "definition" and the remaining dashes in the first block of code until I no longer encounter prompts. I try to run the code and again I'm prompted: "Invalid outside procedure", clsSaveInfo is highlighted. How does this "class" and "definition" thing work?. – Laurens Ruben Jan 11 '18 at 07:26
  • Alright so I figure I need to create a Class module and declare the variables "level" and "prod" in this new Class module and name the module "clsSaveInfo". I'm still missing something though since I immediately get a prompt "User defined type not defined". Which I assume is because the declaration of "level" and "prod" didnt push through to the normal module's subs. – Laurens Ruben Jan 11 '18 at 08:05
  • In my previous comment: "Which I assume is because the declaration of "level" and "prod" didnt push through to the normal module's subs". This was incorrect, the problem was that I hadn't loaded the required library for using "Scripting.Dictionary". I solved this by running CATIA & VB as administrator, going to Tools -> References and checking the box for "Microsoft Scripting Library". Now the script works for 99% as intended. There is 1 thing that doesn't work as I would like it to, all items in the tree are being saved as .CATPoduct while it should save the lowest level items as .CATPart. – Laurens Ruben Jan 12 '18 at 11:45
  • More details on this issue soon. – Laurens Ruben Jan 12 '18 at 11:46
  • None of the part files had an output of "Part" for the suffix. – Laurens Ruben Jan 15 '18 at 15:02
  • I assume this has something to do with Catia first placing the step equivalent of a part in a catia product file before converting it to a catia part file. Anyway, I solved this by changing the line "If TypeName(info.prod) = "Part" Then" to "If Right(partProd.ReferenceProduct.Parent.FullName, 7) = "CATPart" Then" And moved the declaration of "partProd" to above this line. – Laurens Ruben Jan 15 '18 at 15:09
  • I have some additional issues related to this question, see: https://stackoverflow.com/questions/48264708/catia-vba-enable-use-of-scripting-dictionary-in-catscript Many thanks for helping me out with this script, it's invaluable to me not only for what it does but also for what it teaches me. – Laurens Ruben Jan 15 '18 at 15:10
  • One last hurdle to go before I can make a batch out of this code you gave me. See: https://stackoverflow.com/questions/48282675/catia-vba-to-catscript-for-type-collection – Laurens Ruben Jan 16 '18 at 13:48