Author Topic: Importing a Layout from a Template  (Read 17625 times)

0 Members and 1 Guest are viewing this topic.

zoltan

  • Guest
Importing a Layout from a Template
« on: March 11, 2011, 11:40:50 AM »
I'm trying to copy a layout from a template drawing into the current drawing.

I have searched the forums and I followed this thread to this thread and I think I have an idea of what needs to happen.

1. Get the database from the template file.
2. Find the layout in the Layout Dictionary.
3. Get the Block Table Record for the layout's paperspace.
4. Clone the BTR and add it to the drawing's Block Table.
5. Clone the layout and add it to the Layout Dictionary with the new BTR.

When the drawing is regenerated, I see the new layout in the layout tabs, but AutoCAD crashes when I try to activate it.  In ArxDbg, I can see the new block table record in the block table and the new layout in the layout dictionary, but it crashes when I try to view the items.

I think I am missing something BIG!  Does anyone have a working solution for this?

AutoCAD 2011

Microsoft Visual Studio 2008
Version 9.0.30729.1 SP

Microsoft .NET Framework
Version 3.5 SP1

Windows XP Pro SP3

Code: [Select]
        /// <summary>
        /// Imports a Layout from a template
        /// </summary>
        /// <param name="path">
        /// The path to the template file including the extension
        /// </param>
        /// <param name="name">
        /// The name of the layout to import.
        /// </param>
        public static void ImportLayout(string path, string name)
        {
            // the destination document and database
            Document dstDocument = Application.DocumentManager.MdiActiveDocument;
            Database dstDatabase = dstDocument.Database;
            Editor dstEditor = dstDocument.Editor;

            // get the sourse database from the template file
            Database srcDatabase = new Database(false, true);
            srcDatabase.ReadDwgFile(path, FileOpenMode.OpenForReadAndReadShare, false, null);

            using (Transaction srcTrans = srcDatabase.TransactionManager.StartTransaction())
            {

                DBDictionary srcLayoutDictionary = (DBDictionary)srcTrans.GetObject(srcDatabase.LayoutDictionaryId, OpenMode.ForRead);

                // go through the layout dictionary to find the layout that matches the name.
                foreach (DictionaryEntry layout in srcLayoutDictionary)
                {
                    if (layout.Key.ToString() == name)
                    {
                        ObjectId srcLayoutId = (ObjectId)layout.Value;
                        Layout srcLayout = (Layout)srcTrans.GetObject(srcLayoutId, OpenMode.ForRead);

                        // the block table record for the layout.
                        ObjectId srcLayoutBtr = srcLayout.BlockTableRecordId;

                        // clone the layout's block table record.
                        IdMapping btrMapping = new IdMapping();
                        dstDatabase.WblockCloneObjects(new ObjectIdCollection(new ObjectId[] { srcLayoutBtr }), dstDatabase.BlockTableId, btrMapping, DuplicateRecordCloning.Replace, false);

                        // find the ObjectId of the new block table record.
                        ObjectId dstLayoutBtr = ObjectId.Null;
                        foreach (IdPair pair in btrMapping)
                        {
                            ObjectId key = pair.Key;

                            if (ObjectId.Equals(key, srcLayoutBtr))
                            {
                                dstLayoutBtr = pair.Value;
                            }
                        }

                        // clone the layout.
                        IdMapping layoutMapping = new IdMapping();
                        dstDatabase.WblockCloneObjects(new ObjectIdCollection(new ObjectId[] { srcLayoutId }), dstDatabase.LayoutDictionaryId, layoutMapping, DuplicateRecordCloning.Replace, false);

                        // find the ObjectId of the new layout.
                        foreach (IdPair pair in layoutMapping)
                        {
                            ObjectId key = pair.Key;

                            if (ObjectId.Equals(key, srcLayoutId))
                            {

                                ObjectId dstLayoutId = pair.Value;

                                using (Transaction dstTrans = dstDatabase.TransactionManager.StartTransaction())
                                {
                                    Layout dstLayout = (Layout)dstTrans.GetObject(dstLayoutId, OpenMode.ForWrite);

                                    // add the new layout to the Layout Dictionary.
                                    dstLayout.AddToLayoutDictionary(dstDatabase, dstLayoutBtr);

                                    dstTrans.Commit();
                                }
                            }
                        }
                    }
                }

                srcTrans.Commit();
            }

            // regenerate the drawing.
            dstEditor.Regen();
        }

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Importing a Layout from a Template
« Reply #1 on: March 11, 2011, 03:27:06 PM »
This worked for me.  I tried other ways, but couldn't get them to work correctly, as they would fatally error, and crash acad with and ' ePermanetlyErased ' error.

Code: [Select]
    public void Main ()
    {
    Document toDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument as Document;
    using( DocumentLock toLock = toDoc.LockDocument() ) {
    Database toDb = toDoc.Database as Database;
   
    string Path = @"c:/test/blank.dwg";
    string LoName = "test";
   
    Document fromDoc;
    Database fromDb = MyUtility.GetDatabaseAtPath( Path, toDb, FileOpenMode.OpenForReadAndAllShare, FindFileHint.Default, out fromDoc );
    using( Transaction toTrans = toDb.TransactionManager.StartTransaction() ) {
    using( Transaction fromTrans = fromDb.TransactionManager.StartTransaction() ) {
    DBDictionary fromLoDict = fromTrans.GetObject( fromDb.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
    ObjectIdCollection IdCol = new ObjectIdCollection();
    foreach ( DBDictionaryEntry de in fromLoDict ) {
    if ( de.Key != LoName ) continue;
    IdCol.Add( de.Value );
    }
    fromDb.WblockCloneObjects( IdCol, toDb.LayoutDictionaryId, new IdMapping(), DuplicateRecordCloning.Ignore, false );
    }
    toTrans.Commit();
    }
    fromDb.Dispose();
    }
    }

Code: [Select]
public static Database GetDatabaseAtPath ( string path, Database db, Autodesk.AutoCAD.DatabaseServices.FileOpenMode openMode, FindFileHint findOpt, out Document doc )
{
// If doc != null, then the calling function must lock the document passed out.
// Also, the calling function must NOT set the HostApplication.WorkingDatabase to the
// database returned.
//
// If doc == null, then the calling function must dispose of the database returned.
// Also, the calling function must set the HostApplication.WorkingDatabase to the
// database returned, if working with text or attributes.
//
// If null is returned, then the drawing is read-only to the calling program, and the
// calling program wants to make changes to the database.

doc = GetDocumentFrom( AcadApp.DocumentManager, path );
if ( doc != null ) return doc.Database;
if (
openMode == FileOpenMode.OpenForReadAndReadShare
&&
( ( File.GetAttributes ( path ) & FileAttributes.ReadOnly ) == FileAttributes.ReadOnly )
)
return null;
string FoundAtPath = HostApplicationServices.Current.FindFile( path, db, findOpt );
if ( string.IsNullOrEmpty( FoundAtPath ) ) return null;
Database Db = new Database( false, true );
Db.ReadDwgFile( FoundAtPath, openMode, true, null );
return Db;
}
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

zoltan

  • Guest
Re: Importing a Layout from a Template
« Reply #2 on: March 11, 2011, 04:21:58 PM »
WOW!

I guess I wasn't missing something, I was OVER COMPLICATING things!

So it makes sense that since the dictionary holds a pointer to the Block Table Record, cloning the dictionary will clone the BTR also.

What is the Layout.AddToLayoutDictionary supposed to be used for?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Importing a Layout from a Template
« Reply #3 on: March 11, 2011, 04:32:08 PM »
I'm not sure.  I was trying to use the ' WBlockClone ' method, but can't seem to get that to work, so I went this way and it worked.  I'm still trying some things, as this will copy straight, and I think the other way, one could copy and then rename the layout before adding it completely.  If that makes sense.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Importing a Layout from a Template
« Reply #4 on: March 11, 2011, 05:41:15 PM »
Also
You can create a new layout with the layermanger then use the CopyFrom() method but still need to add viewports objects etc.. wil post a example.

I believe since layouts do ont derive from the entity class is why wblockclone causes problems

Here is a similiar one that uses CopyFrom for PlotSettings
http://www.theswamp.org/index.php?topic=31867.msg398478#msg398478

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Importing a Layout from a Template
« Reply #5 on: March 11, 2011, 06:31:01 PM »
Also
You can create a new layout with the layermanger then use the CopyFrom() method but still need to add viewports objects etc.. wil post a example.

Layouts have an Initialize method, that should take care of some of the issues with making a new Layout.


I believe since layouts do ont derive from the entity class is why wblockclone causes problems

You wouldn't think so, as the WblockClone is a method of the DBObject class, and Layout inherits from that, but I can't get it to work at all.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Importing a Layout from a Template
« Reply #6 on: March 11, 2011, 07:56:04 PM »
I believe since layouts do ont derive from the entity class is why wblockclone causes problems

You wouldn't think so, as the WblockClone is a method of the DBObject class, and Layout inherits from that, but I can't get it to work at all.

Sorry,
Way off there  was going off memory which I should not do.



Code: [Select]
   [CommandMethod("CopyLayout")]
            public void CopyLayout()
            {
                string layoutName = "Test";
                string fileName = @"C:\Users\Jeff\Desktop\Temp\Test\LayoutTest.dwt";


                Database templateDb = new Database(false, true) as Database;
                templateDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, "");

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

                LayoutManager layoutManager = LayoutManager.Current;

                using (Transaction trx = db.TransactionManager.StartTransaction())
                using (Transaction templateTrx = templateDb.TransactionManager.StartTransaction())           
                {   
                    DBDictionary layoutDictionary = trx.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;


                    if (layoutDictionary.Contains(layoutName))
                    {
                        ed.WriteMessage("\nThis Layout is already in drawing.");
                        return;
                    }

                    DBDictionary templateLayoutDictionary = templateTrx.GetObject(templateDb.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
                   
                    if (!(templateLayoutDictionary.Contains(layoutName)))
                    {
                        ed.WriteMessage("\nTemplate does not contain a Layout with that name.");
                        return;
                    }
                 
                        ObjectId newLayoutId = layoutManager.CreateLayout(layoutName);
                        Layout newLayout = trx.GetObject(newLayoutId, OpenMode.ForWrite) as Layout;

                        Layout templateLayout = templateLayoutDictionary.GetAt(layoutName).GetObject(OpenMode.ForWrite) as Layout;
                        newLayout.CopyFrom(templateLayout);
                                       
                        BlockTableRecord templateLayoutBtr = templateTrx.GetObject(templateLayout.BlockTableRecordId, OpenMode.ForRead) as BlockTableRecord;

                        ObjectIdCollection objIdColl = new ObjectIdCollection();
                        foreach (ObjectId id in templateLayoutBtr)
                        {
                            objIdColl.Add(id);
                        }

                        BlockTable extBt = templateDb.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
                        IdMapping map = new IdMapping();
                        db.WblockCloneObjects(objIdColl, newLayout.BlockTableRecordId, map, DuplicateRecordCloning.Replace, false);

                        newLayout.Initialize();           
                   
                    templateTrx.Commit();
                    trx.Commit();                   
                }
                layoutManager.CurrentLayout = layoutName;
            }

*******Edit******
Removed NOT operator @   if (layoutDictionary.Contains(layoutName))
« Last Edit: March 11, 2011, 09:36:48 PM by Jeff H »

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Importing a Layout from a Template
« Reply #7 on: March 11, 2011, 08:20:50 PM »
Layouts have an Initialize method, that should take care of some of the issues with making a new Layout.

The documentation does not specify, but when you use LayoutManager to create a layout it asscioates it with a BlockTableRecord.
There is Layout.AddToLayoutDictionary, but have not messed with it. I guess you would have to create a new Btr yourself?

kaefer

  • Guest
Re: Importing a Layout from a Template
« Reply #8 on: March 14, 2011, 06:20:34 AM »
Code: [Select]
    [CommandMethod("CopyLayout")]
        ....
        Database templateDb = new Database(false, true) as Database;

Looks good, works great, but shouldn't you dispose the side database when you're done with it?

Regards

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Importing a Layout from a Template
« Reply #9 on: March 14, 2011, 05:39:27 PM »
Looks like you have the right idea Jeff.  Here is a different version.  One that doesn't use the layout manager, so in theory, it can be changed easily to work with a drawing open by it's database only.

Code: [Select]
    [CommandMethod("testcopylayout", CommandFlags.Session)]
    public void Main ()
    {
    Document toDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument as Document;
    using( DocumentLock toLock = toDoc.LockDocument() ) {
    Database toDb = toDoc.Database as Database;
   
    string Path = @"c:/test/blank.dwg";
    string LoName = "test";
   
    string BlkName = "*Paper_Space";
    int LoCnt = 0;
   
    Document fromDoc;
    Database fromDb = MyUtility.GetDatabaseAtPath( Path, toDb, FileOpenMode.OpenForReadAndAllShare, FindFileHint.Default, out fromDoc );
    using( Transaction toTrans = toDb.TransactionManager.StartTransaction() ) {
    using( Transaction fromTrans = fromDb.TransactionManager.StartTransaction() ) {
    DBDictionary fromLoDict = fromTrans.GetObject( fromDb.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
    ObjectIdCollection IdCol = new ObjectIdCollection();
    foreach ( DBDictionaryEntry de in fromLoDict ) {
    if ( de.Key != LoName ) continue;
    Layout fromLo = fromTrans.GetObject( de.Value, OpenMode.ForRead ) as Layout;
    BlockTableRecord fromBtr = fromTrans.GetObject( fromLo.BlockTableRecordId, OpenMode.ForRead ) as BlockTableRecord;
    foreach ( ObjectId id in fromBtr ) { IdCol.Add( id ); }
   
    BlockTable toBt = toTrans.GetObject( toDb.BlockTableId, OpenMode.ForWrite ) as BlockTable;
    while ( toBt.Has( BlkName + LoCnt ) ) LoCnt++;
    Layout toLo = new Layout();
    toLo.CopyFrom( fromLo );
    toLo.LayoutName = fromLo.LayoutName;
    DBDictionary toLoDict = toTrans.GetObject( toDb.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
    if ( toLoDict.Contains( toLo.LayoutName ) ) {
    PromptResult pr;
    do {
    pr = toDoc.Editor.GetString( "\n Layout name exists already, enter new name: " );
    if ( pr.Status == PromptStatus.Cancel ) return;
    } while ( string.IsNullOrEmpty( pr.StringResult ) || toLoDict.Contains( pr.StringResult ) );
    toLo.LayoutName = pr.StringResult;
    }
    BlockTableRecord toBtr = new BlockTableRecord();
    toBtr.Name = BlkName + LoCnt;
    toBt.Add( toBtr );
    toTrans.AddNewlyCreatedDBObject( toBtr, true );
    fromDb.WblockCloneObjects( IdCol, toBtr.ObjectId, new IdMapping(), DuplicateRecordCloning.Ignore, false );
    toLo.AddToLayoutDictionary( toDb, toBtr.ObjectId );
    toTrans.AddNewlyCreatedDBObject( toLo, true );
    }
    }
    toTrans.Commit();
    }
    fromDb.Dispose();
    }
    }
    }
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Importing a Layout from a Template
« Reply #10 on: March 14, 2011, 11:07:41 PM »

Looks good, works great, but shouldn't you dispose the side database when you're done with it?

Regards

Yes sir,
thanks for catching that.

Looks like you have the right idea Jeff.  Here is a different version.  One that doesn't use the layout manager, so in theory, it can be changed easily to work with a drawing open by it's database only.

Nice you figured out how to use AddToLayoutDictionary().
Thanks for the good pointers.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Importing a Layout from a Template
« Reply #11 on: March 15, 2011, 11:09:20 AM »
It felt so good to be doing something in C# again I couldn't quit.   :lmao:

Code: [Select]
    public bool AddLayoutToDatabase ( Database db, string name, string templatePath, string templateLoName )
    {
    string BlkName = "*Paper_Space";
    int LoCnt = 0;
   
    using ( Transaction Trans = db.TransactionManager.StartTransaction() ) {
    DBDictionary LoDict = Trans.GetObject( db.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
    if ( LoDict.Contains( name ) ) return false;
   
    Document fromDoc;
    DocumentLock fromDocLock = null;
    Database fromDb = MyUtility.GetDatabaseAtPath( templatePath, HostApplicationServices.WorkingDatabase, FileOpenMode.OpenForReadAndAllShare, FindFileHint.Default, out fromDoc );
    if ( fromDb == null ) return false;
if ( fromDoc != null ) fromDocLock = fromDoc.LockDocument();
    using ( Transaction fromTrans = fromDb.TransactionManager.StartTransaction() ) {
    DBDictionary fromLoDict = fromTrans.GetObject( fromDb.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
    Layout fromLo = null;
    foreach ( DBDictionaryEntry de in fromLoDict ) {
    if ( de.Key == templateLoName ) fromLo = fromTrans.GetObject( de.Value, OpenMode.ForRead ) as Layout;
    if ( fromLo != null ) break;
    }
    if ( fromLo == null ) {
    if ( fromDocLock != null ) fromDocLock.Dispose();
    else fromDb.Dispose();
    return false;
    }
    ObjectIdCollection IdCol = new ObjectIdCollection();
    BlockTableRecord fromBtr = fromTrans.GetObject( fromLo.BlockTableRecordId, OpenMode.ForRead ) as BlockTableRecord;
    foreach ( ObjectId id in fromBtr ) { IdCol.Add( id ); }
   
    BlockTable Bt = Trans.GetObject( db.BlockTableId, OpenMode.ForWrite ) as BlockTable;
    while ( Bt.Has( BlkName + LoCnt ) ) LoCnt++;
    Layout Lo = new Layout();
    Lo.LayoutName = name;
    Lo.CopyFrom( fromLo );
    BlockTableRecord Btr = new BlockTableRecord();
    Btr.Name = BlkName + LoCnt;
    Bt.Add( Btr );
    Trans.AddNewlyCreatedDBObject( Btr, true );
    fromDb.WblockCloneObjects( IdCol, Btr.ObjectId, new IdMapping(), DuplicateRecordCloning.Ignore, false );
    Lo.AddToLayoutDictionary( db, Btr.ObjectId );
    Trans.AddNewlyCreatedDBObject( Lo, true );
    }
    Trans.Commit();
    if ( fromDocLock != null ) fromDocLock.Dispose();
    else fromDb.Dispose();
    }
    return true;
    }
   
    public bool AddLayoutToDatabase ( Database db, string templatePath, string templateLoName )
    {
    string BlkName = "*Paper_Space";
    int LoCnt = 0;
   
    using ( Transaction Trans = db.TransactionManager.StartTransaction() ) {
    DBDictionary LoDict = Trans.GetObject( db.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
    if ( LoDict.Contains( templateLoName ) ) return false;
   
    Document fromDoc;
    DocumentLock fromDocLock = null;
    Database fromDb = MyUtility.GetDatabaseAtPath( templatePath, HostApplicationServices.WorkingDatabase, FileOpenMode.OpenForReadAndAllShare, FindFileHint.Default, out fromDoc );
    if ( fromDb == null ) return false;
if ( fromDoc != null ) fromDocLock = fromDoc.LockDocument();
    using ( Transaction fromTrans = fromDb.TransactionManager.StartTransaction() ) {
    DBDictionary fromLoDict = fromTrans.GetObject( fromDb.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
    Layout fromLo = null;
    foreach ( DBDictionaryEntry de in fromLoDict ) {
    if ( de.Key == templateLoName ) fromLo = fromTrans.GetObject( de.Value, OpenMode.ForRead ) as Layout;
    if ( fromLo != null ) break;
    }
    if ( fromLo == null ) {
    if ( fromDocLock != null ) fromDocLock.Dispose();
    else fromDb.Dispose();
    return false;
    }
    ObjectIdCollection IdCol = new ObjectIdCollection();
    BlockTableRecord fromBtr = fromTrans.GetObject( fromLo.BlockTableRecordId, OpenMode.ForRead ) as BlockTableRecord;
    foreach ( ObjectId id in fromBtr ) { IdCol.Add( id ); }
   
    BlockTable Bt = Trans.GetObject( db.BlockTableId, OpenMode.ForWrite ) as BlockTable;
    while ( Bt.Has( BlkName + LoCnt ) ) LoCnt++;
    Layout Lo = new Layout();
    Lo.LayoutName = templateLoName;
    Lo.CopyFrom( fromLo );
    BlockTableRecord Btr = new BlockTableRecord();
    Btr.Name = BlkName + LoCnt;
    Bt.Add( Btr );
    Trans.AddNewlyCreatedDBObject( Btr, true );
    fromDb.WblockCloneObjects( IdCol, Btr.ObjectId, new IdMapping(), DuplicateRecordCloning.Ignore, false );
    Lo.AddToLayoutDictionary( db, Btr.ObjectId );
    Trans.AddNewlyCreatedDBObject( Lo, true );
    }
    Trans.Commit();
    if ( fromDocLock != null ) fromDocLock.Dispose();
    else fromDb.Dispose();
    }
    return true;
    }
   
    public bool AddLayoutToDatabase ( Database db, string name )
    {
    string BlkName = "*Paper_Space";
    int LoCnt = 0;
   
    using ( Transaction Trans = db.TransactionManager.StartTransaction() ) {
    DBDictionary LoDict = Trans.GetObject( db.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
    if ( LoDict.Contains( name ) ) return false;
BlockTable Bt = Trans.GetObject( db.BlockTableId, OpenMode.ForWrite ) as BlockTable;
while ( Bt.Has( BlkName + LoCnt ) ) LoCnt++;
Layout Lo = new Layout();
Lo.LayoutName = name;
BlockTableRecord Btr = new BlockTableRecord();
Btr.Name = BlkName + LoCnt;
Bt.Add( Btr );
Trans.AddNewlyCreatedDBObject( Btr, true );
Lo.AddToLayoutDictionary( db, Btr.ObjectId );
Lo.Initialize();
Trans.AddNewlyCreatedDBObject( Lo, true );
    Trans.Commit();
    }
    return true;
    }

Code: [Select]
    [CommandMethod("testcopylayout", CommandFlags.Session)]
    public void Main ()
    {
    Document Doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument as Document;
    Database Db = Doc.Database;
    Editor Ed = Doc.Editor;
    using( DocumentLock DocLock = Doc.LockDocument() ) {
    AddLayoutToDatabase( Db, "test1", @"c:/test/blank.dwg", "test" );
    AddLayoutToDatabase( Db, @"c:/test/blank.dwg", "test" );
    AddLayoutToDatabase( Db, "test2" );
    }
    }
   
    [CommandMethod("testcopylayout1", CommandFlags.Session)]
    public void Main1 ()
    {
    Document Doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument as Document;
    using( DocumentLock DocLock = Doc.LockDocument() ) {
    using ( Database Db = new Database( true, false ) ) {
    AddLayoutToDatabase( Db, "test1", @"c:/test/blank.dwg", "test" );
    AddLayoutToDatabase( Db, @"c:/test/blank.dwg", "test" );
    AddLayoutToDatabase( Db, "test2" );
    Db.SaveAs( @"c:/test/createlayout.dwg", DwgVersion.Current );
    }
    }
    }

Code: [Select]
public static Database GetDatabaseAtPath ( string path, Database db, Autodesk.AutoCAD.DatabaseServices.FileOpenMode openMode, FindFileHint findOpt, out Document doc )
{
// If doc != null, then the calling function must lock the document passed out.
// Also, the calling function must NOT set the HostApplication.WorkingDatabase to the
// database returned.
//
// If doc == null, then the calling function must dispose of the database returned.
// Also, the calling function must set the HostApplication.WorkingDatabase to the
// database returned, if working with text or attributes.
//
// If null is returned, then the drawing is read-only to the calling program, and the
// calling program wants to make changes to the database.

doc = GetDocumentFrom( AcadApp.DocumentManager, path );
if ( doc != null ) return doc.Database;
if (
openMode == FileOpenMode.OpenForReadAndReadShare
&&
( ( File.GetAttributes ( path ) & FileAttributes.ReadOnly ) == FileAttributes.ReadOnly )
)
return null;
string FoundAtPath = HostApplicationServices.Current.FindFile( path, db, findOpt );
if ( string.IsNullOrEmpty( FoundAtPath ) ) return null;
Database Db = new Database( false, true );
Db.ReadDwgFile( FoundAtPath, openMode, true, null );
return Db;
}
}
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

zoltan

  • Guest
Re: Importing a Layout from a Template
« Reply #12 on: March 18, 2011, 12:17:28 PM »
Thanks Willey,

That looks great!!

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Importing a Layout from a Template
« Reply #13 on: March 18, 2011, 01:06:32 PM »
You're welcome Zoltan.  Glad it works for you.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

dull_blades

  • Guest
Re: Importing a Layout from a Template
« Reply #14 on: January 16, 2012, 05:38:17 PM »
Hi folks!

Sorry to dredge up an old thread.  I am creating new layouts (by importing from a template) just as the OP is doing.  This thread has helped tremendously.

Unfortunately I am seeing some issues that I wanted to investigate.

I originally started my own routine by piecing together a bunch of samples I found on the internet. I was able to get my routine to work, but with a few issues.  So I did some searching and found this thread. 

After implementing the solution by Jeff above (Reply #6), I am seeing the same issues as I have when using my code.  Basically, the code works great on an empty drawing file (new file).  But if, I run Jeff's solution (or mine) on a drawing containing modelspace drawing content, existing layouts, viewports, etc... the newly added layout acts as if it has not been initialized.  Once I switch to a different layout, back to the newly created layout and run a zoom extents on the layout, everything looks correct.

Am I missing something that was not discussed in this thread?  Has anyone else experienced this behaviour?

Thanks!