Retrieve output parameters from an AutoCAD API method in python

后端 未结 1 1018
隐瞒了意图╮
隐瞒了意图╮ 2021-01-28 11:12

I\'m trying to retrieve 2 output Arrays from an XRecord in AutoCAD 2016 using python 2.7, with comtypes imported, the first array is an array of integers (DXF Group Codes) and t

相关标签:
1条回答
  • 2021-01-28 12:12

    Well, I haven't figured out any way to do so from python, however, since the data stored in XRecords are just numbers and strings (in my application), stored in the XRecord as variants, I've used MS Excel as a middle man to pass me data.

    Note: All numbers I've got were retrieved but as floats.

    And all strings were retrieved but their type is unicode. (you can convert them to string easily with the built-in function str())

    Here's how I've done that.


    First: Creation of The Facilitator Workbook (Our Middle Man)

    1-Normally as a regular windows user, open Excel, then open Visual Basic Editor, one way to do that is to go to Developer tab and click on Visual Basic Editor.

    2-From the Editor, insert a module (one way is from the menu bar: insert>Module), then left-double click on its default name and type "mod_facilitate", then hit Enter.

    3-Left-double click on its icon at the project viewer.

    4- A window will appear, copy the following code to it.

    Sub getxrecord()
    'get running AutoCAD object
    Dim mycad As AcadApplication, mydoc As AcadDocument, filepath As String
    Set mycad = GetObject(, "AutoCAD.Application.20")
    'get the selected drawing, provided from python code
    With Sheet1
        filepath = .Range(.Cells(1, 1), .Cells(1, 1)).Value
    End With
    
    Dim iCount As Integer, i As Integer, j As Integer, CompName As String
    iCount = mycad.Documents.Count
    For i = 0 To iCount - 1
        CompName = mycad.Documents.Item(i).FullName
        If CompName Like filepath Then
            j = i
            Exit For
        End If
    Next i
    Set mydoc = mycad.Documents.Item(j)
    Dim name2 As String
    
    'get the object from its provided handle
    
    With Sheet1
        handler = .Range(.Cells(2, 1), .Cells(2, 1)).Value
    End With
    Dim myXRecord As AcadXRecord
    Set myXRecord = mydoc.HandleToObject(handler)
    
    Dim DxfGrcd As Variant, Val As Variant
    DxfGrcd = Array()
    Val = Array()
    myXRecord.GetXRecordData DxfGrcd, Val
    
    Dim UB As Integer
    UB = UBound(DxfGrcd)
    For i = 0 To UB
        With Sheet1
            .Range(.Cells((i + 1), 2), .Cells((i + 1), 2)).Value = DxfGrcd(i)
            .Range(.Cells((i + 1), 3), .Cells((i + 1), 3)).Value = Val(i)
        End With
    Next i
    
    End Sub
    

    5- From Tools>References Select these reference names, leaving the others at their previous states

    AcSmComponents20 1.0 Type Library
    AutoCAD 2016 Type Library
    CAO 1.0 Type Library
    

    Then click on OK, then hit Ctrl+s to save.

    6- Save the file and name it "facilitator", save it within the same directory of your python file. Save it of type Excel Macro-Enabled Workbook (has the extension .xlsm)

    7- At your python file, define the function to retrieve XRecord's data as following, I'll tell what are its arguments for:

    def XRecord_return(namefile,handle,size):
        xl.Range["A1"].Value[xlRangeValueDefault] = namefile
        xl.Range["A2"].Value[xlRangeValueDefault] = handle
        xl.Application.Run("facilitator.xlsm!mod_facilitate.getxrecord")
    
        dxfgrcd = []
        vals = []
        for i in range(0,size):
            CellB = 'B' + str(i+1)
            CellC = 'C' + str(i+1)
            dxfgrcd.append(xl.Range[CellB].Value[xlRangeValueDefault])
            vals.append(xl.Range[CellC].Value[xlRangeValueDefault])
    
        return dxfgrcd,vals
    

    Second: What to Insure

    Note: All the following steps must be written before the definition of XRecord_return

    1- AutoCAD must be instantiated from python using a line like autocad = CreateObject("AutoCAD.Application.20",dynamic=True) or autocad = comtypes.client.CreateObject("AutoCAD.Application.20",dynamic=True) depending on the scope of importing and importing form [ import comtypes.client or from comtypes.client import CreateObject ], here, importing scope is the python file's module scope.

    2-instantiate Excel using xl = CreateObject("Excel.Application") and open the facilitator file with

    xlpath = os.getcwd()
    xlpath += '\\facilitator.xlsm'
    xl = CreateObject("Excel.Application")
    from comtypes.gen.Excel import xlRangeValueDefault
    xlwb = xl.Workbooks.Open(Filename=xlpath,ReadOnly=0)
    

    3- You have to know how many elements are stored in the XRecord (excluding the number of associated DXF group codes), this number of elements is what you'll supply to XRecord_return as its size argument.

    e.g. An XRecord that stores 3.0 "abc" 5 and have correspondent DXF group codes 1 2 3 is of size 3, not 6.

    Third: Supplying Data to The Facilitator Workbook

    We need only its first worksheet, you must provide the following data:-

    1- The drawing's full path/directory to cell "A1".

    To get the drawing's full path if you have its Document object you can get it from the property FullName. This value is what you'll supply to XRecord_return as its namefile argument.

    To assign, for instance: xl.Range["A1"].Values[xlRangeValueDefault] = filepath

    2-The XRecord's handle value to cell "A2", you can get it from the property Handle of the XRecord. This value is what you'll supply to XRecord_return as its 'handle' argument.

    To assign, for instance: xl.Range["A1"].Values[xlRangeValueDefault] = handlevalue

    3- After that, wherever you need to get the XRecords data, call the XRecord_return function, like

    DxfGrCd,vals = XRecord_return(filepath,handlevalue,size_of_XRecord)
    

    The outputs are lists that contain the correspondent data.

    Last, But not Least

    When you finish using Excel for retrieving data from as many XRecords as you need, close the facilitator workbook using xlwb.Close(SaveChanges=0)

    0 讨论(0)
提交回复
热议问题