pyautocad & ActiveX: pywintypes.com_error, AddTable & wrong parameters

25 views Asked by At

I am currently trying to add a table to a newly created AutoCAD layout in Python, using the AddTable() method.

I am currently facing this error:

type he table = modelspace.AddTable(insertion_point, num_rows, num_columns, 
row_height, col_width)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<COMObject <unknown>>", line 3, in AddTable
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2147024809), None)re

I will attach the code in its entirety at the bottom. I believe the issue comes from an error in function parameters. I have tried to closely followed what is indicated in the documentation here:

ActiveX documentation: text and more generally through here as well: text


Entire code:

import win32com.client
import os
from pyautocad import Autocad, ACAD, APoint
from array import array
import time
from pythoncom import com_error



def run_vba_macro(vba_file_path, *args):
    acad = win32com.client.Dispatch("AutoCAD.Application")
    acad.Visible = True

    doc = acad.ActiveDocument
    vba_module = doc.VBProject.VBComponents.Add(1)
    
    with open(vba_file_path, 'r') as vba_file:
        vba_module.CodeModule.AddFromString(vba_file.read())

    vba_module.ProcedureOptions(1)  # Set module as a procedure
    vba_module_name = os.path.splitext(os.path.basename(vba_file_path))[0]

    # Execute the VBA macro with parameters
    vba_args = ", ".join(map(str, args))
    vba_macro_call = f"{vba_module_name}.Example_AddTable {vba_args}"
    acad.Application.Run(vba_macro_call)


def problem_function(source_layout, new_layout_name, layouts, doc, acad):
    # Add a new layout to the layouts collection
    new_layout = layouts.Add(new_layout_name)

    # set the active layout to the new one- this is because idk how paperspace works
    #acad.ActiveDocument.ActiveLayout = acad.ActiveDocument.Layouts.Item(new_layout_name)
    #
    #new_layout = doc.Layouts.ModelSpace(new_layout_name)
    doc.ActiveLayout = new_layout

    # for i in doc.Layouts:
    #     if i.Name == 'NewLayout':
    #         new_layout = i
    #         break

    paper_space = doc.PaperSpace
    print(f"The paper space we are inserting to is: {paper_space.Name}, {paper_space.Layout.Name}")
    insertion_point = (0,0,0)
    #new_layout.Block.AddText("Hello", insertion_point, 25.0)
    #print(f"new_layout.Block.Count is {new_layout.Block.Count}")
   





    for bloc in new_layout.Block:
        print(f"\t new_layout.Block.Name is {new_layout.Block.Name}")

    # Iterate through Tables inside source_layout
    for table in source_layout.Block:
        if table.EntityName == "AcDbTable" and table is not None:
            print("found a table in source layout!")
            # Retrieve parameters for the existing table
            insertion_point = array('f', table.InsertionPoint)


            num_rows = table.Rows #num_rows = table.Rows.Count
            num_columns = table.Columns
            row_height = float(table.Rows) #table.Rows.Item(1).Height
            col_width = float(table.Columns)

            # Add a table to the new_layout using the retrieved parameters
            #new_table = paper_space.AddTable(insertion_point, num_rows, num_columns, row_height, col_width)

            print(f"Table is the one in layer: {table.Layer}")
            print(f"The insertion point used is {insertion_point}, type: {type(insertion_point)}")
            #print(f"InsertionPoint(0) is {insertion_point(0)}")
            print(f"The num_rows used is {num_rows}, type: {type(num_rows)}")
            print(f"The num_columns used is {num_columns}, type: {type(num_columns)}")
            print(f"The row_height used is {row_height}, type: {type(row_height)}")
            print(f"The col_width used is {col_width}, type: {type(col_width)}")

            
            print("\n")

            
            #paper_space.Blocks.AddTable(insertion_point, num_rows, num_columns, row_height, col_width)
            

            insertion_point = [0.0, 0.0, 0.0]

            try:
                #new_table = paper_space.AddTable(insertion_point, num_rows, num_columns, row_height, col_width)

                modelspace = doc.ModelSpace
                table = modelspace.AddTable(insertion_point, num_rows, num_columns, row_height, col_width)
                copy_table = table.Copy()
                table.Erase()
                new_layout.Block.AppendEntity(copy_table)
                doc.Regen(0)
            except com_error:
                print("AutoCAD is busy, retrying...")
                time.sleep(1)
                modelspace = doc.ModelSpace
                table = modelspace.AddTable(insertion_point, num_rows, num_columns, row_height, col_width)
                copy_table = table.Copy()
                table.Erase()
                new_layout.Block.AppendEntity(copy_table)
                doc.Regen(0)
                #new_table = paper_space.AddTable(insertion_point, num_rows, num_columns, row_height, col_width)
            # Now, you can customize the new_table or perform additional operations if needed
            # Execute the VBA macro to add a table


            


            print(f"Table copied from '{source_layout.LayoutName}' to '{new_layout_name}' successfully.")
            doc.Regen(0)




def text_insert(acad):
    t1 = acad.model.AddText("Hello", APoint(75,50), 25)

def main():
    file_name = "Drawing1.dwg"
    file_path = os.path.abspath(file_name)
    acad = win32com.client.Dispatch("AutoCAD.Application")

    # Get the active document
    doc = acad.ActiveDocument

    # Assume the file PI-D410-XXX2-Copy-Dummy.dwg is already open
    # Specify the layout name to copy
    source_layout_name = "8"

    # Get layouts collection from the active document
    layouts = doc.Layouts

    # Find the source layout by name
    source_layout = None
    for layout in layouts:
        if layout.name == source_layout_name:
            print("** Found layout 8!")
            source_layout = layout
            break

    if source_layout is not None:
        # Specify the name for the new layout
        new_layout_name = "NewLayout"

        # Copy layout information from the source layout to a new layout
        #text_insert(acad)
        problem_function(source_layout, new_layout_name, layouts, doc, acad)

        print(f"Layout '{source_layout_name}' copied to '{new_layout_name}' successfully.")
    else:
        print(f"Layout '{source_layout_name}' not found in the active document.")

if __name__ == "__main__":
    main()

I do not understand where the error comes from, or what I should be doing instead. I have also tried:

  • Using a new CAD file in case this one has been corrupted.
  • Checking my Python was indeed 64 bit.
  • Using Add Table to the ModelSpace or PaperSpace instead and then moving it into my layout.

I am running out of options currently, and I am always met with this error. Would anyone know what I am doing wrong? Or how should I go about doing this instead?

Thank you immensely for any support :)

0

There are 0 answers