How to Duplicate a Layout in a Database

How to Duplicate a Layout in a Database

Poncho_Slim
Enthusiast Enthusiast
394 Views
3 Replies
Message 1 of 4

How to Duplicate a Layout in a Database

Poncho_Slim
Enthusiast
Enthusiast

I have attempted to Duplicate a Layout in a Database. I am unable to use a LayoutManager Object since I am trying to make changes to Documents (.dwg files) in the background to multiplle drawings in one sweep. The drawing has a layout with some viewports in it. A hard duplicate that LayoutManager.CopyLayout() worked great, but I realized that I need to be able to do this for drawings that are open in the background via accessing its Database, and since I dont have the drawing open, I wont be able to use LayoutManager.

 

Here is the current code I had:

private void CopyRebuildSheet()
        {
            Debug.Print("CopyRebuildSheet");
            string newLayoutName = "";
            foreach (DataGridViewRow Row in PlanSheetsAvailableTable.Rows)
            {
                DB_Sheet Sheet;
                Sheets.TryGetValue(Row.Cells[SheetNumColumnIndex].Value.ToString(), out Sheet);
                string FilePath = $"{Sheet.fullPath}\\{Sheet.fileName}";

                Database db = OpenDrawingFile(FilePath);
                using(Transaction tr = db.TransactionManager.StartTransaction())
                {
                    DBDictionary layoutDic = tr.GetObject(db.LayoutDictionaryId, OpenMode.ForWrite) as DBDictionary;
                    foreach(DBDictionaryEntry entry in layoutDic)
                    {
                        ObjectId layoutId = entry.Value;
                        Layout layout = tr.GetObject(layoutId, OpenMode.ForRead) as Layout;
                        if (layout.LayoutName == Row.Cells[SheetNumColumnIndex].Value.ToString())
                        {
                            // Here is an ERROR
                            LayoutManager layoutManager = ;
                            
                            //ObjectId newLayoutId = layoutManager.CreateLayout($"{layout.LayoutName} ({Row.Cells[RSNumColumnIndex].Value.ToString()})");
                            newLayoutName =$"{layout.LayoutName} ({Row.Cells[RSNumColumnIndex].Value})";
                            //Layout newLayout = tr.GetObject(newLayoutId, OpenMode.ForWrite) as Layout;
                            layoutManager.CloneLayout(layout.LayoutName, newLayoutName, layoutDic.Count);

                            if (RSSheetsToBeImportedIntoSheetSetManager.ContainsKey(Sheet.fileName))
                            {
                                RSSheetsToBeImportedIntoSheetSetManager[Sheet.fileName] += $"\n{newLayoutName}";
                            }
                            else
                            {
                                RSSheetsToBeImportedIntoSheetSetManager.Add(Sheet.fileName, newLayoutName);
                            }

                            tr.Commit();
                            break;
                        }
                    }
                }

                EnableTheTitleBlock(newLayoutName);
            }
        }


 

0 Likes
Accepted solutions (1)
395 Views
3 Replies
Replies (3)
Message 2 of 4

norman.yuan
Mentor
Mentor
Accepted solution

You need to set the side database to HostApplicationService.WorkingDatabase in order to use LayoutManager against this database. Also, you need to dispose the side database when you are done with it. Something like:

 

// save original working database

var originalDb=HostApplicationServices.WorkingDatabase;

foreach (.....)

{

  ...

  using (var db=OpenDrawingFile(...))

  {

     HostApplicationServices.WorkingDatabase=db;

     '' identify layout to copy

     '' using LayerManager to copy a layout here

     'db.SaveAs(...);

  }

}

// restore original working database

HostApplicationServices.WorkingDatabase = originalDb;

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 4

Poncho_Slim
Enthusiast
Enthusiast

This worked perfectly. Thank you for your solution. Here is the revised version:

        private void CopyRebuildSheet()
        {
            var originalDB = HostApplicationServices.WorkingDatabase;
            Debug.Print("CopyRebuildSheet");
            string newLayoutName = "";
            foreach (DataGridViewRow Row in PlanSheetsAvailableTable.Rows)
            {
                DB_Sheet Sheet;
                Sheets.TryGetValue(Row.Cells[SheetNumColumnIndex].Value.ToString(), out Sheet);
                string FilePath = $"{Sheet.fullPath}\\{Sheet.fileName}";

                
                using(var db = OpenDrawingFile(FilePath))
                {
                    HostApplicationServices.WorkingDatabase = db;

                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        DBDictionary layoutDic = tr.GetObject(db.LayoutDictionaryId, OpenMode.ForWrite) as DBDictionary;
                        foreach(DBDictionaryEntry entry in layoutDic)
                        {
                            ObjectId layoutId = entry.Value;
                            Layout layout = tr.GetObject(layoutId, OpenMode.ForRead) as Layout;
                            if (layout.LayoutName == Row.Cells[SheetNumColumnIndex].Value.ToString())
                            {
                                LayoutManager layoutManager = LayoutManager.Current;
                                newLayoutName =$"{layout.LayoutName} ({Row.Cells[RSNumColumnIndex].Value})";
                                layoutManager.CloneLayout(layout.LayoutName, newLayoutName, layoutDic.Count);

                                if (RSSheetsToBeImportedIntoSheetSetManager.ContainsKey(Sheet.fileName))
                                {
                                    RSSheetsToBeImportedIntoSheetSetManager[Sheet.fileName] += $"\n{newLayoutName}";
                                }
                                else
                                {
                                    RSSheetsToBeImportedIntoSheetSetManager.Add(Sheet.fileName, newLayoutName);
                                }
                                tr.Commit();
                                db.SaveAs(FilePath, DwgVersion.Current);

                                break;
                            }
                        }
                        HostApplicationServices.WorkingDatabase = originalDB;
                    }
                }

                EnableTheTitleBlock(newLayoutName);
            }
        }
0 Likes
Message 4 of 4

norman.yuan
Mentor
Mentor

I think it would be slightly better, or more logically, to place

HostApplicationServices.WorkingDatabase = originalDB;

outside the "foreach..." loop: you only need to restore it back after all the files are processed. It would be even better to do it like this way:

 

var originalDb=HostApplicationServices.WorkingDatabase;

try

{

    foreach (....)

    {

       .....

    }

}

finally

{

    // this restoration is guaranteed, even exception is raised in the processing loop

    HostApplicationServices.WorkingDatabase = origialDb;

}

Norman Yuan

Drive CAD With Code

EESignature

0 Likes