/// ExportLayouts.cs (c) 2013 Tony Tanzillo
///
/// AutoCAD.NET API sample that automates
/// the EXPORTLAYOUT command to export all
/// layouts in the current document.
///
/// Two versions of the command are included.
/// The second version (EXPORTLAYOUTS2) requires
/// a reference to AcExportLayout.dll.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Linq.Expressions;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
/// Needed with EXPORTLAYOUTS2 command only, and
/// requires a reference to AcExportLayout.dll:
using AcExportLayout = Autodesk.AutoCAD.ExportLayout;
namespace ExportLayoutsExample
{
public static class ExportLayoutsCommands
{
/// <summary>
/// Automates the EXPORTLAYOUT command to export
/// all paper space layouts to .DWG files.
///
/// In this example, we export each layout to
/// a drawing file in the same location as the
/// current drawing, wherein each file has the
/// name "<dwgname>_<layoutname>.dwg".
///
/// This is not a functionally-complete example:
///
/// No checking is done to see if any of the
/// files already exist, and existing files
/// are overwritten without warning or error.
///
/// No checking is done to detect if an existing
/// file exists and is in-use by another user, or
/// cannot be overwritten for any other reason.
///
/// No checking is done to ensure that the user
/// has sufficient rights to write files in the
/// target location.
///
/// You can and should deal with any or all of
/// the above as per your own requirements.
///
/// </summary>
[CommandMethod( "EXPORTLAYOUTS" )]
public static void ExportLayoutsCommand()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var editor = doc.Editor;
try
{
if( (short) Application.GetSystemVariable( "DWGTITLED" ) == 0 )
{
editor.WriteMessage(
"\nCommand cannot be used on an unnamed drawing"
);
return;
}
string format =
Path.Combine(
Path.GetDirectoryName( doc.Name ),
Path.GetFileNameWithoutExtension( doc.Name ) )
+ "_{0}.dwg";
string[] names = null;
using( Transaction tr = doc.TransactionManager.StartTransaction() )
{
// Get the localized name of the model tab:
BlockTableRecord btr = (BlockTableRecord)
SymbolUtilityServices.GetBlockModelSpaceId( db )
.GetObject( OpenMode.ForRead );
Layout layout = (Layout)
btr.LayoutId.GetObject( OpenMode.ForRead );
string model = layout.LayoutName;
// Open the Layout dictionary:
IDictionary layouts = (IDictionary)
db.LayoutDictionaryId.GetObject( OpenMode.ForRead );
// Get the names and ids of all paper space layouts into a list:
names = layouts.Keys.Cast<string>()
.Where( name => name != model ).ToArray();
tr.Commit();
}
int cmdecho = 0;
#if DEBUG
cmdecho = 1;
#endif
using( new ManagedSystemVariable
( "CMDECHO", cmdecho
) ) using( new ManagedSystemVariable
( "CMDDIA",
0 ) ) using( new ManagedSystemVariable
( "FILEDIA",
0 ) ) using( new ManagedSystemVariable
( "CTAB" ) ) {
foreach( string name in names )
{
string filename = string.Format( format, name );
editor.WriteMessage( "\nExporting {0}\n", filename );
Application.SetSystemVariable( "CTAB", name );
editor.Command( "._EXPORTLAYOUT", filename );
}
}
}
catch( System.Exception ex )
{
#if DEBUG
editor.WriteMessage( ex.ToString() );
#else
throw ex;
#endif
}
}
/// <summary>
///
/// Doesn't use the command line, requires AutoCAD R12
/// or later and a reference to AcExportLayout.dll:
///
/// This version can be used from the application context,
/// which can make it easier to use in a batch process that
/// exports layouts of many files.
///
/// The example also shows how to use the AcExportLayout
/// component to export a layout to an in-memory Database
/// without creating a drawing file.
///
/// </summary>
[CommandMethod( "EXPORTLAYOUTS2", CommandFlags.Session )]
public static void ExportLayouts2()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var editor = doc.Editor;
try
{
if( (short) Application.GetSystemVariable( "DWGTITLED" ) == 0 )
{
editor.WriteMessage(
"\nCommand cannot be used on an unnamed drawing"
);
return;
}
string format =
Path.Combine(
Path.GetDirectoryName( doc.Name ),
Path.GetFileNameWithoutExtension( doc.Name ) )
+ "_{0}.dwg";
Dictionary<string, ObjectId> layouts = null;
using( doc.LockDocument() )
{
using( Transaction tr = doc.TransactionManager.StartTransaction() )
{
// Get the localized name of the model tab:
BlockTableRecord btr = (BlockTableRecord)
SymbolUtilityServices.GetBlockModelSpaceId( db )
.GetObject( OpenMode.ForRead );
Layout layout = (Layout)
btr.LayoutId.GetObject( OpenMode.ForRead );
string model = layout.LayoutName;
// Open the Layout dictionary:
IDictionary layoutDictionary = (IDictionary)
db.LayoutDictionaryId.GetObject( OpenMode.ForRead );
// Get the names and ids of all paper space layouts
// into a Dictionary<string,ObjectId>:
layouts = layoutDictionary.Cast<DictionaryEntry>()
.Where( e => ( (string) e.Key ) != model )
.ToDictionary(
e => (string) e.Key,
e => (ObjectId) e.Value );
tr.Commit();
}
/// Get the export layout 'engine':
Autodesk.AutoCAD.ExportLayout.Engine engine =
Autodesk.AutoCAD.ExportLayout.Engine.Instance();
using( new ManagedSystemVariable
( "CTAB" ) ) {
foreach( var entry in layouts )
{
string filename = string.Format( format, entry.Key );
editor.WriteMessage( "\nExporting {0} => {1}\n", entry.Key, filename );
Application.SetSystemVariable( "CTAB", entry.Key );
using( Database database = engine.ExportLayout( entry.Value ) )
{
if( engine.EngineStatus == AcExportLayout.ErrorStatus.Succeeded )
{
database.SaveAs( filename, DwgVersion.Newest );
}
else
{
editor.WriteMessage( "\nExportLayout failed: ",
engine.EngineStatus.ToString() );
break;
}
}
}
}
}
}
catch( System.Exception ex )
{
#if DEBUG
editor.WriteMessage( ex.ToString() );
#else
throw ex;
#endif
}
}
}
public static class EditorInputExtensionMethods
{
public static PromptStatus Command( this Editor editor, params object[] args )
{
if( editor == null )
throw new ArgumentNullException
( "editor" ); return runCommand( editor, args );
}
static Func<Editor, object[], PromptStatus> runCommand = GenerateRunCommand();
static Func<Editor, object[], PromptStatus> GenerateRunCommand()
{
MethodInfo method
= typeof( Editor
).GetMethod( "RunCommand",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public );
var instance
= Expression
.Parameter( typeof( Editor
),
"instance" ); var args
= Expression
.Parameter( typeof( object[] ),
"args" ); return Expression.Lambda<Func<Editor, object[], PromptStatus>>(
Expression.Call( instance, method, args ), instance, args )
.Compile();
}
}
/// <summary>
/// Automates saving/changing/restoring system variables
/// </summary>
public class ManagedSystemVariable : IDisposable
{
string name = null;
object oldval = null;
public ManagedSystemVariable( string name, object value )
: this( name )
{
Application.SetSystemVariable( name, value );
}
public ManagedSystemVariable( string name )
{
if( string.IsNullOrWhiteSpace( name ) )
throw new ArgumentException
( "name" ); this.name = name;
this.oldval = Application.GetSystemVariable( name );
}
public void Dispose()
{
if( oldval != null )
{
object temp = oldval;
oldval = null;
Application.SetSystemVariable( name, temp );
}
}
}
}