Search code examples
.netautocad-plugin

How do I limit this list to only paper space layouts in AutoCAD?


Here is a simple command to display a list of layouts in the command line window:

public void TestVP()
{
    try
    {
        _AcAp.Document acDoc = _AcAp.Application.DocumentManager.MdiActiveDocument;
        _AcDb.Database acCurDb = acDoc.Database;

        _AcEd.Editor editor = _AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
        using (_AcDb.Transaction acTrans = _AcDb.HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
        {
            _AcDb.BlockTable acBlkTbl;
            acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, _AcDb.OpenMode.ForRead) as _AcDb.BlockTable;

            foreach(_AcDb.ObjectId id in acBlkTbl)
            {
                _AcDb.BlockTableRecord btRecord = (_AcDb.BlockTableRecord)acTrans.GetObject(id, _AcDb.OpenMode.ForRead);
                if(btRecord.IsLayout)
                {
                    _AcDb.Layout acLayout = (_AcDb.Layout)acTrans.GetObject(btRecord.LayoutId, _AcDb.OpenMode.ForRead);
                    editor.WriteMessage(acLayout.LayoutName + "\n");
                }
            }

            acTrans.Commit();
        }
    }
    catch (System.Exception ex)
    {
        _AcAp.Application.ShowAlertDialog(
            string.Format("\nError: {0}\nStacktrace: {1}", ex.Message, ex.StackTrace));
    }
}

At the moment it also includes the Model layout. I don't want it to. How do I limit the list of layouts to paper space layouts?


Even when I do it using the LayoutManager like this:

using (_AcDb.Transaction acTrans = _AcDb.HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
{
    _AcDb.DBDictionary layoutDic = acTrans.GetObject(acCurDb.LayoutDictionaryId, _AcDb.OpenMode.ForRead) as _AcDb.DBDictionary;
    foreach(_AcDb.DBDictionaryEntry entry in layoutDic)
    {
        _AcDb.ObjectId layoutId = entry.Value;
        _AcDb.Layout layout = acTrans.GetObject(layoutId, _AcDb.OpenMode.ForRead) as _AcDb.Layout;
        editor.WriteMessage(String.Format("{0}--> {1}", Environment.NewLine, layout.LayoutName));
    }

    acTrans.Commit();
}

I still end up with:

Active Layout is : Model Number of Layouts is : 3
--> Layout1
--> Layout2
--> Model

I don't want to test against the layout name of "Model".


Solution

  • This is what I came up with:

    public void TestVP()
    {
        try
        {
            _AcAp.Document acDoc = _AcAp.Application.DocumentManager.MdiActiveDocument;
            _AcDb.Database acCurDb = acDoc.Database;
            _AcEd.Editor editor = _AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
            _AcDb.LayoutManager layoutMgr = _AcDb.LayoutManager.Current;
    
            editor.WriteMessage(String.Format("{0}Active Layout is : {1}", Environment.NewLine, layoutMgr.CurrentLayout));
            editor.WriteMessage(String.Format("{0}Number of Layouts is : {1}", Environment.NewLine, layoutMgr.LayoutCount));
    
            using (_AcDb.Transaction acTrans = _AcDb.HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
            {
                _AcDb.BlockTable bt = acCurDb.BlockTableId.GetObject(_AcDb.OpenMode.ForRead) as _AcDb.BlockTable;
                _AcDb.BlockTableRecord ms = acTrans.GetObject(bt[_AcDb.BlockTableRecord.ModelSpace], _AcDb.OpenMode.ForRead) as _AcDb.BlockTableRecord;
                _AcDb.DBDictionary layoutDic = acTrans.GetObject(acCurDb.LayoutDictionaryId, _AcDb.OpenMode.ForRead) as _AcDb.DBDictionary;
                foreach(_AcDb.DBDictionaryEntry entry in layoutDic)
                {
                    _AcDb.ObjectId layoutId = entry.Value;
                    _AcDb.Layout layout = acTrans.GetObject(layoutId, _AcDb.OpenMode.ForRead) as _AcDb.Layout;
                    editor.WriteMessage(String.Format("{0}--> {1}", Environment.NewLine, layout.LayoutName));
    
                    _AcDb.BlockTableRecord layoutBlkTbl = acTrans.GetObject(layout.BlockTableRecordId, _AcDb.OpenMode.ForRead) as _AcDb.BlockTableRecord;
                    if(layoutBlkTbl.Id != ms.Id)
                        editor.WriteMessage(" (PaperSpace)");
                    
                }
    
                acTrans.Commit();
            }
        }
        catch (System.Exception ex)
        {
            _AcAp.Application.ShowAlertDialog(
                string.Format("\nError: {0}\nStacktrace: {1}", ex.Message, ex.StackTrace));
        }
    }
    

    The output I get is:

    Active Layout is : Model
    Number of Layouts is : 3
    --> Layout1 (PaperSpace)
    --> Layout2 (PaperSpace)
    --> Model
    

    I simply compare the Id of the Layout against that for the Model Space object Id. There might be a simpler way. But atleast I can now limit my list to just paper space layouts.