I have written the following C# code that takes user input of an integer, then plots views in sheets corresponding to polyines in the model space on different layers. For example in the attached file when 3 is input, then 3 views are inserted on sheet 1, sheet 2, and sheet 3. I have the viewports inserting correctly per the code, but when I un-comment the vp.on line I get the error: Autodesk.AutoCAD.Runtime.Exception: 'eNotInPaperspace'. But in the drawing I can easily turn these views on no problem, any ideas here?
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
namespace AutoCADExtents
{
public class Commands
{
[CommandMethod("POLYEXTENTS")]
public void GetPolylineExtents()
{
// Get the current document and database
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// Start a transaction
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// Open the Block table for read
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// Get the active document and editor
Editor ed = doc.Editor;
// Prompt user for the number of layers/views
PromptIntegerOptions numLayersPromptOptions = new PromptIntegerOptions("\nEnter number of layers/views to create: ");
numLayersPromptOptions.AllowNegative = false;
numLayersPromptOptions.AllowZero = false;
PromptIntegerResult numLayersPromptResult = ed.GetInteger(numLayersPromptOptions);
if (numLayersPromptResult.Status != PromptStatus.OK)
{
ed.WriteMessage("\nInvalid input or user cancelled.");
return;
}
int numLayers = numLayersPromptResult.Value;
// Open the LayoutManager
LayoutManager layoutManager = LayoutManager.Current;
for (int i = 1; i <= numLayers; i++)
{
string sheetName = "Sheet " + i;
// Get or create the layout
Layout layout = tr.GetObject(layoutManager.GetLayoutId(sheetName), OpenMode.ForWrite) as Layout;
// Create or get the first viewport in the layout
Viewport vp = GetOrCreateViewport(tr, layout);
// Set the viewport properties based on overall extents and layout size
SetViewportProperties(tr, layout, vp, bt, ed, i);
// Inform user
ed.WriteMessage($"\nViewport created and adjusted successfully in '{sheetName}'.");
}
tr.Commit(); // Commit the transaction
}
}
private Viewport GetOrCreateViewport(Transaction tr, Layout layout)
{
Viewport vp = null;
// Open the BlockTableRecord for layout
BlockTableRecord layoutRecord = tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite) as BlockTableRecord;
// Remove existing viewport if any
foreach (ObjectId objId in layoutRecord)
{
if (objId.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Viewport))))
{
vp = tr.GetObject(objId, OpenMode.ForWrite) as Viewport;
if (vp != null)
{
vp.Erase();
break;
}
}
}
// Create a new viewport
vp = new Viewport();
layoutRecord.AppendEntity(vp);
tr.AddNewlyCreatedDBObject(vp, true);
return vp;
}
private void SetViewportProperties(Transaction tr, Layout layout, Viewport vp, BlockTable bt, Editor ed, int layerNumber)
{
// Get the overall extents of the entities in model space for the specified layer number
Extents3d overallExtents = GetOverallExtents(tr, bt, layerNumber);
// Check if valid extents were found
if (overallExtents.MinPoint != Point3d.Origin && overallExtents.MaxPoint != Point3d.Origin)
{
// Calculate the center of the extents in model space
Point3d centerPointModelSpace = overallExtents.MinPoint + ((overallExtents.MaxPoint - overallExtents.MinPoint) / 2.0);
// Calculate the layout dimensions in inches (convert mm to inches)
double layoutWidth = 20.3867;
double layoutLength = 25.2982;
// Determine scale factors based on layout dimensions
double scaleHeight = layoutWidth / (overallExtents.MaxPoint.Y - overallExtents.MinPoint.Y);
double scaleWidth = layoutLength / (overallExtents.MaxPoint.X - overallExtents.MinPoint.X);
// Choose the smaller scale factor to fit either width or height
double scaleFactor = Math.Min(scaleHeight, scaleWidth);
// Set the viewport center in paper space
vp.CenterPoint = new Point3d(13.3056, 13.3432, 0.0);
// Set the viewport size based on scale factor
vp.Height = (overallExtents.MaxPoint.Y - overallExtents.MinPoint.Y) * scaleFactor;
vp.Width = (overallExtents.MaxPoint.X - overallExtents.MinPoint.X) * scaleFactor;
// Set the view center in model space
vp.ViewCenter = new Point2d(centerPointModelSpace.X, centerPointModelSpace.Y);
// Set the view scale (optional)
vp.CustomScale = scaleFactor;
//vp.On = true;
}
else
{
// No valid extents found
ed.WriteMessage($"\nNo valid extents found for Layer {layerNumber}. Viewport not adjusted.");
}
}
private Extents3d GetOverallExtents(Transaction tr, BlockTable bt, int layerNumber)
{
// Initialize extents
Extents3d overallExtents = new Extents3d();
// Open the Block table record Model space for read
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
// Iterate through the entities in Model space
foreach (ObjectId objId in btr)
{
Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity;
// Check if the entity is a Polyline and on the specified layer
if (ent != null && ent is Polyline && ent.Layer == $"{layerNumber}")
{
Polyline pline = (Polyline)ent;
// Get the extents of the polyline
Extents3d extents = pline.GeometricExtents;
// Extend overall extents
overallExtents.AddExtents(extents);
}
}
return overallExtents;
}
}
}
Also tried to write a second code that turns on all vp's but this also returned the same error.
Solved! Go to Solution.
Solved by carl3ZPF6. Go to Solution.
Hi,
Each layout has its own viewport which is not a floating viewport and must not be erased. The Number property of this viewport is always 1, so, you should replace:
if (vp != null)
{
vp.Erase();
break;
}
with:
if (vp != null && vp.Number != 1)
{
vp.Erase();
break;
}
@_gileThis is my best attempt:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
namespace AutoCADExtents
{
public class Commands
{
[CommandMethod("POLYEXTENTS")]
public void GetPolylineExtents()
{
// Get the current document and database
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// Start a transaction
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// Open the Block table for read
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// Get the active document and editor
Editor ed = doc.Editor;
// Prompt user for the number of layers/views
PromptIntegerOptions numLayersPromptOptions = new PromptIntegerOptions("\nEnter number of layers/views to create: ");
numLayersPromptOptions.AllowNegative = false;
numLayersPromptOptions.AllowZero = false;
PromptIntegerResult numLayersPromptResult = ed.GetInteger(numLayersPromptOptions);
if (numLayersPromptResult.Status != PromptStatus.OK)
{
ed.WriteMessage("\nInvalid input or user cancelled.");
return;
}
int numLayers = numLayersPromptResult.Value;
// Open the LayoutManager
LayoutManager layoutManager = LayoutManager.Current;
for (int i = 1; i <= numLayers; i++)
{
string sheetName = "Sheet " + i;
// Get or create the layout
Layout layout = tr.GetObject(layoutManager.GetLayoutId(sheetName), OpenMode.ForWrite) as Layout;
// Create or get the first viewport in the layout
Viewport vp = GetOrCreateViewport(tr, layout);
// Set the viewport properties based on overall extents and layout size
SetViewportProperties(tr, layout, vp, bt, ed, i, sheetName);
// Inform user
ed.WriteMessage($"\nViewport created and adjusted successfully in '{sheetName}'.");
}
tr.Commit(); // Commit the transaction
}
}
private Viewport GetOrCreateViewport(Transaction tr, Layout layout)
{
Viewport vp = null;
// Open the BlockTableRecord for layout
BlockTableRecord layoutRecord = tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite) as BlockTableRecord;
// Check if a viewport already exists
foreach (ObjectId objId in layoutRecord)
{
if (objId.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Viewport))))
{
vp = tr.GetObject(objId, OpenMode.ForWrite) as Viewport;
if (vp != null)
{
// If viewport exists and is not the first viewport (optional condition), erase it
if (vp.Number != 1)
{
vp.Erase();
vp = null; // Set vp to null to create a new one
break;
}
}
}
}
// If no valid viewport found, create a new one
if (vp == null)
{
vp = new Viewport();
layoutRecord.AppendEntity(vp);
tr.AddNewlyCreatedDBObject(vp, true);
}
return vp;
}
private void SetViewportProperties(Transaction tr, Layout layout, Viewport vp, BlockTable bt, Editor ed, int layerNumber, string sheetName)
{
// Get the overall extents of the entities in model space for the specified layer number
Extents3d overallExtents = GetOverallExtents(tr, bt, layerNumber);
// Check if valid extents were found
if (overallExtents.MinPoint != Point3d.Origin && overallExtents.MaxPoint != Point3d.Origin)
{
// Calculate the center of the extents in model space
Point3d centerPointModelSpace = overallExtents.MinPoint + ((overallExtents.MaxPoint - overallExtents.MinPoint) / 2.0);
// Calculate the layout dimensions in inches (convert mm to inches)
double layoutWidth = 20.3867;
double layoutLength = 25.2982;
// Determine scale factors based on layout dimensions
double scaleHeight = layoutWidth / (overallExtents.MaxPoint.Y - overallExtents.MinPoint.Y);
double scaleWidth = layoutLength / (overallExtents.MaxPoint.X - overallExtents.MinPoint.X);
// Choose the smaller scale factor to fit either width or height
double scaleFactor = Math.Min(scaleHeight, scaleWidth);
// Set the viewport center in paper space
vp.CenterPoint = new Point3d(13.3056, 13.3432, 0.0);
// Set the viewport size based on scale factor
vp.Height = (overallExtents.MaxPoint.Y - overallExtents.MinPoint.Y) * scaleFactor;
vp.Width = (overallExtents.MaxPoint.X - overallExtents.MinPoint.X) * scaleFactor;
// Set the view center in model space
vp.ViewCenter = new Point2d(centerPointModelSpace.X, centerPointModelSpace.Y);
// Set the view scale (optional)
vp.CustomScale = scaleFactor;
// Inform user
ed.WriteMessage($"\nViewport properties set for '{sheetName}'.");
// Ensure that the layout switch happens after viewport properties are set
SetCurrentLayoutTab(sheetName);
}
else
{
// No valid extents found
ed.WriteMessage($"\nNo valid extents found for Layer {layerNumber}. Viewport not adjusted.");
}
}
private Extents3d GetOverallExtents(Transaction tr, BlockTable bt, int layerNumber)
{
// Initialize extents
Extents3d overallExtents = new Extents3d();
// Open the Block table record Model space for read
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
// Iterate through the entities in Model space
foreach (ObjectId objId in btr)
{
Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity;
// Check if the entity is a Polyline and on the specified layer
if (ent != null && ent is Polyline && ent.Layer == $"{layerNumber}")
{
Polyline pline = (Polyline)ent;
// Get the extents of the polyline
Extents3d extents = pline.GeometricExtents;
// Extend overall extents
overallExtents.AddExtents(extents);
}
}
return overallExtents;
}
public static void SetCurrentLayoutTab(string tab)
{
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
using (DocumentLock lk = acDoc.LockDocument())
{
// Start a separate transaction for setting the current layout
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
try
{
LayoutManager.Current.CurrentLayout = tab;
acTrans.Commit();
}
catch
{
acTrans.Abort();
}
}
}
}
}
}
This runs fine with user input 1 and 2, but crashes with user input 3, which is even weirder than the original behavior
I would try to set the layout current before doing anything:
// Open the LayoutManager
LayoutManager layoutManager = LayoutManager.Current;
for (int i = 1; i <= numLayers; i++)
{
string sheetName = "Sheet " + i;
layoutManager.CurrentLayout = sheetName
// Get or create the layout
Layout layout = tr.GetObject(layoutManager.GetLayoutId(sheetName), OpenMode.ForWrite) as Layout;
// Create or get the first viewport in the layout
Viewport vp = GetOrCreateViewport(tr, layout);
// Set the viewport properties based on overall extents and layout size
SetViewportProperties(tr, layout, vp, bt, ed, i, sheetName);
// Inform user
ed.WriteMessage($"\nViewport created and adjusted successfully in '{sheetName}'.");
}
In your SetCurrentLayoutTab() method, there is no need to lock the document, nor start a Transaction.
Norman Yuan
@norman.yuansee my code below, this results in no output, messages in the editor say views were added and adjusted but there is nothing:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
namespace AutoCADExtents
{
public class Commands
{
[CommandMethod("POLYEXTENTS")]
public void GetPolylineExtents()
{
// Get the current document and database
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// Start a transaction
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// Open the Block table for read
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// Get the active document and editor
Editor ed = doc.Editor;
// Prompt user for the number of layers/views
PromptIntegerOptions numLayersPromptOptions = new PromptIntegerOptions("\nEnter number of layers/views to create: ");
numLayersPromptOptions.AllowNegative = false;
numLayersPromptOptions.AllowZero = false;
PromptIntegerResult numLayersPromptResult = ed.GetInteger(numLayersPromptOptions);
if (numLayersPromptResult.Status != PromptStatus.OK)
{
ed.WriteMessage("\nInvalid input or user cancelled.");
return;
}
int numLayers = numLayersPromptResult.Value;
// Open the LayoutManager
LayoutManager layoutManager = LayoutManager.Current;
for (int i = 1; i <= numLayers; i++)
{
string sheetName = "Sheet " + i;
layoutManager.CurrentLayout = sheetName;
// Get or create the layout
Layout layout = tr.GetObject(layoutManager.GetLayoutId(sheetName), OpenMode.ForWrite) as Layout;
// Create or get the first viewport in the layout
Viewport vp = GetOrCreateViewport(tr, layout);
// Set the viewport properties based on overall extents and layout size
SetViewportProperties(tr, layout, vp, bt, ed, i, sheetName);
vp.On = true;
// Inform user
ed.WriteMessage($"\nViewport created and adjusted successfully in '{sheetName}'.");
}
tr.Commit(); // Commit the transaction
}
}
private Viewport GetOrCreateViewport(Transaction tr, Layout layout)
{
Viewport vp = null;
// Open the BlockTableRecord for layout
BlockTableRecord layoutRecord = tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite) as BlockTableRecord;
// Check if a viewport already exists
foreach (ObjectId objId in layoutRecord)
{
if (objId.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Viewport))))
{
vp = tr.GetObject(objId, OpenMode.ForWrite) as Viewport;
if (vp != null)
{
// If viewport exists and is not the first viewport (optional condition), erase it
if (vp.Number != 1)
{
vp.Erase();
vp = null; // Set vp to null to create a new one
break;
}
}
}
}
// If no valid viewport found, create a new one
if (vp == null)
{
vp = new Viewport();
layoutRecord.AppendEntity(vp);
tr.AddNewlyCreatedDBObject(vp, true);
}
return vp;
}
private void SetViewportProperties(Transaction tr, Layout layout, Viewport vp, BlockTable bt, Editor ed, int layerNumber, string sheetName)
{
// Get the overall extents of the entities in model space for the specified layer number
Extents3d overallExtents = GetOverallExtents(tr, bt, layerNumber);
// Check if valid extents were found
if (overallExtents.MinPoint != Point3d.Origin && overallExtents.MaxPoint != Point3d.Origin)
{
// Calculate the center of the extents in model space
Point3d centerPointModelSpace = overallExtents.MinPoint + ((overallExtents.MaxPoint - overallExtents.MinPoint) / 2.0);
// Calculate the layout dimensions in inches (convert mm to inches)
double layoutWidth = 20.3867;
double layoutLength = 25.2982;
// Determine scale factors based on layout dimensions
double scaleHeight = layoutWidth / (overallExtents.MaxPoint.Y - overallExtents.MinPoint.Y);
double scaleWidth = layoutLength / (overallExtents.MaxPoint.X - overallExtents.MinPoint.X);
// Choose the smaller scale factor to fit either width or height
double scaleFactor = Math.Min(scaleHeight, scaleWidth);
// Set the viewport center in paper space
vp.CenterPoint = new Point3d(13.3056, 13.3432, 0.0);
// Set the viewport size based on scale factor
vp.Height = (overallExtents.MaxPoint.Y - overallExtents.MinPoint.Y) * scaleFactor;
vp.Width = (overallExtents.MaxPoint.X - overallExtents.MinPoint.X) * scaleFactor;
// Set the view center in model space
vp.ViewCenter = new Point2d(centerPointModelSpace.X, centerPointModelSpace.Y);
// Set the view scale (optional)
vp.CustomScale = scaleFactor;
// Inform user
ed.WriteMessage($"\nViewport properties set for '{sheetName}'.");
// Ensure that the layout switch happens after viewport properties are set
}
else
{
// No valid extents found
ed.WriteMessage($"\nNo valid extents found for Layer {layerNumber}. Viewport not adjusted.");
}
}
private Extents3d GetOverallExtents(Transaction tr, BlockTable bt, int layerNumber)
{
// Initialize extents
Extents3d overallExtents = new Extents3d();
// Open the Block table record Model space for read
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
// Iterate through the entities in Model space
foreach (ObjectId objId in btr)
{
Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity;
// Check if the entity is a Polyline and on the specified layer
if (ent != null && ent is Polyline && ent.Layer == $"{layerNumber}")
{
Polyline pline = (Polyline)ent;
// Get the extents of the polyline
Extents3d extents = pline.GeometricExtents;
// Extend overall extents
overallExtents.AddExtents(extents);
}
}
return overallExtents;
}
}
}
@norman.yuan @_gile After some playing around I was able to fix this with a separate function, see below. Not sure why I couldnt do this in the loop.
public void TurnOnAllViewports()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// Get the layout dictionary
DBDictionary layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
foreach (DBDictionaryEntry layoutEntry in layoutDict)
{
// Get each layout
Layout layout = (Layout)tr.GetObject(layoutEntry.Value, OpenMode.ForRead);
// Skip the Model layout
if (layout.LayoutName == "Model")
continue;
// Switch to the layout
ed.Command("_.layout", "Set", layout.LayoutName);
// Get the block table record for the layout
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead);
foreach (ObjectId objId in btr)
{
// Check if the object is a viewport
if (objId.ObjectClass == RXObject.GetClass(typeof(Viewport)))
{
Viewport vp = (Viewport)tr.GetObject(objId, OpenMode.ForWrite);
// Turn on the viewport
vp.On = true;
}
}
}
// Commit the transaction
tr.Commit();
}
// Refresh the display
Application.UpdateScreen();
}
Can't find what you're looking for? Ask the community or share your knowledge.