CATIA v5 VBA:自定义BOM宏将UserRefProperties插入表中

时间:2017-11-30 13:11:31

标签: vba catia

我想创建一个自定义BOM,我在coe.org论坛上找到了一个宏(见帖子底部)。 我按照要求实施它有些困难。 在某些时候,宏使用代码:

Call oDrawingTable.SetCellString(n, 1, ProductList(n).PartNumber)
    Call Dressup_Table(oDrawingTable, n, 1, 2, 0)

我测试了宏并且这有效,但是我想写一些用户定义的属性的值而不是预设的CATIA属性。 因此我将代码更改为:

Call oDrawingTable.SetCellString(n, 1, ProductList(n).UserRefProperties.Item("CE_NUMBER"))
    Call Dressup_Table(oDrawingTable, n, 1, 2, 0)

当我再次执行宏时,我得到错误:

  

自动化错误

     

未指定的错误

我对编程很新,但我已经使用了

...Product.UserRefProperties.Item("CE_NUMBER") 

之前在我的标题栏中,它确实在那里工作。我尝试了多种变体,比如

ProductList(n).CE_NUMBER

但是我无法让它发挥作用。

我已经退回了产品列表(n),它的声明如下:

Dim ProductList(50) As Product

据我所知,它应该返回相同类型的东西.Product就像我的标题块中的代码一样。

任何人都知道如何让这个宏做我想做的事情? Thx提前。

从coe.org复制的原始宏代码(它有几个缺少的字符):

Option Explicit
Sub CATMain()

  On Error Resume Next

'Declare Variables
    Dim oDocument As Document
    Dim oDrawingDoc As DrawingDocument
    Dim oDrawingSheets As DrawingSheets
    Dim oDrawingSheet As DrawingSheet
    Dim oDrawingViews As DrawingViews
    Dim oDrawingView As DrawingView
    Dim oDrawingTables As DrawingTables
    Dim oDrawingTable As DrawingTable
    Dim oBackgroundView As DrawingView
    Dim oProductDoc As ProductDocument
    Dim oProducts As Products
    Dim oProduct As Product
    Dim TempProduct As Product
    Dim QtyDict As Variant
    Dim Width As Integer
    Dim height As Integer
    Dim xOffset As Integer
    Dim yOffset As Integer
    Dim XOrig As Integer
    Dim YOrig As Integer




'Check that the ActiveDocument is a CATDrawing.
'If not, inform the user and terminate execution.

    Set oDocument = CATIA.ActiveDocument

    If Right(oDocument.FullName, 10) "CATDrawing" Then
        MsgBox "This utility must be executed from a within a CATDrawing."
        Exit Sub
    End If

'Populate the Variables
    Set oDrawingDoc = CATIA.ActiveDocument
    Set oDrawingSheets = oDrawingDoc.Sheets
    Set oDrawingSheet = oDrawingSheets.ActiveSheet
    Set oDrawingViews = oDrawingSheet.Views
    Set oDrawingView = oDrawingViews.Item(3)
    Set oBackgroundView = oDrawingViews.Item("Background View"
    Set oDrawingTables = oBackgroundView.Tables

    Err.Clear

 'Check that the linked document is a product and not a part

    Set oProductDoc = oDrawingView.GenerativeLinks.FirstLink.Parent

    If Err.Number 0 Then
        MsgBox "The linked model is not a product!", vbExclamation
        Exit Sub
    End If


    Set oProducts = oProductDoc.Product.Products
    Set QtyDict = CreateObject("Scripting.Dictionary"




'get the sheet dimensions so that we can place the bom in the right
'place relative to the drawing border

    xOffset = -90
    yOffset = 10
    Width = oDrawingSheet.GetPaperWidth
    height = oDrawingSheet.GetPaperHeight

    XOrig = Width + xOffset
    YOrig = yOffset





'Scan through the Product Structure of the assembly noteing the quantity of
'each component.  Add one of each component to a list of the products for
'future use.
    Dim n As Integer
    Dim SourceText As String
    Dim ProductList(50) As Product
    Dim Index As Integer
    Index = 1




    For n = 1 To oProducts.Count
        Set TempProduct = oProducts.Item(n)



        If QtyDict.exists(TempProduct.PartNumber) = True Then
            QtyDict.Item(TempProduct.PartNumber) = QtyDict.Item(TempProduct.PartNumber) + 1
        Else
            QtyDict.Add TempProduct.PartNumber, 1
            Set ProductList(Index) = TempProduct
            Index = Index + 1
        End If
    Next n



'Check to see if a BOM has already been created on the Drawing.
'This code will be utilized when updates to the BOM are needed.
'If the BOM table already exists, skip to the code which will
'populate the BOM.
    For n = 1 To oDrawingTables.Count
        Set oDrawingTable = oDrawingTables.Item(n)
        If oDrawingTable.Name = "DrawingBOM" Then
            GoTo POPULATEBOM
        End If
    Next n

'If the table does not exist, create one and label it the same as
'the table name being searched for.

    Set oDrawingTable = oDrawingTables.Add(XOrig, YOrig, QtyDict.Count + 1, 5, 3, 5)
    oDrawingTable.Name = "DrawingBOM"
    oDrawingTable.AnchorPoint = CatTableBottomRight






'Populate the cells of the BOM Table
POPULATEBOM:

    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 1, "Part Number"
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 1, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 2, "Description"
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 2, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 3, "Supplier"
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 3, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 4, "Qty"
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 4, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 5, "Source"
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 5, 1, 1)


    Call oDrawingTable.SetColumnSize(1, 50)
    Call oDrawingTable.SetColumnSize(2, 110)
    Call oDrawingTable.SetColumnSize(3, 110)
    Call oDrawingTable.SetColumnSize(4, 12)
    Call oDrawingTable.SetColumnSize(5, 20)

'Use the list created earlier in order to populate the information
'about each part in the product structure.

    For n = 1 To (oDrawingTable.NumberOfRows - 1)

        Call oDrawingTable.SetCellString(n, 1, ProductList(n).PartNumber)
            Call Dressup_Table(oDrawingTable, n, 1, 2, 0)
        Call oDrawingTable.SetCellString(n, 2, ProductList(n).Definition)
            Call Dressup_Table(oDrawingTable, n, 2, 2, 0)
        Call oDrawingTable.SetCellString(n, 3, ProductList(n).DescriptionRef)
            Call Dressup_Table(oDrawingTable, n, 3, 2, 0)
        Call oDrawingTable.SetCellString(n, 4, QtyDict.Item(ProductList(n).PartNumber))
                Call Dressup_Table(oDrawingTable, n, 4, 1, 0)


        Select Case ProductList(n).Source

        Case "0"

            SourceText = "Unknown"

        Case "1"

            SourceText = "Made"

        Case "2"

            SourceText = "Bought"

        End Select



        Call oDrawingTable.SetCellString(n, 5, SourceText)
            Call Dressup_Table(oDrawingTable, n, 5, 2, 0)

    Next n





End Sub

Sub Dressup_Table(current_table As DrawingTable, ByVal line_number As Integer, ByVal column_number As Integer, ByVal type_justification As Integer, ByVal bold As Integer)


'-------------------------------
' sort out the justification
'-------------------------------
'
    If type_justification = 1 Then
        current_table.SetCellAlignment line_number, column_number, CatTableMiddleCenter
    ElseIf type_justification = 2 Then
        current_table.SetCellAlignment line_number, column_number, CatTableMiddleLeft
    End If
'
'--------------------------------------
' get the current text
'--------------------------------------
'
    Dim current_text As DrawingText
    Set current_text = current_table.GetCellObject(line_number, column_number)
'
'------------------------------------
' set up the current text
'------------------------------------
'
    Dim oText As Integer
    oText = Len(current_text.Text)
'
' Font Arial
'
    current_text.SetFontName 1, oText, "Arial (TrueType)"
'
' font height
'
    current_text.SetFontSize 1, oText, 2.5
'
' graphical attributes
'
    current_text.SetParameterOnSubString catBold, 1, oText, bold
    current_text.SetParameterOnSubString catUnderline, 1, oText, 0
    current_text.SetParameterOnSubString catItalic, 1, oText, 0
    current_text.SetParameterOnSubString catItalic, 1, oText, 0
    current_text.SetParameterOnSubString catOverline, 1, oText, 0
'
End Sub

我目前在我的宏中编码:

Option Explicit
Sub CATMain()

'Declare Variables
    Dim oDocument As Document
    Dim oDrawingDoc As DrawingDocument
    Dim oDrawingSheets As DrawingSheets
    Dim oDrawingSheet As DrawingSheet
    Dim oDrawingViews As DrawingViews
    Dim oDrawingView As DrawingView
    Dim oDrawingTables As DrawingTables
    Dim oDrawingTable As DrawingTable
    Dim oBackgroundView As DrawingView
    Dim oProductDoc As ProductDocument
    Dim oProducts As Products
    Dim oProduct As Product
    Dim TempProduct As Product
    Dim QtyDict As Variant
    Dim Width As Integer
    Dim height As Integer
    Dim xOffset As Integer
    Dim yOffset As Integer
    Dim XOrig As Integer
    Dim YOrig As Integer




'Check that the ActiveDocument is a CATDrawing.
'If not, inform the user and terminate execution.

    Set oDocument = CATIA.ActiveDocument

    If Right(oDocument.FullName, 10) <> "CATDrawing" Then
        MsgBox "This utility must be executed from a within a CATDrawing."
        Exit Sub
    End If

'Populate the Variables
    Set oDrawingDoc = CATIA.ActiveDocument
    Set oDrawingSheets = oDrawingDoc.Sheets
    Set oDrawingSheet = oDrawingSheets.ActiveSheet
    Set oDrawingViews = oDrawingSheet.Views
    Set oDrawingView = oDrawingViews.Item(4)
    Set oBackgroundView = oDrawingViews.Item("Background View")
    Set oDrawingTables = oBackgroundView.Tables

    Err.Clear

 'Check that the linked document is a product and not a part

    Set oProductDoc = oDrawingView.GenerativeLinks.FirstLink.Parent

    If Err.Number <> 0 Then
        MsgBox "The linked model is not a product!", vbExclamation
        Exit Sub
    End If


    Set oProducts = oProductDoc.Product.Products
    Set QtyDict = CreateObject("Scripting.Dictionary")


'get the sheet dimensions so that we can place the bom in the right
'place relative to the drawing border

    xOffset = -90
    yOffset = 200
    Width = oDrawingSheet.GetPaperWidth
    height = oDrawingSheet.GetPaperHeight

    XOrig = Width + xOffset
    YOrig = yOffset





'Scan through the Product Structure of the assembly noteing the quantity of
'each component.  Add one of each component to a list of the products for
'future use.
    Dim n As Integer
    Dim SourceText As String
    Dim ProductList(50) As Product
    Dim Index As Integer
    Index = 1




    For n = 1 To oProducts.Count
        Set TempProduct = oProducts.Item(n)



        If QtyDict.exists(TempProduct.PartNumber) = True Then
            QtyDict.Item(TempProduct.PartNumber) = QtyDict.Item(TempProduct.PartNumber) + 1
        Else
            QtyDict.Add TempProduct.PartNumber, 1
            Set ProductList(Index) = TempProduct
            Index = Index + 1
        End If
    Next n





'If the table does not exist, create one and label it the same as
'the table name being searched for.

    Set oDrawingTable = oDrawingTables.Add(XOrig, YOrig, QtyDict.Count + 1, 9, 3, 5)
    oDrawingTable.Name = "DrawingBOM"
    oDrawingTable.AnchorPoint = CatTableBottomRight






'Populate the cells of the BOM Table
POPULATEBOM:

    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 1, "QTY")
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 1, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 2, "PART-NUMBER")
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 2, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 3, "DESCRIPTION")
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 3, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 4, "VENDOR")
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 4, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 5, "STOCK NUMBER")
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 5, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 6, "MATERIAL")
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 6, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 7, "COATING")
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 7, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 8, "WEIGHT")
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 8, 1, 1)
    Call oDrawingTable.SetCellString(oDrawingTable.NumberOfRows, 9, "REMARK")
                Call Dressup_Table(oDrawingTable, oDrawingTable.NumberOfRows, 9, 1, 1)


    Call oDrawingTable.SetColumnSize(1, 10)
    Call oDrawingTable.SetColumnSize(2, 100)
    Call oDrawingTable.SetColumnSize(3, 100)
    Call oDrawingTable.SetColumnSize(4, 50)
    Call oDrawingTable.SetColumnSize(5, 50)
    Call oDrawingTable.SetColumnSize(6, 80)
    Call oDrawingTable.SetColumnSize(7, 80)
    Call oDrawingTable.SetColumnSize(8, 50)
    Call oDrawingTable.SetColumnSize(9, 80)

'Use the list created earlier in order to populate the information
'about each part in the product structure.

    For n = 1 To (oDrawingTable.NumberOfRows - 1)

        Call oDrawingTable.SetCellString(n, 1, QtyDict.Item(ProductList(n).PartNumber))
            Call Dressup_Table(oDrawingTable, n, 1, 1, 0)
        Call oDrawingTable.SetCellString(n, 2, ProductList(n).UserRefProperties.CE_NUMBER)
            Call Dressup_Table(oDrawingTable, n, 2, 2, 0)
        Call oDrawingTable.SetCellString(n, 3, ProductList(n).UserRefProperties.Item("DESCRIPTION"))
            Call Dressup_Table(oDrawingTable, n, 3, 2, 0)
        Call oDrawingTable.SetCellString(n, 4, ProductList(n).UserRefProperties.Item("VENDOR"))
            Call Dressup_Table(oDrawingTable, n, 4, 2, 0)
        Call oDrawingTable.SetCellString(n, 5, ProductList(n).UserRefProperties.Item("STOCK_NUMBER"))
            Call Dressup_Table(oDrawingTable, n, 5, 2, 0)
        Call oDrawingTable.SetCellString(n, 6, ProductList(n).UserRefProperties.Item("MATERIAL"))
            Call Dressup_Table(oDrawingTable, n, 6, 2, 0)
        Call oDrawingTable.SetCellString(n, 7, ProductList(n).UserRefProperties.Item("COATING"))
            Call Dressup_Table(oDrawingTable, n, 7, 2, 0)
        Call oDrawingTable.SetCellString(n, 8, ProductList(n).UserRefProperties.Item("CC_CALC_WEIGHT"))
            Call Dressup_Table(oDrawingTable, n, 8, 2, 0)
        Call oDrawingTable.SetCellString(n, 9, ProductList(n).UserRefProperties.Item("REMARK"))
            Call Dressup_Table(oDrawingTable, n, 9, 2, 0)



    Next n





End Sub

Sub Dressup_Table(current_table As DrawingTable, ByVal line_number As Integer, ByVal column_number As Integer, ByVal type_justification As Integer, ByVal bold As Integer)


'-------------------------------
' sort out the justification
'-------------------------------
'
    If type_justification = 1 Then
        current_table.SetCellAlignment line_number, column_number, CatTableMiddleCenter
    ElseIf type_justification = 2 Then
        current_table.SetCellAlignment line_number, column_number, CatTableMiddleLeft
    End If
'
'--------------------------------------
' get the current text
'--------------------------------------
'
    Dim current_text As DrawingText
    Set current_text = current_table.GetCellObject(line_number, column_number)
'
'------------------------------------
' set up the current text
'------------------------------------
'
    Dim oText As Integer
    oText = Len(current_text.Text)
'
' Font Arial
'
    current_text.SetFontName 1, oText, "Arial (TrueType)"
'
' font height
'
    current_text.SetFontSize 1, oText, 2.5
'
' graphical attributes
'
    current_text.SetParameterOnSubString catBold, 1, oText, bold
    current_text.SetParameterOnSubString catUnderline, 1, oText, 0
    current_text.SetParameterOnSubString catItalic, 1, oText, 0
    current_text.SetParameterOnSubString catItalic, 1, oText, 0
    current_text.SetParameterOnSubString catOverline, 1, oText, 0
'
End Sub

2 个答案:

答案 0 :(得分:0)

目前我手头没有CATIA,但UserRefProperties的项目可能不是字符串,而是参数。在您的情况下,很可能是StrParam,一个包含字符串的参数。尝试

ProductList(n).UserRefProperties.Item("CE_NUMBER").Value

而不是

ProductList(n).UserRefProperties.Item("CE_NUMBER")

除此之外,当您循环所有产品时,要么确保所有产品都具有该用户参数,要么处理无法保证的情况。

答案 1 :(得分:0)

TLDR:
取代

ProductList(n).UserRefProperties.Item("CE_NUMBER")

ProductList(n).Product.UserRefProperties.Item("CE_NUMBER")

冗长的解释:

Call oDrawingTable.SetCellString(n, 1, ProductList(n).UserRefProperties.Item("CE_NUMBER"))
    Call Dressup_Table(oDrawingTable, n, 1, 2, 0)

此代码未执行的原因是因为方法“UserRefProperties”不适用于此特定对象级别的产品,即使方法“参数”在此级别工作也是如此。即使在检查产品的同时,您也会在相同的对象水平上找到两组参数。

现在这会引起一些混乱,我会试着澄清一下: 当Catia打开.CATProduct文件时,此文件被声明为ProductDocument对象,此对象包含Product对象,可以使用Parameters和UserRefProperties方法。 当调用ProductDocument的子Product(在这种情况下为oProductDoc)时会出现混淆,在这种情况下通过

Productlist(Index) =  oProductDoc.Product.Products.item(n)

方法。

现在,我们实际上使用ProductList(n)调用上面原始BOM代码的下方是原始oProductDoc的子产品的ProductDocument。但是我们实际上并没有将ProductList(n)声明为ProductDocument,而是将其声明为Product。 Catia认识到我们正在这样做并允许它发生,它还方便地将基础产品的所有方法/属性/参数“拔除/复制”到该对象。所有这些除UserRefProperties外 因此,要实际访问UserRefProperties,需要更深层次,ProductList(n)的Product级别。最后,我们得出了原始问题的解决方案:

而不是使用

ProductList(n).UserRefProperties.Item("CE_NUMBER"))

我们应该用

替换它
ProductList(n).Product.UserRefProperties.Item("CE_NUMBER"))

我偶然发现了解决方案,试用和错误。很长一段时间我都不知道为什么它按照它的方式工作但是最近我在VBA中发现了“Locals”窗口,很快我就清楚地知道发生了什么。
我并不是说我的解释是100%正确的,我的术语充其量只是粗略的,但我相信思路至少是朝着正确的方向发展。

我放弃了尝试使用宏制作自定义BOM,因为Catia中的高级BOM选项可以达到足以满足我的需求。