<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Existing Layout Names and Creating and Setting a New Layout in .NET Forum</title>
    <link>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8168739#M25179</link>
    <description>&lt;P&gt;The code needs to be in two separate transactions, then it works as expected. I tried it, but I had a transaction with the two transactions later, and then it also fails.&lt;/P&gt;</description>
    <pubDate>Tue, 31 Jul 2018 20:26:54 GMT</pubDate>
    <dc:creator>Civil3DReminders_com</dc:creator>
    <dc:date>2018-07-31T20:26:54Z</dc:date>
    <item>
      <title>Existing Layout Names and Creating and Setting a New Layout</title>
      <link>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8168698#M25178</link>
      <description>&lt;P&gt;I'm creating some layouts and viewports and the code works great, except I don't have a way to check if the existing layout name exists. So I created an extension method to get the list of existing layouts (below).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;public static List&amp;lt;string&amp;gt; GetLayoutNames(this Database db)
        {
            var existSheetNames = new List&amp;lt;string&amp;gt;();
            var layoutDict = db.LayoutDictionaryId.GetObject(OpenMode.ForRead) as DBDictionary;
            foreach (var layout in layoutDict)
            {
                existSheetNames.Add(layout.Key);
            }
            return existSheetNames;
        }&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Once I do that, then setting a layout returns an error "eSetFailed" with this code at the &lt;SPAN&gt;lm.CurrentLayout = name; line&lt;/SPAN&gt;:&lt;/P&gt;
&lt;PRE&gt;        public static ObjectId CreateAndMakeLayoutCurrent(LayoutManager lm, string name, bool select =true)
        {
            //try and get Layout
            ObjectId id = lm.GetLayoutId(name);
            try
            {
                if (!id.IsValid)
                {
                    id = lm.CreateLayout(name);
                }
                lm.CurrentLayout = name;                
            }
            catch(System.Exception ex)
            {
                Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n" + ex.Message);
            }
            return id;
        }&lt;/PRE&gt;
&lt;P&gt;I'm using a basic command method:&amp;nbsp;[CommandMethodAttribute("CtCreateLayoutsBySheets")]&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'm out of ideas. Any ideas?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 31 Jul 2018 20:09:55 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8168698#M25178</guid>
      <dc:creator>Civil3DReminders_com</dc:creator>
      <dc:date>2018-07-31T20:09:55Z</dc:date>
    </item>
    <item>
      <title>Re: Existing Layout Names and Creating and Setting a New Layout</title>
      <link>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8168739#M25179</link>
      <description>&lt;P&gt;The code needs to be in two separate transactions, then it works as expected. I tried it, but I had a transaction with the two transactions later, and then it also fails.&lt;/P&gt;</description>
      <pubDate>Tue, 31 Jul 2018 20:26:54 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8168739#M25179</guid>
      <dc:creator>Civil3DReminders_com</dc:creator>
      <dc:date>2018-07-31T20:26:54Z</dc:date>
    </item>
    <item>
      <title>Re: Existing Layout Names and Creating and Setting a New Layout</title>
      <link>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8169047#M25180</link>
      <description>&lt;P&gt;Two transactions, as in need to commit the first before the 2nd will work?&amp;nbsp; Or just run two transactions and commit both at end?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Just curious.&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/95076"&gt;@Civil3DReminders_com&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;&lt;P&gt;The code needs to be in two separate transactions, then it works as expected. I tried it, but I had a transaction with the two transactions later, and then it also fails.&lt;/P&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 31 Jul 2018 23:57:37 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8169047#M25180</guid>
      <dc:creator>brianchapmandesign</dc:creator>
      <dc:date>2018-07-31T23:57:37Z</dc:date>
    </item>
    <item>
      <title>Re: Existing Layout Names and Creating and Setting a New Layout</title>
      <link>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8169054#M25181</link>
      <description>&lt;P&gt;If the call to&amp;nbsp;&lt;SPAN&gt;existLayoutNames = db.GetLayoutNames();&lt;/SPAN&gt; is in the transaction that creates the layouts then it will fail. As done below with the two transaction doesn't error out.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;        public static bool CreateMultipleLayouts(List&amp;lt;ObjectId&amp;gt; sheetObjIdsToPlot)
        {
            bool created = false;
            Document Adoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Editor ed = Adoc.Editor;
            Database db = Adoc.Database;

            var layerStates = new List&amp;lt;LayerState&amp;gt;();

            var objIdsHidden = new List&amp;lt;ObjectId&amp;gt;();

            try
            {
                CollectLayersAndTurnOff(layerStates);
                var showPageSetupForNewLayouts = System.Convert.ToInt32(Application.GetSystemVariable("SHOWPAGESETUPFORNEWLAYOUTS"));

                if (showPageSetupForNewLayouts != 0)
                {
                    Application.SetSystemVariable("SHOWPAGESETUPFORNEWLAYOUTS", 0);
                }

                var existLayoutNames = new List&amp;lt;string&amp;gt;();

                using (var tr = db.TransactionManager.StartTransaction())
                {
                    existLayoutNames = db.GetLayoutNames();
                }
                
                using (Transaction ts = db.TransactionManager.StartTransaction())
                {
                    
                    objIdsHidden = db.HideAllObjects();

                    int counter = sheetObjIdsToPlot.Count;
                    
                    try
                    {
                        var modelSpaceScale = CtUtilities.GetModelSpaceScale();
                        var sheetInfos = new List&amp;lt;SheetInformation&amp;gt;();

                        // Collect the sheet info first, and then create them. 
                        // This way the scale stays the same and hopefully the layouts come out correct.
                        foreach (var sheetObjId in sheetObjIdsToPlot)
                        {
                            var sheet = sheetObjId.GetObject(OpenMode.ForRead) as Sheet;
                            Extents3d sheetExtents3d = sheet.GeometricExtents;
                            sheetExtents3d.TransformBy(ed.CurrentUserCoordinateSystem.Inverse());
                            
                            var sheetInfo = new SheetInformation()
                            {
                                LayoutName = ("CustomLayout_" + counter).CheckNameAndIncrement(existLayoutNames, false),
                                ModelSpaceMinPoint = sheetExtents3d.MinPoint,
                                ModelSpaceMaxPoint = sheetExtents3d.MaxPoint,
                                IsLandscape = sheet.IsLandscape()
                            };
                            sheetInfos.Add(sheetInfo);
                            counter--;
                        }

                        var currentSpace = LayoutManager.Current.CurrentLayout;

                        foreach (var sheetInfo in sheetInfos)
                        {
                            CreateViewPort(sheetInfo, modelSpaceScale);
                        }

                        LayoutManager.Current.CurrentLayout = currentSpace;
                    }
                    catch (System.Exception ex)
                    {
                        ed.WriteMessage("\nCreateMultipleLayouts1: " + ex.Message);
                    }
                    finally
                    {
                        if ((int)showPageSetupForNewLayouts != 0)
                        {
                            Application.SetSystemVariable("SHOWPAGESETUPFORNEWLAYOUTS", showPageSetupForNewLayouts);
                        }

                        db.ShowAllObjects(objIdsHidden);
                    }
                    ts.Commit();
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nCreateMultipleLayouts2: " + ex.Message);
            }
            finally
            {
                TurnOnLayers(layerStates);
            }
            
            return created;
        }&lt;/PRE&gt;</description>
      <pubDate>Wed, 01 Aug 2018 00:02:02 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8169054#M25181</guid>
      <dc:creator>Civil3DReminders_com</dc:creator>
      <dc:date>2018-08-01T00:02:02Z</dc:date>
    </item>
    <item>
      <title>Re: Existing Layout Names and Creating and Setting a New Layout</title>
      <link>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8170514#M25182</link>
      <description>&lt;P&gt;Well, in your original post you did not show exactly the command method that put the 2 code snippets together, wrapped in one transaction, that fails, as you claimed. The code in the your latest post you also did not show the situation of how the code fails. But I guessed I knew what you meant, so I went ahead for a test run with exactly with your 2 code snippets and put them in ONE TRANSACTION in a commandmethod, as following:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;public class OpenLayoutTest
    {
        [CommandMethod("CreateMyLayout")]

        public static void CreateLayouts()
        {
            var dwg = CadApp.DocumentManager.MdiActiveDocument;
            var ed = dwg.Editor;

            using (var tran = dwg.TransactionManager.StartTransaction())
            {
                var lNames = dwg.Database.GetLayoutNames();

                var newLayoutId = CreateAndMakeLayoutCurrent(
                    LayoutManager.Current, "New Layout");

                tran.Commit();
            }
        }

        public static ObjectId CreateAndMakeLayoutCurrent(
            LayoutManager lm, string name, bool select = true)
        {
            //try and get Layout
            ObjectId id = lm.GetLayoutId(name);
            try
            {
                if (!id.IsValid)
                {
                    id = lm.CreateLayout(name);
                }
                lm.CurrentLayout = name;
            }
            catch (System.Exception ex)
            {
                Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager
                    .MdiActiveDocument.Editor.WriteMessage("\n" + ex.Message);
            }
            return id;
        }

    }

    public static class DBExtensions
    {
        public static List&amp;lt;string&amp;gt; GetLayoutNames(this Database db)
        {
            var existSheetNames = new List&amp;lt;string&amp;gt;();
            var layoutDict = db.LayoutDictionaryId.GetObject(OpenMode.ForRead) as DBDictionary;
            foreach (var layout in layoutDict)
            {
                existSheetNames.Add(layout.Key);
            }
            return existSheetNames;
        }
    }&lt;/PRE&gt;
&lt;P&gt;As you can see, in the CommandMethod class, I simply wrapped your 2 pieces of code in a transaction. The code runs without error: the first&amp;nbsp;run creates a new layout ("New Layout"); the following run, make the "New Layout" current, if it wasn't. No error. I tested with Acad2018, but would not think it would be otherwise with 2017, 2019, or whatever Acad version.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So, since you did not show full code that led to error, I suspect there could be other reasons that causes error. For example, LayoutManager.Current.CurrentLayout = "xxxx" would raise exception if called in ApplicationContext without current document being locked.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;There are also a&amp;nbsp;few things:&lt;/P&gt;
&lt;P&gt;1. In your latest code, you have&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;                using (var tr = db.TransactionManager.StartTransaction())
                {
                    existLayoutNames = db.GetLayoutNames();
                }&lt;/PRE&gt;
&lt;P&gt;It is not a good practice to start a transaction (even for reading only) and not commit it.&lt;/P&gt;
&lt;P&gt;2. If you create an extension method to get data from whatever object (in your case, it is Database), it would be better to make it self-contained, and no dependency to outside environment. And if there is dependency, then you add argument to the method so that the dependency could be injected when the method is calling. Here I am talking about the need to using a Transaction to wrap your extension method call, which is not good design, IMO. you should:&lt;/P&gt;
&lt;PRE&gt;        public static List&amp;lt;string&amp;gt; GetLayoutNames(this Database db)
        {
            var existSheetNames = new List&amp;lt;string&amp;gt;();&lt;BR /&gt;            &lt;STRONG&gt;using (var tran = db.TransactionManager.StartTransaction())&lt;/STRONG&gt;&lt;BR /&gt;            {
                var layoutDict = db.LayoutDictionaryId.GetObject(OpenMode.ForRead) as DBDictionary;
                foreach (var layout in layoutDict)
                {
                    existSheetNames.Add(layout.Key);
                }&lt;BR /&gt;                tran.Commit();&lt;BR /&gt;            }
            return existSheetNames;
        }&lt;/PRE&gt;
&lt;P&gt;3. When&amp;nbsp;using LayoutManager, there is no need to wrap its method calls with Transaction, it methods internally starts transaction and commit it as needed&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;With the suggestion I made in 2 and 3, the command method I showed on top could be simplified to:&lt;/P&gt;
&lt;PRE&gt;[CommandMethod("CreateMyLayout")]

        public static void CreateLayouts()
        {
            var dwg = CadApp.DocumentManager.MdiActiveDocument;
            var ed = dwg.Editor;
            
            var lNames = dwg.Database.GetLayoutNames();
            var newLayoutId = CreateAndMakeLayoutCurrent(
                LayoutManager.Current, "New Layout");
        }&lt;/PRE&gt;
&lt;P&gt;That is, no need to wrap the Database extension method GetLayoutNames() and CreateAndMakeLayoutCurrent(). This, of course works with my test (Acad2018).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Again, I have no idea where the error you saw came from.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 01 Aug 2018 14:05:26 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8170514#M25182</guid>
      <dc:creator>norman.yuan</dc:creator>
      <dc:date>2018-08-01T14:05:26Z</dc:date>
    </item>
    <item>
      <title>Re: Existing Layout Names and Creating and Setting a New Layout</title>
      <link>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8170789#M25183</link>
      <description>&lt;P&gt;Thanks for looking at it Norman.&lt;/P&gt;</description>
      <pubDate>Wed, 01 Aug 2018 15:34:30 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/existing-layout-names-and-creating-and-setting-a-new-layout/m-p/8170789#M25183</guid>
      <dc:creator>Civil3DReminders_com</dc:creator>
      <dc:date>2018-08-01T15:34:30Z</dc:date>
    </item>
  </channel>
</rss>

