Sheet Set - Replace specific block on each sheet with a new block

I am learning Dynamo and I am giving myself a headache trying to figure some of this stuff out. If anyone can help me with any of the following it would be very much appreciated.

My goal is to have a script that I can select a specific block to replace with a different block on every sheet within a sheet set. I have figured out how to insert my replacement block at the desired location although with manual coordinates.
Ultimately I would like the script to do the following:

  1. Get the sheet set the current drawing is a part or select the sheet set somehow
  2. Load each layout in the sheet set
    a. Find all blocks named “x”
    b. Get insertion coordinates of each block
    c. Delete all blocks named “x”
    d. Insert new blocks at the coordinates from block “x”

I am struggling to understand the following:

  • Can I access the sheet set that the current drawing/layout is a part of?
  • How to access an individual sheet within a drawing and then search for blocks within that sheet.
  • Once I find the block, how do I retrieve the insertion point information to save.

I think my biggest issue at this point is understanding the data structure for accessing and filtering lists of objects and any advice or resources for getting a grasp on this would be very much appreciated.

This is what I have so far which inserts the block into the current sheet but it doesn’t get the coordinates of the existing blocks and delete them.

1 Like

Hi @srCAD,

Cool! You’re going to need download a few packages to get this to work since there aren’t many nodes available OOTB.

Take a look at the “AMR Sheet Set Manager” package. I think it will have some nodes that will help you with this.

You can accomplish this with the Camber package. Here are some of the nodes that enable access to layouts (look under the “AutoCAD shelf”):

Just to clarify some terminology here, I believe you are referring to a block reference rather than a block. I’m clarifying because a block definition does not have any insertion point in world coordinates (or paper coordinates, in this case). So once you have the block references, there’s a few ways you could get the insertion point.

  • If only using OOTB nodes, you can get the block reference’s coordinate system using BlockReference.CoordinateSystem and then get the origin of the CS using CoordinateSystem.Origin.
  • You can use the Civil 3D Toolkit package to simplify this slightly by using the BlockReferenceExtensions.GetInsertionPoint node.

One last note. As you may have discovered, Dynamo is only able to access the current document at this point in time. So even if you can get the name of a layout from a sheet set, you won’t be able to do much with it unless that specific DWG is open. There are some nodes available in the Camber package under the “External” shelf that enable access to files other than the currently open one, but I haven’t added the ability to work with layouts yet. So for now, you are probably stuck running this script on one drawing at a time and not in bulk :confused:

It’s certainly possible to do bulk operations, but you’ll be stepping outside the realm of pre-made nodes and getting into custom functionality using the AutoCAD .NET API.

1 Like

Thank you for the reply! I think this should help me get a functional script for now and I can add the bulk functionality down the road.

Would you be okay with iterating through the layouts by a list of drawings rather than the sheet set manager? I found this information on using sheet set manager: Using SheetSet Manager API in VB.NET - AutoCAD DevBlog but am having trouble finding documentation on how to implement this in the developer guide outside of ARX and can’t seem to figure it out. It would be easier for me to develop something by selecting a folder and it iterating through the dwgs within it.

@mzjensen Would you mind telling me where I’m going wrong here? Still new to using python node and .NET for civil 3d so I apologize. I’ve managed to collect the layouts in python and get their block table record IDs. But when I use “.GetBlockReferenceIds” on the block table record of the paper spaces, I get an empty list instead of a list of the entities drawn in paper space. Is this the correct method for collecting block references in a block reference table, I.E. paper space layouts?

import os
import re

# Add Assemblies for AutoCAD APIs
clr.AddReference('acmgd')
clr.AddReference('acdbmgd')
clr.AddReference('accoremgd')




# Import references from AutoCAD
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.EditorInput import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *

import Autodesk.AutoCAD.ApplicationServices.Application as acapp
import Autodesk.AutoCAD.ApplicationServices.DocumentCollectionExtension



DWGPaths = ['F:\Dynamo\Replace Blocks Across Sheets\A.dwg', 'F:\Dynamo\Replace Blocks Across Sheets\B.dwg']


#Real Code


for DWGPath in DWGPaths:
    adoc = DocumentCollectionExtension.Open(acapp.DocumentManager, DWGPath, False)


    with adoc.LockDocument():
        with adoc.Database as db:
            with db.TransactionManager.StartTransaction() as t:
                
                layoutObjectIDs = []
                layoutBlockTableIDs = []
                
                layoutDict = t.GetObject(db.LayoutDictionaryId, OpenMode.ForWrite)
                
                for layout in layoutDict:
                	if "Model" not in layout.Key:
                		layoutObjectIDs.append(layout.Value)
                
                for layoutObjectID in layoutObjectIDs:
                	layout = t.GetObject(layoutObjectID, OpenMode.ForRead)
                	
                	layoutBlockTableID = layout.BlockTableRecordId
                	layoutBlockTableIDs.append(layoutBlockTableID)
                
                for layoutBlockTableID in layoutBlockTableIDs:
                	layoutBTR = t.GetObject(layoutBlockTableID, OpenMode.ForRead)
                	
                	blockReferenceIDs = layoutBTR.GetBlockReferenceIds(True, True)
                
                t.Commit()
                pass
                
    if adoc:
        DocumentExtension.CloseAndSave(adoc, DWGPath)


OUT = layoutBlockTableIDs, layoutObjectIDs, blockReferenceIDs



The GetBlockReferenceIds method gets the object IDs of the block references that have that particular record as their source block table record, so that isn’t what you want. So instead you’d want to loop through the IDs in the block table record and collect those that are block references, then check the names of each block reference’s parent block table record so you collect the ones you want.

As a separate note, this is going to be much more performant if you use a side database for each DWG instead of opening and closing the file each time.

Okay. I’m kind of confused but this does help. I thought I was attempting to loop through the IDs of the block table record. The block table record of the paper space. → Help
“Each Paper space layout has its own block table record.”

So I’m correct up to the “GetBlockReferenceIds” step? How would I instead get all of the entities in each block table record?

I’d love to learn more about using a side database for each DWG but I honestly have no clue how to do that.

This is where you would loop through the IDs. After you have the paper space block table record.

But how do I list all of the objects in a block table record? Is a block table record just a list? So i can do like, for item in block table record, print item? Ect.?

It’s essentially just a collection of object IDs, so you can iterate over it. Something like this:

for oid in btr:
    # Do work here
1 Like

Easy. Thanks!!!

Can’t believe I actually got this working. It’s kind of a mess but it works and I’m super proud of it! First time doing a lot of stuff here for me. This will replace a block with another block by name given a folder of dwgs across all of the layouts in those dwgs.

ReplaceBlocksAcrossSheets.dyn (18.2 KB)

Thanks so much for all your help @mzjensen :sob: I’d be totally stuck without ya.

3 Likes