.NET

Reply
Contributor
s.jabs
Posts: 12
Registered: ‎08-15-2007
Message 1 of 17 (1,581 Views)

Erasing Layouts

1581 Views, 16 Replies
04-19-2010 09:42 AM
Does anyone have an example of how to properly remove a layout? I'm writing a routine to strip down drawings to an optimized (and standardized) format, but I'm having trouble with this one bit of code:

{code}

Protected Friend Shared Sub RemoveLayouts(ByVal dbAcad As Database)
Dim edCmdLine As Editor = AcApp.Application.DocumentManager.MdiActiveDocument.Editor
Dim alLayouts As ArrayList = New ArrayList()
Dim lmAcad As LayoutManager = LayoutManager.Current
Dim oiTemp As ObjectId

Try
' Create empty layout to satisfy one minimum layout requirement
oiTemp = lmAcad.CreateLayout("Some-Random-Name")

Using trAcad As Transaction = dbAcad.TransactionManager.StartTransaction()
Dim deItem As DictionaryEntry
Dim dicLayouts As DBDictionary = DirectCast(trAcad.GetObject(dbAcad.LayoutDictionaryId, OpenMode.ForRead), DBDictionary)
Dim intI As Integer
Dim lItem As Layout
Dim oiBlock As ObjectId
Dim oicViewports As ObjectIdCollection
Dim vItem As Viewport

' Get the list of layouts
For Each deItem In dicLayouts
alLayouts.Add(DirectCast(trAcad.GetObject(CType(deItem.Value, ObjectId), OpenMode.ForRead), Layout).LayoutName)
Next

' Cycle through the layouts, deleting all but model space and one layout
For intI = 0 To alLayouts.Count - 1
If alLayouts(intI) <> "Model" And alLayouts(intI) <> "Some-Random-Name" Then
Try
lItem = DirectCast(trAcad.GetObject(lmAcad.GetLayoutId(alLayouts(intI)), OpenMode.ForWrite), Layout)
oiBlock = lItem.BlockTableRecordId

' Deals with viewports
oicViewports = lItem.GetViewports()
For Each oiViewport In oicViewports
vItem = DirectCast(trAcad.GetObject(oiViewport, OpenMode.ForWrite), Viewport)
vItem.Erase()
Next

lmAcad.DeleteLayout(lItem.LayoutName)
Catch ex As Exception
End Try
End If
Next

trAcad.Commit()
End Using

Using trAcad As Transaction = dbAcad.TransactionManager.StartTransaction()
Dim lItem As Layout

lItem = DirectCast(trAcad.GetObject(oiTemp, OpenMode.ForWrite), Layout)
lItem.Initialize()
lItem.LayoutName = "Layout1"

trAcad.Commit()
End Using
Catch ex As Exception
End Try
End Sub
{code}

If I don't remove the viewports "manually", I get drawing corruption. If the layout to be removed contains a block with attribute definitions, that too causes corruption. If I get the BlockTableRecord from the layout, and erase it instead, I don't get corruption, but the drawing crashes when I switch layout tabs.
New Member
boylek
Posts: 1
Registered: ‎02-13-2011
Message 2 of 17 (1,446 Views)

Re: Erasing Layouts

04-14-2011 07:13 PM in reply to: s.jabs

i'm trying to deal with the same thing....in C#

not much luck yet....

Distinguished Contributor
Artvegas
Posts: 104
Registered: ‎04-21-2011
Message 3 of 17 (1,356 Views)

Re: Erasing Layouts

09-22-2011 02:32 AM in reply to: boylek

To erase a layout you can use the current LayoutManager's DeleteLayout() method. It will safely delete a layout including all contents.

 

Best of all, if you use this to erase the last remaining paper space layout, a new default paper space layout will automatically be generated by AutoCAD.

 

Note: If you try and delete the Model layout an exception will be thrown.

 

Here is a C# sample to erase all paper space layouts...

 

[CommandMethod("EraseAllLayouts")]
public static void EraseAllLayouts() {

   Document doc = Application.DocumentManager.MdiActiveDocument;
   Database db = doc.Database;
   Editor ed = doc.Editor;

   using (Transaction tr = db.TransactionManager.StartTransaction()) {

      // ACAD_LAYOUT dictionary.
      DBDictionary layoutDict = tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;

      // Iterate dictionary entries.
      foreach (DBDictionaryEntry de in layoutDict) {
         string layoutName = de.Key;
         if (layoutName != "Model") {
            LayoutManager.Current.DeleteLayout(layoutName); // Delete layout.
         }
      }
   }

   ed.Regen();   // Updates AutoCAD GUI to relect changes.
}

 

Hope this helps.

 

Art

Valued Mentor
fieldguy
Posts: 376
Registered: ‎03-31-2005
Message 4 of 17 (1,339 Views)

Re: Erasing Layouts

09-22-2011 08:42 AM in reply to: s.jabs

Be careful with dictionary entries.  I got caught doing the same thing.

 

You are using Dim deItem As DictionaryEntry to iterate through a DBDicitionary.  You should use Dim deItem As DBDictionaryEntry.

 

I got diffrerent results when I made that change. 

Distinguished Contributor
Dale.Bartlett
Posts: 148
Registered: ‎01-06-2003
Message 5 of 17 (1,246 Views)

Re: Erasing Layouts

04-09-2012 11:23 PM in reply to: s.jabs

This is a great example, thanks. I am finding that the drawing regens throughout the process with "Regenerating model - caching viewports". Regenauto doesn't affect. Does anyone have a way to prevent the screen flashing etc? Also, sometimes the new default layout is the next number, ie "Layout 10". I haven't been able to resolve these small niggles but am really appreciative of the sample. Regards, Dale

Distinguished Contributor
Dale.Bartlett
Posts: 148
Registered: ‎01-06-2003
Message 6 of 17 (1,235 Views)

Re: Erasing Layouts

04-10-2012 01:05 AM in reply to: s.jabs

Update: I had already removed the ed.Regen() line. Dale

Distinguished Contributor
Artvegas
Posts: 104
Registered: ‎04-21-2011
Message 7 of 17 (1,221 Views)

Re: Erasing Layouts

04-10-2012 10:05 AM in reply to: Dale.Bartlett

Hi Dale,

 

The command line output can be temporarily suppressed by setting the NOMUTT system variable. A word of caution though, this can get a little complicated. You need to watch out for happens if the user enters UNDO. You don't want to accidentally leave the user with NOMUTT set to 1 (i.e. if exception is thrown). Refer to the following links for details on this:

http://through-the-interface.typepad.com/through_the_interface/2008/09/no-muttering-at.html

http://through-the-interface.typepad.com/through_the_interface/2008/09/more-quiet-comm.html

 

I think the flashing is caused because this is what happens if you were to do this manually in the AutoCAD UI, it just happens fast. You could set the current layout to model space first, i.e.:

   LayoutManager.Current.CurrentLayout = "Model";

 

See what you mean by it being named "Layout10". Seems to happens when you are replacing a Layout1. Only thing I can think of is to manually rename it to whatever you want using the RenameLayout() method, i.e.:

   DBDictionary layoutDict = tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
   if (layoutDict.Count == 1)
   {
      foreach (DBDictionaryEntry de in layoutDict)
      {
         string layoutName = de.Key;
         if (layoutName != "Model")
         {
            LayoutManager.Current.RenameLayout(layoutName, "NewLayoutName");
         }
      }
   }

 

Hope this helps,
Art

Valued Contributor
andred
Posts: 89
Registered: ‎10-17-2003
Message 8 of 17 (1,083 Views)

Re: Erasing Layouts

08-28-2012 06:21 PM in reply to: Artvegas

Thank you ArtVegas, discussion groups are really valuable.

 

I had this code to erase a layout:

 

    Private Function DeleteLayout(ByVal LayoutNameToDelete As String) As Boolean
        Dim bReturnValue As Boolean = True
        Dim oLayoutIDToRename As ObjectId = Nothing
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor()
        Dim Db As Database = ed.Document.Database()
        Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument

        oLayoutIDToRename = GetLayoutByName(LayoutNameToDelete)
        Try
            Using doclock As DocumentLock = acDoc.LockDocument
                Using tm1 As Transaction = Db.TransactionManager.StartTransaction()
                    Dim oLayoutToRename As Layout = tm1.GetObject(oLayoutIDToRename, OpenMode.ForWrite)
                    oLayoutToRename.Erase()
                    tm1.Commit()
                    oLayoutToRename = Nothing
                End Using
            End Using
            'Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.Regen()
        Catch ex As Exception
            ed.WriteMessage("\nImpossible de supprimer la présentation " & LayoutNameToDelete & ": " & ex.Message)
            bReturnValue = False
        End Try

       Return bReturnValue

    End Function

 

Here the function GetLayoutByName:

Public Function GetLayoutByName(ByVal layoutName As String) As ObjectId

        Dim oReturnValue As ObjectId = Nothing
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor()
        Dim CurrentDb As Database = ed.Document.Database()

        Try
            ''Create a variable to store the list oflayout identifiers
            Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = CurrentDb.TransactionManager
            Using myT As Transaction = tm.StartTransaction
                ''Open the layout dictionary
                Dim layoutDic As DBDictionary = myT.GetObject(CurrentDb.LayoutDictionaryId, OpenMode.ForRead, False)

                '' Check each layout in the layout table
                Dim Entry As DBDictionaryEntry = Nothing
                For Each Entry In layoutDic
                    Dim layoutId As ObjectId = Entry.Value
                    Dim objLayout As Layout = myT.GetObject(layoutId, OpenMode.ForRead, False)

                    If objLayout.LayoutName.ToUpper = layoutName.ToUpper Then
                        oReturnValue = objLayout.ObjectId
                    End If
                Next
                myT.Commit()
            End Using

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            oReturnValue = Nothing
        End Try

        Return oReturnValue

    End Function

 

The layout is deleted but AutoCAD become unstable. When I close AutoCAD, it freeze. I don't know why. Now I replace my function by yours (converted in VB .Net and 3 modifications) and it works perfectly.

 

        Dim bReturnValue As Boolean = True
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor()
        Dim Db As Database = ed.Document.Database()
        Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument

        Try
            Using doclock As DocumentLock = acDoc.LockDocument
                Using tr As Transaction = Db.TransactionManager.StartTransaction

                    'ACAD_LAYOUT dictionary.
                    Dim layoutDict As DBDictionary = tr.GetObject(Db.LayoutDictionaryId, OpenMode.ForWrite)

                    'Iterate dictionary entries.
                    For Each de As DBDictionaryEntry In layoutDict
                        Dim layoutName As String = de.Key
                        If layoutName.ToUpper = LayoutNameToDelete.ToUpper Then
                            LayoutManager.Current.DeleteLayout(LayoutNameToDelete)
                        End If

                    Next
                    tr.Commit()
                    ed.Regen()
                End Using
            End Using
        Catch ex As Exception
            ed.WriteMessage("\nImpossible de supprimer la présentation " & LayoutNameToDelete & ": " & ex.Message)
            bReturnValue = False
        End Try

        Return bReturnValue

    End Function

I had to make three adjustements. First I replace the openmode to ForWrite and second commit the transaction. Third I also have to lock the document. All the transaction is embed in  a try statement for more security.

 

Hope this help for vb programmer.

 

Regards,

 

André

 

Valued Contributor
andred
Posts: 89
Registered: ‎10-17-2003
Message 9 of 17 (1,066 Views)

Re: Erasing Layouts

08-30-2012 06:21 AM in reply to: Artvegas

Hi ArtVegas,

 

I have a question for you. I have a routine to rename a layout and now a good routine to delete layout. I want to rename a layout sequence order. I already have a routine inserting a layout (ex. insert layout 003, the existing layout 003 is rename to 004 and all subsequent layout). My problem is when I delete a layout. I want to do the same thing in reverse order (ex. delete layout 003, renaming layout 004 to 003, etc.).

 

When I delete layout, i'm using LayoutToBeRemoved to do some processing when I delete a layout, but when I want to rename a layout I have an error saying "Layout already exist". It is ok, because at this event occurs the layout is not deleted. I tried the same thing with LayoutRemoved event, but I have the same problem. But at this stage the layout is supposed to be removed.

 

Do you have any idea?

 

Regards,

 

André

 

Distinguished Contributor
Artvegas
Posts: 104
Registered: ‎04-21-2011
Message 10 of 17 (1,050 Views)

Re: Erasing Layouts

08-31-2012 05:08 AM in reply to: andred

Hi Andre, I'm not exactly sure what you are trying to do. But it sounds as if AutoCAD is complaining that you are trying to rename a layout to a name that is already being used by another layout, which you wouldn't want to do. Perhaps if you post some simple code that shows the problem I'd get a better understanding and might be able to help.

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.