Plot DWG TO PDF for Multiple Layouts In C#

Plot DWG TO PDF for Multiple Layouts In C#

Anonymous
Not applicable
10,978 Views
15 Replies
Message 1 of 16

Plot DWG TO PDF for Multiple Layouts In C#

Anonymous
Not applicable
Hi, I'm Not able to find a way to do this.Actually i have searched in all the forums ,but none of them given were working as expected. My Program is simple ,If i click a button in my windows Forms ,It has to create pdf for all the layouts present in the drawing. FYI-i have tried with commandMethod,SendCommand ,loading Lisp(All these are Working Manually). But When i try to execute the same in code,its not working.So i'm looking for the exact solution for this. I hope someone would help me.Thank You
0 Likes
10,979 Views
15 Replies
Replies (15)
Message 2 of 16

_gile
Consultant
Consultant

Hi,

 

Maybe you can get some inspiration from these little classes:

 

 

using System.Collections.Generic;
using System.IO;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.PlottingServices;
using Autodesk.AutoCAD.Publishing;

namespace Gile.Publish
{
    // Base class for the different configurations
    public abstract class PlotToFileConfig
    {
        // Private fields
        private string dsdFile, dwgFile, outputDir, outputFile, plotType;
        private int sheetNum;
        private IEnumerable<Layout> layouts;
        private const string LOG = "publish.log";

        // Base constructor
        public PlotToFileConfig(string outputDir, IEnumerable<Layout> layouts, string plotType)
        {
            Database db = HostApplicationServices.WorkingDatabase;
            this.dwgFile = db.Filename;
            this.outputDir = outputDir;
            this.dsdFile = Path.ChangeExtension(this.dwgFile, "dsd");
            this.layouts = layouts;
            this.plotType = plotType;
            string ext = plotType == "0" || plotType == "1" ? "dwf" : "pdf";
            this.outputFile = Path.Combine(
                this.outputDir,
                Path.ChangeExtension(Path.GetFileName(this.dwgFile), ext)); 
        }

        // Plot the layouts
        public void Publish()
        {
            if (TryCreateDSD())
            {
				object bgp = Application.GetSystemVariable("BACKGROUNDPLOT");
                object ctab = Application.GetSystemVariable("CTAB");
                try
                {
                    Application.SetSystemVariable("BACKGROUNDPLOT", 0);

                    Publisher publisher = Application.Publisher;
                    PlotProgressDialog plotDlg = new PlotProgressDialog(false, this.sheetNum, true);
                    publisher.PublishDsd(this.dsdFile, plotDlg);
                    plotDlg.Destroy();
                    File.Delete(this.dsdFile);
			    }
                catch (System.Exception exn)
                {
                    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                    ed.WriteMessage("\nError: {0}\n{1}", exn.Message, exn.StackTrace);
                    throw;
                }
                finally
                {
                    Application.SetSystemVariable("BACKGROUNDPLOT", bgp);
                    Application.SetSystemVariable("CTAB", ctab);
                }
            }
        }

        // Creates the DSD file from a template (default options)
        private bool TryCreateDSD()
        {
            using (DsdData dsd = new DsdData())
            using (DsdEntryCollection dsdEntries = CreateDsdEntryCollection(this.layouts))
            {
                if (dsdEntries == null || dsdEntries.Count <= 0) return false;

                if (!Directory.Exists(this.outputDir))
                    Directory.CreateDirectory(this.outputDir);

                this.sheetNum = dsdEntries.Count;

                dsd.SetDsdEntryCollection(dsdEntries);

                dsd.SetUnrecognizedData("PwdProtectPublishedDWF", "FALSE");
                dsd.SetUnrecognizedData("PromptForPwd", "FALSE");
                dsd.NoOfCopies = 1;
                dsd.DestinationName = this.outputFile;
                dsd.IsHomogeneous = false;
                dsd.LogFilePath = Path.Combine(this.outputDir, LOG);

                PostProcessDSD(dsd);

                return true;
            }
        }

        // Creates an entry collection (one per layout) for the DSD file
        private DsdEntryCollection CreateDsdEntryCollection(IEnumerable<Layout> layouts)
        {
            DsdEntryCollection entries = new DsdEntryCollection();

            foreach (Layout layout in layouts)
            {
                DsdEntry dsdEntry = new DsdEntry();
                dsdEntry.DwgName = this.dwgFile;
                dsdEntry.Layout = layout.LayoutName;
                dsdEntry.Title = Path.GetFileNameWithoutExtension(this.dwgFile) + "-" + layout.LayoutName;
                dsdEntry.Nps = layout.TabOrder.ToString();
                entries.Add(dsdEntry);
            }
            return entries;
        }

        // Writes the definitive DSD file from the templates and additional informations
        private void PostProcessDSD(DsdData dsd)
        {
            string str, newStr;
            string tmpFile = Path.Combine(this.outputDir, "temp.dsd");

            dsd.WriteDsd(tmpFile);

            using (StreamReader reader = new StreamReader(tmpFile, Encoding.Default))
            using (StreamWriter writer = new StreamWriter(this.dsdFile, false, Encoding.Default))
            {
                while (!reader.EndOfStream)
                {
                    str = reader.ReadLine();
                    if (str.Contains("Has3DDWF"))
                    {
                        newStr = "Has3DDWF=0";
                    }
                    else if (str.Contains("OriginalSheetPath"))
                    {
                        newStr = "OriginalSheetPath=" + this.dwgFile;
                    }
                    else if (str.Contains("Type"))
                    {
                        newStr = "Type=" + this.plotType;
                    }
                    else if (str.Contains("OUT"))
                    {
                        newStr = "OUT=" + this.outputDir;
                    }
                    else if (str.Contains("IncludeLayer"))
                    {
                        newStr = "IncludeLayer=TRUE";
                    }
                    else if (str.Contains("PromptForDwfName"))
                    {
                        newStr = "PromptForDwfName=FALSE";
                    }
                    else if (str.Contains("LogFilePath"))
                    {
                        newStr = "LogFilePath=" + Path.Combine(this.outputDir, LOG);
                    }
                    else
                    {
                        newStr = str;
                    }
                    writer.WriteLine(newStr);
                }
            }
            File.Delete(tmpFile);
        }
    }

    // Class to plot one DWF file per sheet
    public class SingleSheetDwf : PlotToFileConfig
    {
        public SingleSheetDwf(string outputDir, IEnumerable<Layout> layouts)
            : base(outputDir, layouts, "0") {}
    }

    // Class to plot a multi-sheet DWF file
    public class MultiSheetsDwf : PlotToFileConfig
    {
        public MultiSheetsDwf(string outputDir, IEnumerable<Layout> layouts) 
            : base(outputDir, layouts, "1") {}
    }

    // Class to plot one PDF file per sheet
    public class SingleSheetPdf : PlotToFileConfig
    {
        public SingleSheetPdf(string outputDir, IEnumerable<Layout> layouts)
            : base(outputDir, layouts, "5") {}
    }

    // Class to plot a multi-sheet PDF file
    public class MultiSheetsPdf : PlotToFileConfig
    {
        public MultiSheetsPdf(string outputDir, IEnumerable<Layout> layouts) 
            : base(outputDir, layouts, "6") {}
    }
}

 

Using instructions:

Create an instance of SingleSheetPdf (to plot one file per layout) or MultiSheetPdf (to plot a multi sheet file) and call this instance Publish() method.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 16

Anonymous
Not applicable
Hi, Thanks for your reply.I think you are explaining a dll file runs in commandmethod (Sorry if im wrong).Actually i have to do it in exe.not in .dll .So is there any other way to Export/Publish DWG TO PDF (All layouts) from an exe. Because i got a similar program which is running fine with .netload options inside Autocad.But i want to do it from outside. Problem is i'm Not able to refer accoremgd.dll,acmgd.dll Etc..These dll's are throwing error whenever i try to run my exe . So do you have any other suggestions/ideas to overcome this issue?
0 Likes
Message 4 of 16

Anonymous
Not applicable
Can you please give me a who;e solution which i used in my .net?
0 Likes
Message 5 of 16

Anonymous
Not applicable
What about if my single sheet having multiple layouts and i want to print those all layouts?
0 Likes
Message 6 of 16

_gile
Consultant
Consultant

Sorry, it's a little confusing what you mean with sheet, layout (here) or window (there)...

Please use the AutoCAD vocabulary:

  • a sheet is an item of a sheet set (this routine do not deals with sheet sets, if any) ;
  • a layout corresponds to a paper space tab (each drawing have at least one layout) ;
  • a layout may contain one ore more viewport.

As is, the upper routine prints all the layouts of the current document into a single multi sheets PDF file.

 

 

More genrally,

 

You will not learn .NET AutoCAD API by copying codes found on the web that you do not understand and asking someone here or elsewhere to modify them to suit your needs.

 

If you want to learn how to program AutoCAD with the .NET API, you should first have a good knowledge of AutoCAD and learn .NET (Framework, OOP, C#, ...) outside of AutoCAD, and only after this, learn the AutoCAD API.

 

If you want someone to write a program for you, clearly express your request and you'll probably find someone to do it (possibly against compensation).

 

If you want the community members to keep on helping you, please, give some feedback to those who spend some time to reply you.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 16

Anonymous
Not applicable
Right according to your reply I have more than one viewport in my single sheet and I want to print those all viewport in my pdf.
0 Likes
Message 8 of 16

_gile
Consultant
Consultant

As is, the routine prints all the contents of the plot area (i.e. all viewports within this area) of each layout.

Maybe an issue with your drawing.

 

What if you directly plot the layout from AutoCAD ?



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 9 of 16

Anonymous
Not applicable
Sorry its my mistake I want to say that I have more than one pages in my single sheet and I want to print pdf of that all pages.
0 Likes
Message 10 of 16

_gile
Consultant
Consultant

Sorry,

 

I cannot follow you anymore.

You're multiplying posts in different topics (and on different sites).

Which code are you trying to use ? the one in this current topic or the one in this topic (or anyone else) ?

What do you mean with "page", "sheet" ? is this related to AutoCAD or PDF ?

 

Using this topic upper code, if you want to:

  • create a single PDF file containing one sheet per layout in the DWG file: use the MultiSheetPdf class
  • create a single PDF file for each layout in the DWG file: use the SingleSheetPdf class

to build a CommandMethod in which you create a new instance of this class passing it the output PDF file name and a collection of Layout instances you want to plot, then the call this instance Publish() method (refer to the CommandMethod code of this topic).

 

If you are not able to do it by yourself, leave on this kind of task until you are more comfortable with .NET general programming and .NET AutoCAD programming and choose simpler goals to learn.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 11 of 16

Anonymous
Not applicable

Sorry sir,actually I am new here and want answer immediately for some circumstances.I will sent you screenshot of my file you check it and tell me whats wrong in that.

0 Likes
Message 12 of 16

_gile
Consultant
Consultant

As I said upper, it seems to be a drawing (DWG) issue.

In the single layout of this drawing, only one viewport is within the plot area, so only this viewport can be plotted.

Did you tried, as I recommended, to plot the layout directly form AutoCAD _PLOT command ? Certainly not...


You have to create one layout per viewport and put each viewport in its own layout plot area.


As I said upper, you cannot pretend to program AutoCAD if you ignore the AutoCAD basic features.


I do not know what kind of "circumstances" requires you to get an answer immediately, but from my side, I'm not sure you want to spend more time to do your work for you.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 13 of 16

5thSth
Advocate
Advocate

@_gile 

wow! thats some beautiful work you did with that code!
educational stuff!

0 Likes
Message 14 of 16

_gile
Consultant
Consultant

@5thSth

 

Thanks.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 15 of 16

wayne
Explorer
Explorer

Hi Gile,

What you've coded is amazing, and I've tried it with the default AutoCAD layout and they are publishing fine.

However, once I attempt to publish a customized layout, AutoCAD sent me error message says that there were no plottable sheets.

Here are some details if you can take a look:

//Delete viewport

private static void DeleteViewports(ref Document doc)
{
Database db = doc.Database;
Editor ed = doc.Editor;

ObjectIdCollection erased = new ObjectIdCollection();
using (DocumentLock dlock = doc.LockDocument())
{
using (Transaction trans = db.TransactionManager.StartTransaction())
{

ed.SwitchToPaperSpace();
BlockTableRecord acBlkTblRec;
acBlkTblRec = (BlockTableRecord)trans.GetObject(db.CurrentSpaceId, OpenMode.ForRead);

BlockTableRecordEnumerator pBTREnum = acBlkTblRec.GetEnumerator();
int i = 0;

while (pBTREnum.MoveNext())
{
ObjectId pObjId = pBTREnum.Current;
DBObject pDbObj = (DBObject)trans.GetObject(pObjId, OpenMode.ForRead);
if (i == 0)
{
i = i + 1;
continue;
}
else
{
if (!pDbObj.IsErased)
{
pDbObj.UpgradeOpen();
pDbObj.Erase(true);
}
}
}
trans.Commit();
}
}
}

 

//paperName = @"ANSI_A_(8.50_x_11.00_Inches)"

//deviceName = "DWF6 ePlot.pc3"

private static void CreateOrEditPageSetUp(string deviceName, string paperName, string pageSetUp)
{
Document acDoc = AcadApp.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
DBDictionary plSets = acTrans.GetObject(acCurDb.PlotSettingsDictionaryId, OpenMode.ForRead) as DBDictionary;
DBDictionary vStyles = acTrans.GetObject(acCurDb.VisualStyleDictionaryId, OpenMode.ForRead) as DBDictionary;
PlotSettings acPlSet = default(PlotSettings);
bool createNew = false;

LayoutManager acLaoutMgr = LayoutManager.Current;

Layout acLayout = acTrans.GetObject(acLaoutMgr.GetLayoutId(acLaoutMgr.CurrentLayout), OpenMode.ForRead) as Layout;

if (plSets.Contains(pageSetUp) == false)
{
createNew = true;

acPlSet = new PlotSettings(acLayout.ModelType);
acPlSet.CopyFrom(acLayout);

acPlSet.PlotSettingsName = pageSetUp;
acPlSet.AddToPlotSettingsDictionary(acCurDb);
acTrans.AddNewlyCreatedDBObject(acPlSet, true);
}
else
{
acPlSet = plSets.GetAt(pageSetUp).GetObject(OpenMode.ForWrite) as PlotSettings;
}
try
{
PlotSettingsValidator acPlSetVdr = PlotSettingsValidator.Current;
acPlSetVdr.SetPlotConfigurationName(acPlSet, deviceName, paperName);
if (acLayout.ModelType == false)
{
acPlSetVdr.SetPlotType(acPlSet, Autodesk.AutoCAD.DatabaseServices.PlotType.Layout);
}
else
{
acPlSetVdr.SetPlotType(acPlSet, Autodesk.AutoCAD.DatabaseServices.PlotType.Extents);
acPlSetVdr.SetPlotCentered(acPlSet, true);
}
// Set the plot offset
acPlSetVdr.SetPlotOrigin(acPlSet, new Point2d(0, 0));
// Set the plot scale
acPlSetVdr.SetUseStandardScale(acPlSet, true);
acPlSetVdr.SetStdScaleType(acPlSet, StdScaleType.ScaleToFit);
acPlSetVdr.SetPlotPaperUnits(acPlSet, PlotPaperUnit.Millimeters);
acPlSet.ScaleLineweights = true;
acPlSet.ShowPlotStyles = true;
acPlSetVdr.RefreshLists(acPlSet);

// Specify the shaded viewport options
acPlSet.ShadePlot = PlotSettingsShadePlotType.AsDisplayed;

acPlSet.ShadePlotResLevel = ShadePlotResLevel.Normal;

// Specify the plot options
acPlSet.PrintLineweights = true;
acPlSet.PlotTransparency = false;
acPlSet.PlotPlotStyles = true;
acPlSet.DrawViewportsFirst = true;
// Specify the plot orientation
acPlSetVdr.SetPlotRotation(acPlSet, PlotRotation.Degrees000);

// Set the plot style
if (acCurDb.PlotStyleMode == true)
{
acPlSetVdr.SetCurrentStyleSheet(acPlSet, "acad.ctb");
}
else
{
acPlSetVdr.SetCurrentStyleSheet(acPlSet, "acad.stb");
}

// Zoom to show the whole paper
acPlSetVdr.SetZoomToPaperOnUpdate(acPlSet, true);
}
catch (Autodesk.AutoCAD.Runtime.Exception es)
{
System.Windows.Forms.MessageBox.Show(es.Message);
}
// Save the changes made
acTrans.Commit();

if (createNew == true)
{
acPlSet.Dispose();
}
}
}
public static void AssignPageSetupToLayout(string pageSetup)
{
// Get the current document and database, and start a transaction
Document acDoc = AcadApp.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Reference the Layout Manager
LayoutManager acLayoutMgr = LayoutManager.Current;

// Get the current layout and output its name in the Command Line window
Layout acLayout = acTrans.GetObject(acLayoutMgr.GetLayoutId(acLayoutMgr.CurrentLayout),
OpenMode.ForRead) as Layout;

DBDictionary acPlSet = acTrans.GetObject(acCurDb.PlotSettingsDictionaryId,
OpenMode.ForRead) as DBDictionary;

// Check to see if the page setup exists
if (acPlSet.Contains(pageSetup) == true)
{
PlotSettings plSet = acPlSet.GetAt(pageSetup).GetObject(OpenMode.ForRead) as PlotSettings;

// Update the layout
acLayout.UpgradeOpen();
acLayout.CopyFrom(plSet);

// Save the new objects to the database
acTrans.Commit();
}
else
{
// Ignore the changes made
acTrans.Abort();
}
}

// Update the display
acDoc.Editor.Regen();
}

0 Likes
Message 16 of 16

a.kouchakzadeh
Advocate
Advocate

Gilles, your code is super amazing

0 Likes