Hello, I’m trying create script, which will be delete all layout excluding layout name the same as file name. How I can delete layout by dynamo from Civil 3d?
What have you tried so far?
When I tested on my own I could filter out the Layout except the one with the same name as file name byt couldn’t delete the rest.
You can use python by ‘side loading’ the file as a Database and erasing the layout using the AutoCAD API. Use carefully as this will overwrite files - I have added a boolean to IN[2]
specifically to try a dry run before committing. EDIT See updated code below as this was producing unhandled errors
import clr
import traceback
from pathlib import Path # python 3.4+
clr.AddReference("AcDbMgd")
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.DatabaseServices import *
from System.IO import FileShare
dwgdir = IN[0]
layouts = IN[1] if isinstance(IN[1], list) else [IN[1]] # list of layouts to erase
delete_layouts = IN[2] # True / False
files = list(map(str, Path(dwgdir).glob("*.dwg")))
output = []
for dwg in files:
info = []
with Database(False, True) as db:
db.ReadDwgFile(dwg, FileShare.ReadWrite, False, "")
info.append(dwg)
with db.TransactionManager.StartTransaction() as t:
try:
layoutdict = t.GetObject(db.LayoutDictionaryId, OpenMode.ForRead)
for layout in layoutdict.get_Keys():
if layout in layouts:
layout_to_erase = t.GetObject(layoutdict[layout], OpenMode.ForWrite)
if delete_layouts:
layout_to_erase.Erase()
info.append(f"{layout} erased")
except:
output.append(traceback.format_exc())
t.Commit()
if delete_layouts and len(info) > 1: # Layout(s) erased
db.SaveAs(dwg, DwgVersion.Current)
output.append(info)
OUT = output
Thanks Mike.
I’m new to Python so this was a good example how to use it.
Hi Piotr,
I was getting a lot of unhandled exceptions on my code leading to C3D crashing (this is a professional hazard when working with the AutoCAD API). Anyhow… I have updated the code as follows
import clr
import traceback
from pathlib import Path # python 3.4+
clr.AddReference("AcDbMgd")
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.DatabaseServices import *
from System.IO import FileShare
dwgdir = IN[0]
layouts = IN[1] if isinstance(IN[1], list) else [IN[1]]
delete_layouts = IN[2] # True / False
files = list(map(str, Path(dwgdir).glob("*.dwg")))
# https://forums.autodesk.com/t5/net/remove-layout/m-p/5824156/highlight/true#M46014
output = []
currentdb = HostApplicationServices.WorkingDatabase
for dwg in files:
info = []
with Database(False, True) as db:
db.ReadDwgFile(dwg, FileShare.ReadWrite, False, "")
HostApplicationServices.WorkingDatabase = db
layoutmanager = LayoutManager.Current
info.append(dwg)
for layout in layouts:
try:
if delete_layouts:
layoutmanager.DeleteLayout(layout)
info.append(f"{layout} erased")
except:
info.append(traceback.format_exc())
if delete_layouts and len(info) > 1: # Layout(s) erased
db.SaveAs(dwg, DwgVersion.Current)
output.append(info)
HostApplicationServices.WorkingDatabase = currentdb
OUT = output
It’s based on a response by Gilles Chanteau who is unparalleled in their knowledge of the API
Inputs as follows:
IN[0]
Path to directory with dwg filesIN[1]
Layouts to deleteIN[2]
Dry run (False) Do it! (True)
You could use a List.UniqueItems node on the flattened layout list to reduce iterations
It works! Thanks, you are great!
Unfortunately, script works only at test clean files. Scrip causes crash Civil 3d and damaged files. I tried on Civil 2022 and 2024 and many DWG. After use script DWG has 0KB.
Did you test Object.Delete node? you can remove a list of objects using it!
I tested that one but it didn’t work for layouts
I have it working on C3D 2022. Start by starting with a clean graph and testing, testing, testing.
Of my AutoCAD API scripts which do complicated actions some have taken hundreds of hours of testing, often crashing C3D and often trying different order of actions, using different methods etc.
You will have to dig into the API docs and persevere
I know it may not provide solace to you at the moment, however we are able to do large process runs on DWGs for issue where we swap blocks, delete layouts, change text, embed images, zoom views, add XData etc. Unfortunately I can’t share those scripts.
@Mike.Buttery Do you think it would be easy to tweak the python script to work for the current file rather than a whole directory path?
You could work on the current file, however the strategy is slightly different as there is no side loading.
I would first try it with Dynamo nodes rather than python as I would expect that to be more stable
@Mike.Buttery
Interesting, so it would be advantageous to run this externally? I can tweak my workflow to do it that way. I feel like I am getting really close with some python scripts to get my ultimate goal of breaking out a master file of a bunch of layouts into separate .dwg’s (either single layout per .dwg or grouping layouts together into a single .dwg), but it seems to crash CAD on me once I get close. I am open to any ideas on how to accomplish this.