Hi …
This script is almost working. It repairs all broken referenced surfaces - or - will - when its working.
I need to find out why RepairBrokenDRef is not “happy”.
The code has a number “bad” areas and limits.
-
- Error catch is not present at all (yet).
-
- It assumes that user has activated the applicable Data Shortcut Project in the active C3D session.
-
- I haven’t found an “elegant” way to match Civil 3D types in the DWG DB with DataShortCutEntityTypes
import os
import sys
import clr
from System.IO import FileShare
from System import Enum
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AeccDbMgd')
#
clr.AddReference('AeccDataShortcutMgd')
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *
#
from Autodesk.Civil.DataShortcuts import *
from Autodesk.Civil.DataShortcuts import DataShortcutEntityType
fset = IN[0]
o = []
def dwgtask (path):
if not os.path.exists(path):
return False
adoc = Application.DocumentManager.MdiActiveDocument
HostApplicationServices.WorkingDatabase = adoc.Database
if adoc is None:
return False
with Database(False, True) as db:
db.ReadDwgFile(path, FileShare.ReadWrite, False, "")
cdoc = CivilDocument.GetCivilDocument(db)
sids = cdoc.GetSurfaceIds()
for id in sids:
with db.TransactionManager.StartTransaction() as t:
surf = t.GetObject(id,OpenMode.ForRead)
if surf.IsReferenceStale: # # # Broken Reference
etn = type(surf).__name__
for d in ds:
if d[1].upper().strip() in etn.upper().strip() and surf.Name.upper().strip() == d[2].upper().strip():
# RepairBrokenDRef(id,d[3])
o.append([path,etn,surf.Name,d[3]])
break
t.Commit()
db.CloseInput(True)
#db.SaveAs(path, DwgVersion.Current)
HostApplicationServices.WorkingDatabase = adoc.Database
return True
adoc = Application.DocumentManager.MdiActiveDocument
vals = DataShortcuts.CreateDataShortcutManager(True)
dsm = vals[0]
c = dsm.GetPublishedItemsCount()
ds = []
for i in range(c):
p = dsm.GetPublishedItemAt(i)
dsp = p.SourceLocation + "\\" + p.SourceFileName
if os.path.exists(dsp):
ds.append([ i , Enum.GetName(DataShortcutEntityType, p.DSEntityType), p.Name, dsp])
for f in fset:
if not os.path.exists(f):
[repair-references.dyn|attachment](upload://d4QbK7j3EovCKNRHC0mmVtRjIOU.dyn) (17.6 KB)
continue
dwgtask(f)
HostApplicationServices.WorkingDatabase = adoc.Database
OUT = [ds,o]
Oops! I almost posted this as repairing all broken References … you will notice that only the Surface ID collection is iterated at the moment … will add other object types later …
Oh No!!!The object is not open for Write … I missed that … was using Read for check purpose while devving…
Its Working!!! but still needs “attention” …
import os
import sys
import clr
from System.IO import FileShare
from System import Enum
from traceback import format_exc
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AeccDbMgd')
#
clr.AddReference('AeccDataShortcutMgd')
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *
#
from Autodesk.Civil.DataShortcuts import *
from Autodesk.Civil.DataShortcuts import DataShortcutEntityType
from Autodesk.Civil.DataShortcuts import DataShortcuts
fset = IN[0]
o = []
def dwgtask (path):
if not os.path.exists(path):
return False
adoc = Application.DocumentManager.MdiActiveDocument
HostApplicationServices.WorkingDatabase = adoc.Database
if adoc is None:
return False
with Database(False, True) as db:
db.ReadDwgFile(path, FileShare.ReadWrite, False, "")
cdoc = CivilDocument.GetCivilDocument(db)
sids = cdoc.GetSurfaceIds()
for id in sids:
with db.TransactionManager.StartTransaction() as t:
surf = t.GetObject(id,OpenMode.ForWrite)
if surf.IsReferenceStale: # # # Broken Reference
etn = type(surf).__name__
for d in ds:
if d[1].upper().strip() in etn.upper().strip() and surf.Name.upper().strip() == d[2].upper().strip():
try:
DataShortcuts.RepairBrokenDRef(id,d[3])
except:
o.append(format_exc())
break
try:
t.Commit()
except:
o.append(format_exc())
#db.CloseInput(True)
db.SaveAs(path, DwgVersion.Current)
HostApplicationServices.WorkingDatabase = adoc.Database
return True
adoc = Application.DocumentManager.MdiActiveDocument
vals = DataShortcuts.CreateDataShortcutManager(True)
dsm = vals[0]
c = dsm.GetPublishedItemsCount()
ds = []
for i in range(c):
p = dsm.GetPublishedItemAt(i)
dsp = p.SourceLocation + "\\" + p.SourceFileName
if os.path.exists(dsp):
ds.append([ i , Enum.GetName(DataShortcutEntityType, p.DSEntityType), p.Name, dsp])
for f in fset:
if not os.path.exists(f):
continue
dwgtask(f)
HostApplicationServices.WorkingDatabase = adoc.Database
OUT = [ds,o]
Hi Kevin,
Here are some notes on your code - I’m not at a workstation so they may not be 100% working
import os
import sys
from traceback import format_exc
import clr
from System import Enum
from System.IO import FileShare
clr.AddReference("AcMgd")
clr.AddReference("AcCoreMgd")
clr.AddReference("AcDbMgd")
clr.AddReference("AecBaseMgd")
clr.AddReference("AeccDbMgd")
clr.AddReference("AeccDataShortcutMgd")
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *
from Autodesk.AutoCAD.Runtime import *
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *
from Autodesk.Civil.DataShortcuts import *
## Following lines are not required as the classes/functions are already imported by *
# from Autodesk.Civil.DataShortcuts import DataShortcutEntityType
# from Autodesk.Civil.DataShortcuts import DataShortcuts
## Declare classes and functions before variables
# fset = IN[0]
# o = [] ## Using a global in function not best practice
def dwgtask(path, datashortcuts): # pass variables into functions better practice
if os.path.exists(path): # Use True here and the False will automatically return none
# return False
## This is not required - if this is executing in Civil3D & Dynamo
# adoc = Application.DocumentManager.MdiActiveDocument
# HostApplicationServices.WorkingDatabase = adoc.Database ## Not required - already true
# if adoc is None:
# return False
result = [path] # Collect info inside function and return
with Database(False, True) as db:
db.ReadDwgFile(path, FileShare.ReadWrite, False, "")
with db.TransactionManager.StartTransaction() as t: # wrap the whole operation in transaction
try: # Relocated to provide meaningful output from exception
cdoc = CivilDocument.GetCivilDocument(db)
sids = cdoc.GetSurfaceIds()
for id in sids:
surf = t.GetObject(id, OpenMode.ForWrite)
if surf.IsReferenceStale: # # # Broken Reference
etn = type(
surf
).__name__ # Alternatives? GetType(), get_Type(), ToString()?
for d in datashortcuts:
if ( ## A lot of string processing here - is it necessary?
d[1].upper().strip() in etn.upper().strip()
and surf.Name.upper().strip()
== d[2].upper().strip()
):
try:
DataShortcuts.RepairBrokenDRef(id, d[3])
result.append(True)
except:
result.append(format_exc())
break
# try: # To late to catch useful info - inserted at line 47
except:
result.append(format_exc())
t.Commit() # Commit as late as possible otherwise you may miss exceptions
db.SaveAs(path, DwgVersion.Current)
# HostApplicationServices.WorkingDatabase = adoc.Database ## Not required
return result
fset = IN[0]
# adoc = Application.DocumentManager.MdiActiveDocument ## Side loading - not required
vals = DataShortcuts.CreateDataShortcutManager(True) # Current application doc?
dsm = vals[0]
c = dsm.GetPublishedItemsCount()
ds = []
for i in range(c):
p = dsm.GetPublishedItemAt(i)
dsp = p.SourceLocation + "\\" + p.SourceFileName
if os.path.exists(dsp):
ds.append(
[i, Enum.GetName(DataShortcutEntityType, p.DSEntityType), p.Name, dsp]
)
output = []
for f in fset:
## Checked in function not required
# if not os.path.exists(f):
# continue
output.append(dwgtask(f, ds)) # Collect return from function
# HostApplicationServices.WorkingDatabase = adoc.Database ## Not required
## Does not need to be encapsulated as python will automatically cast to tuple
OUT = ds, output
1 Like