I have created a few sheets sets (dst files) and placed them in separate folders along with their accompanying dwg files. Currently, folder and file names are specific to each sheet set. For instance, I have a sheet set named abc.dst that resides in folder ...\acb\. In that folder I have the following drawing files: abc-1.dwg, acb-2.dwg and abc-3.dwg. These files contain the layouts that make up the sheets in the sheet set.
I now want to copy the sheet set dst file along with the associated dwg files into a new directory ...\xyz . I am able to do this and even rename the sheet set file to xyz.dst while keeping the copied dwg files connected the renamed sheet set. My problem is the drawing file names . I want to rename the xyz-1.dwg, xyz-2.dwg and xyz-3.dwg files and keep them connected without having to re-import into my sheet set. The sheets have been numbered and ordered in a such a way that it would create a great deal of effort if I had to go the re-import route.
Is there a way to change the underlying drawing file of any sheet in the sheet set?
Thanks,
Chris
Solved! Go to Solution.
Solved by khoa.ho. Go to Solution.
SheetSet Manager API is COM API which requires to reference AcSmComponents Type Library. Depend on AutoCAD version, you should reference the appropriate AcSmComponentsXX 1.0 Type Library, with XX is 18 or 19 or 20. SheetSet COM API looks strange comparing to normal AutoCAD .NET API.
The following code was tested to work on AutoCAD 2014, to change all drawing names containing "ABC" to "XYZ" on a given DST binary file.
using System; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; // SheetSet COM Reference: // *18 for AutoCAD 2010, 2011, 2012 // *19 for AutoCAD 2013, 2014 // *20 for AutoCAD 2015 using ACSMCOMPONENTS19Lib; [assembly: CommandClass(typeof(NetScript.Acad.Command))] namespace NetScript.Acad { public partial class Command { [CommandMethod("ChangeSheetSetSheet")] public static void ChangeSheetSetSheet() { string filePath = @"C:\Temp\SampleSheetSet.dst"; string oldName = "ABC"; string newName = "XYZ"; try { // Get the SheetSet Manager AcSmSheetSetMgr sheetSetManager = new AcSmSheetSetMgr(); // Create a new SheetSet Database AcSmDatabase sheetSetDb = new AcSmDatabase(); // Open DST file sheetSetDb = sheetSetManager.OpenDatabase(filePath, true); // Lock the db for processing sheetSetDb.LockDb(sheetSetDb); AcSmSheetSet sheetSet = sheetSetDb.GetSheetSet(); // Recursive method to change name ProcessEnumerator(sheetSet.GetSheetEnumerator(), oldName, newName); // Unlock the db after processing sheetSetDb.UnlockDb(sheetSetDb, true); sheetSetManager.Close(sheetSetDb); } catch (System.Exception ex) { } } private static void ProcessEnumerator(IAcSmEnumComponent component, string oldName, string newName) { IAcSmComponent item = component.Next(); while (item != null) { string type = item.GetTypeName(); switch (type) { case "AcSmSheet": try { AcSmSheet sheet = (AcSmSheet)item; AcSmAcDbLayoutReference layout = sheet.GetLayout(); string sheetName = sheet.GetName(); string fileName = layout.GetFileName(); string newSheetName = sheetName.Replace(oldName, newName); string newFileName = fileName.Replace(oldName, newName); // Update sheet name and file name sheet.SetTitle(newSheetName); layout.SetFileName(newFileName); if (!string.IsNullOrEmpty(sheetName)) { IAcSmEnumComponent enumerator = (IAcSmEnumComponent)sheet.GetSheetViews(); ProcessEnumerator(enumerator, oldName, newName); } } catch { } break; } item = component.Next(); } } } }
Credit to Kean's blog: http://through-the-interface.typepad.com/through_the_interface/2010/05/populating-a-tree-view-inside...
And Fenton's blog: http://adndevblog.typepad.com/autocad/2013/09/using-sheetset-manager-api-in-vbnet.html
Can you mark it as accepted solution please? Thanks. You can extend the code to change physical drawing file names together with drawing names in the sheet set.
Done. I am curious now about how to change the file names. I am doing it now in another part of the code with
IO.File.Copy but would like to see the method of which you speak.
Thanks,
Chris
Great! I knew the change file name code should be included for the complete solution. I am going to the meeting now and will be back in couple of hours.
Khoa
Here is the completed code. I made it more generic to further custom extensions. Please see Kean's post to add more code when needed.
I use a struct to pass an encapsulate object to the recursive method when navigating the sheet set. Use System.IO.File.Copy to copy files and System.IO.File.Move to rename files. The code can do direct renaming files or copy files to another location. See the comments for information.
// Credit to Kean Walmsley blog: http://through-the-interface.typepad.com/through_the_interface/2010/05/populating-a-tree-view-inside... // Credit to Fenton Webb blog: http://adndevblog.typepad.com/autocad/2013/09/using-sheetset-manager-api-in-vbnet.html // Written by Khoa Ho - www.NetOnApp.com using System; using System.IO; using System.Windows.Forms; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; // SheetSet COM Reference: // *18 for AutoCAD 2010, 2011, 2012 // *19 for AutoCAD 2013, 2014 // *20 for AutoCAD 2015 using ACSMCOMPONENTS19Lib; [assembly: CommandClass(typeof(NetScript.Acad.CodeLibrary.App.Command))] namespace NetScript.Acad.CodeLibrary.App { public partial class Command { [CommandMethod("ChangeSheetSetSheet")] public static void ChangeSheetSetSheet() { string sheetSetPath = @"C:\Temp\Old\NewSheetSet.dst"; string oldFileName = "ABC"; string newFileName = "XYZ"; string oldFolderName = @"C:\Temp\Old"; // Leave empty for current saved location string newFolderName = @"C:\Temp\New"; // Leave empty for rename files try { // Get the SheetSet Manager AcSmSheetSetMgr sheetSetManager = new AcSmSheetSetMgr(); // Create a new SheetSet Database AcSmDatabase sheetSetDb = new AcSmDatabase(); // Open DST file sheetSetDb = sheetSetManager.OpenDatabase(sheetSetPath, true); // Lock the db for processing sheetSetDb.LockDb(sheetSetDb); AcSmSheetSet sheetSet = sheetSetDb.GetSheetSet(); // Create a wrapper of all needed properties var componentInfo = new ComponentInfo { TreeNode = new TreeNode(sheetSet.GetName()), OldFileName = oldFileName, NewFileName = newFileName, OldFolderName = oldFolderName, NewFolderName = newFolderName }; // Recursive method to navigate sheet set ProcessEnumerator(sheetSet.GetSheetEnumerator(), componentInfo); // Unlock the db after processing, save it to the current file sheetSetDb.UnlockDb(sheetSetDb, true); sheetSetManager.Close(sheetSetDb); } catch (System.Exception ex) { } } private static void ProcessEnumerator(IAcSmEnumComponent component, ComponentInfo componentInfo) { IAcSmComponent item = component.Next(); while (item != null) { string type = item.GetTypeName(); switch (type) { case "AcSmSheet": try { AcSmSheet sheet = (AcSmSheet)item; string sheetName = sheet.GetName(); RenameSheets(sheet, componentInfo); if (!string.IsNullOrEmpty(sheetName)) { IAcSmEnumComponent enumerator = (IAcSmEnumComponent)sheet.GetSheetViews(); ProcessEnumerator(enumerator, componentInfo); } } catch { } break; case "AcSmSubset": break; case "AcSmSheetViews": break; case "AcSmSheetView": break; case "AcSmCustomPropertyValue": break; case "AcSmObjectReference": break; case "AcSmCustomPropertyBag": break; case "AcSmAcDbLayoutReference": break; case "AcSmFileReference": break; case "AcSmAcDbViewReference": break; case "AcSmResources": break; default: break; } item = component.Next(); } } private static void RenameSheets(AcSmSheet sheet, ComponentInfo componentInfo) { // Skip this method if there is no need to rename sheets if (string.IsNullOrEmpty(componentInfo.OldFileName) && string.IsNullOrEmpty(componentInfo.NewFileName)) { return; } try { string sheetName = sheet.GetName(); AcSmAcDbLayoutReference layout = sheet.GetLayout(); string filePath = layout.GetFileName(); string fileFolder = Directory.GetParent(filePath).FullName; string fileName = Path.GetFileName(filePath); string newSheetName = sheetName.Replace( componentInfo.OldFileName, componentInfo.NewFileName); string newFileName = fileName.Replace( componentInfo.OldFileName, componentInfo.NewFileName); //* Update sheet names and file names on DST file // Rename DWG files in the existing folder or copy them to the new folder if (!string.IsNullOrEmpty(componentInfo.OldFolderName) && !string.IsNullOrEmpty(componentInfo.NewFolderName)) { // Copy files from the old to new location string oldFilePath = Path.Combine(componentInfo.OldFolderName, fileName); string newFilePath = Path.Combine(componentInfo.NewFolderName, newFileName); if (File.Exists(oldFilePath)) { File.Copy(oldFilePath, newFilePath); // Copy physical file // Update sheet set layout.SetFileName(newFilePath); sheet.SetTitle(newSheetName); } } else if (string.IsNullOrEmpty(componentInfo.OldFolderName) && !string.IsNullOrEmpty(componentInfo.NewFolderName)) { // Copy files from the current to new location string currentFilePath = Path.Combine(fileFolder, fileName); string newFilePath = Path.Combine(componentInfo.NewFolderName, newFileName); if (File.Exists(currentFilePath)) { File.Copy(currentFilePath, newFilePath); // Copy physical file // Update sheet set layout.SetFileName(newFilePath); sheet.SetTitle(newSheetName); } } else if (string.IsNullOrEmpty(componentInfo.NewFolderName)) { // Rename files in the current location string currentFilePath = Path.Combine(fileFolder, fileName); string newFilePath = Path.Combine(fileFolder, newFileName); if (File.Exists(currentFilePath)) { File.Move(currentFilePath, newFilePath); // Update sheet set layout.SetFileName(newFilePath); sheet.SetTitle(newSheetName); } } } catch (System.Exception ex) { } } } internal struct ComponentInfo { public TreeNode TreeNode; public string OldFileName; public string NewFileName; public string OldFolderName; public string NewFolderName; } }
This is exactly what I need to do, how do I apply this coding to autocad 2018?
@michaelf1986 wrote:This is exactly what I need to do, how do I apply this coding to autocad 2018?
You have to compile the code into a .DLL using Visual Studio and then use the NETLOAD command to load and run it.