.NET

.NET

Reply
Member
KoRORland
Posts: 5
Registered: ‎08-01-2012
Message 1 of 10 (1,106 Views)
Accepted Solution

Batching export to pdf from ACAD problem - C#

1106 Views, 9 Replies
08-01-2012 11:48 PM

Hi everyone!

 

I've got an exiting problem while trying to batch pdf export.

 

My task is quite simple: first, look through the drawing (all the lists and model space) and find all dynamic blocks with effective name "SheetGOST", case it's a drawing frame; second, export areas surrounded by those frames to pdf page by page. I've decided that plotting areas via "DWG To PDF.pc3" would be the easiest way.

Practically all the steps made: I get collection of blocks, I know howto print one of them to pdf, and it,s working correctly. The problem is, when I try to plot all the areas in cycle, in output pdf I get num of pages according to num of lists, and only the last area from the list. Test document contains 24 blocks on 3 lists, I get 3 page pdf with 7th, 22th and 24th frame printed..

 

I ran out of the ideas where I went wrong =(

 

The code is:

 

Spoiler

 

        [CommandMethod("PlotToPdf")] 
        static public void MultiSheetPlot() 
        { 
         Document doc = Application.DocumentManager.MdiActiveDocument; 
            Editor ed = doc.Editor; 
            Database db = doc.Database; 
            Transaction tr = db.TransactionManager.StartTransaction(); 
            using (tr) 
            { 
                List<GostBlk> BlocksToPlot = new List<GostBlk>(); 
                List<Layout> LayList = new List<Layout>(); 
                GetGostStampCollection(db, ed, tr, ref BlocksToPlot, ref LayList); 
                ed.WriteMessage("\nThe number of GOST stamps found: " + BlocksToPlot.Count + "\n\n"); 
                if (BlocksToPlot.Count < 1) return; 

                if (PlotFactory.ProcessPlotState == ProcessPlotState.NotPlotting) 
                { 
                    PlotEngine pe = PlotFactory.CreatePublishEngine(); 
                    using (pe) 
                    { 
                        PlotProgressDialog ppd = new PlotProgressDialog(false, BlocksToPlot.Count, true); 
                        using (ppd) 
                        { 
                            int numSheet = 1; 
                            ppd.set_PlotMsgString(PlotMessageIndex.DialogTitle, "Custom Plot Progress"); 
                            ppd.set_PlotMsgString(PlotMessageIndex.CancelJobButtonMessage, "Cancel Job"); 
                            ppd.set_PlotMsgString(PlotMessageIndex.CancelSheetButtonMessage, "Cancel Sheet"); 
                            ppd.set_PlotMsgString(PlotMessageIndex.SheetSetProgressCaption, "Sheet Set Progress"); 
                            ppd.set_PlotMsgString(PlotMessageIndex.SheetProgressCaption, "Sheet Progress"); 
                            ppd.LowerPlotProgressRange = 0; 
                            ppd.UpperPlotProgressRange = 100; 
                            ppd.PlotProgressPos = 0; 
                            ppd.OnBeginPlot(); 
                            ppd.IsVisible = true; 

                            pe.BeginPlot(ppd, null); 
                             
                            foreach (GostBlk gblk in BlocksToPlot) 
                            { 
                                ppd.StatusMsgString = "Plotting block " + numSheet.ToString() + " of " + BlocksToPlot.Count.ToString(); 
                                ppd.OnBeginSheet(); 
                                ppd.LowerSheetProgressRange = 0; 
                                ppd.UpperSheetProgressRange = 100; 
                                ppd.SheetProgressPos = 0; 

                                PlotInfoValidator piv = new PlotInfoValidator(); 
                                piv.MediaMatchingPolicy = MatchingPolicy.MatchEnabled; 

                                PlotPageInfo ppi = new PlotPageInfo(); 
                                PlotInfo pi = new PlotInfo(); 
                                 
                                BlockReference blk = gblk.BlockRef; 
                                Layout lo = gblk.LayoutRef;                                                                 
                                Extents3d ext = (Extents3d)blk.Bounds; 
                                Point3d first = ext.MaxPoint; 
                                Point3d second = ext.MinPoint; 

                                ResultBuffer rbFrom = new ResultBuffer(new TypedValue(5003, 1)), rbTo = new ResultBuffer(new TypedValue(5003, 2)); 
                                double[] firres = new double[] { 0, 0, 0 }; 
                                double[] secres = new double[] { 0, 0, 0 }; 
                                acedTrans(first.ToArray(), rbFrom.UnmanagedObject, rbTo.UnmanagedObject, 0, firres); 
                                acedTrans(second.ToArray(), rbFrom.UnmanagedObject, rbTo.UnmanagedObject, 0, secres); 
                                Extents2d window = new Extents2d(firres[0], firres[1], secres[0], secres[1]); 

                                // We need a PlotSettings object based on the layout settings which we then customize 
                                PlotSettings ps = new PlotSettings(lo.ModelType); 
                                LayoutManager.Current.CurrentLayout = lo.LayoutName; 
                                pi.Layout = lo.Id; 
                                ps.CopyFrom(lo); 

                                // The PlotSettingsValidator helps create a valid PlotSettings object 
                                PlotSettingsValidator psv = PlotSettingsValidator.Current; 
                                psv.SetPlotWindowArea(ps, window); 
                                psv.SetPlotType(ps, Autodesk.AutoCAD.DatabaseServices.PlotType.Window); 
                                psv.SetUseStandardScale(ps, true); 
                                psv.SetStdScaleType(ps, StdScaleType.ScaleToFit); 
                                psv.SetPlotCentered(ps, true); //StdScaleType.StdScale1To1 
                                psv.SetPlotConfigurationName(ps, "DWG To PDF.pc3", "ISO_A3_(297.00_x_420.00_MM)"); 
                                 
                                pi.OverrideSettings = ps; 
                                piv.Validate(pi); 

                                if (numSheet == 1) 
                                { 
                                    pe.BeginDocument(pi, doc.Name, null, 1, true, "c:\\multiblock"); 
                                } 
                                 
                                pe.BeginPage(ppi, pi, (numSheet == BlocksToPlot.Count), null); 
                                pe.BeginGenerateGraphics(null); 
                                ppd.SheetProgressPos = 50; 
                                pe.EndGenerateGraphics(null); 

                                // Finish the sheet 
                                pe.EndPage(null); 
                                ppd.SheetProgressPos = 100; 
                                ppd.PlotProgressPos += Convert.ToInt32(100 / BlocksToPlot.Count); 
                                ppd.OnEndSheet(); 
                                numSheet++; 
                            } 

                            // Finish the document 
                            pe.EndDocument(null); 
                            // And finish the plot 
                            ppd.PlotProgressPos = 100; 
                            ppd.OnEndPlot(); 
                            pe.EndPlot(null); 
                        } 
                    } 
                } 
                else 
                { 
                    ed.WriteMessage("\nAnother plot is in progress."); 
                } 
            } 
        }

 

 

 

Valued Mentor
fieldguy
Posts: 368
Registered: ‎03-31-2005
Message 2 of 10 (1,078 Views)

Re: Batching export to pdf from ACAD problem - C#

08-02-2012 08:06 AM in reply to: KoRORland

I assume you never see the message "another plot is in progress"?  Do you make sure "background plotting" is off?

In VB:

Imports acapp = Autodesk.AutoCAD.ApplicationServices

acapp.Application.SetSystemVariable("BACKGROUNDPLOT", 0)

 

Can you post a sample dwg with "SheetGOST" in it?

Valued Mentor
fieldguy
Posts: 368
Registered: ‎03-31-2005
Message 3 of 10 (1,073 Views)

Re: Batching export to pdf from ACAD problem - C#

08-02-2012 08:14 AM in reply to: fieldguy

We would also need to see your code for "GetGostStampCollection" in order to test.

Member
KoRORland
Posts: 5
Registered: ‎08-01-2012
Message 4 of 10 (1,072 Views)

Re: Batching export to pdf from ACAD problem - C#

08-02-2012 08:31 AM in reply to: fieldguy

Thx for answer!

 

No, it is plotting sort of corretly - no errors or anything. PlotProgressDialog shows progress for all the frames found. But still output contains only one (last) frame per list. =(

 

Example file in attachment...

Member
KoRORland
Posts: 5
Registered: ‎08-01-2012
Message 5 of 10 (1,071 Views)

Re: Batching export to pdf from ACAD problem - C#

08-02-2012 08:34 AM in reply to: fieldguy

Oh, my bad. Here it is: 

        static void GetGostStampCollection(Database db, Editor ed, Transaction tr, ref List<GostBlk> GostCol, ref List<Layout> LayList)
        {
            BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
            foreach (ObjectId btrId in bt)
            {
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
                if (btr.IsLayout)
                {
                    Layout lo = (Layout)tr.GetObject(btr.LayoutId, OpenMode.ForRead);
                    if (!LayList.Contains(lo)) LayList.Add(lo);
                    BlockTableRecord ms = (BlockTableRecord)tr.GetObject(lo.BlockTableRecordId, OpenMode.ForRead);
                    foreach (ObjectId objId in ms)
                    {
                        Entity ent = (Entity)tr.GetObject(objId, OpenMode.ForRead);
                        if (!ent.GetType().ToString().Contains("BlockReference")) continue;
                        BlockReference blk = (BlockReference)ent;
                        string Effn = ACADExtension.ACADExt.EffectiveName(blk);
                        if (!Effn.ToUpper().Contains("SHEETGOST")) continue;
                        GostBlk theBlk = new GostBlk();
                        theBlk.BlockRef = blk;
                        theBlk.LayoutRef = lo;
                        GostCol.Add(theBlk);
                    }
                }
            }
        }

 

You might need as well my finding block by .EffectiveName:

 

public static string EffectiveName(BlockReference blkref)
        {
            if (blkref.IsDynamicBlock)
            {
                using (BlockTableRecord obj = (BlockTableRecord)blkref.DynamicBlockTableRecord.GetObject(OpenMode.ForRead))
                    return obj.Name;
            }
            return blkref.Name;
        }

 Thanks in advance!

Valued Mentor
fieldguy
Posts: 368
Registered: ‎03-31-2005
Message 6 of 10 (1,069 Views)

Re: Batching export to pdf from ACAD problem - C#

08-02-2012 08:37 AM in reply to: KoRORland

Good - thanks!  What about backgroundplot?

Member
KoRORland
Posts: 5
Registered: ‎08-01-2012
Message 7 of 10 (1,067 Views)

Re: Batching export to pdf from ACAD problem - C#

08-02-2012 08:45 AM in reply to: fieldguy

Whoa! Adding this to the start has done the trick:

 

Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("BACKGROUNDPLOT", 0);

 That's great! Thank you very much! =) Feeling a little bit mad 'bout myself, though :smileyindifferent:

Valued Mentor
fieldguy
Posts: 368
Registered: ‎03-31-2005
Message 8 of 10 (1,064 Views)

Re: Batching export to pdf from ACAD problem - C#

08-02-2012 08:49 AM in reply to: KoRORland

No problem!  Carry on...

Member
KoRORland
Posts: 5
Registered: ‎08-01-2012
Message 9 of 10 (1,038 Views)

Re: Batching export to pdf from ACAD problem - C#

08-03-2012 12:50 AM in reply to: fieldguy

And, finally, working (tested in ACAD2010) code for the problem. In case someone finds it useful:

 

Spoiler
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Internal.Reactors;
using Autodesk.AutoCAD.PlottingServices;
using Autodesk.AutoCAD.Runtime;
using ACAD = Autodesk.AutoCAD.ApplicationServices.Application;
using ED = Autodesk.AutoCAD.EditorInput.Editor;

namespace Plot2PDF
{
    public class Program : IExtensionApplication
    {
        [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedTrans")]

        static extern int acedTrans(double[] point, IntPtr fromRb, IntPtr toRb, int disp, double[] result);
        List<string> msgs = new List<string>();

        public class Blk2Plt
        {
            public BlockReference BlockRef;
            public Layout LayoutObj;
        }

        public void Terminate()
        {
            ApplicationEventManager cadWinEvnts = Autodesk.AutoCAD.Internal.Reactors.ApplicationEventManager.Instance();
            msgs.Sort();
            ED ed = ACAD.DocumentManager.MdiActiveDocument.Editor;
            foreach (string msg in msgs)
            {
                ed.WriteMessage(msg);
            }
        }

        public void Initialize()
        {

        }

        static string EffectiveName(BlockReference blkref)
        {
            if (blkref.IsDynamicBlock)
            {
                using (BlockTableRecord obj = (BlockTableRecord)blkref.DynamicBlockTableRecord.GetObject(OpenMode.ForRead))
                    return obj.Name;
            }
            return blkref.Name;
        }

        static void GetBlocksToPlotCollection(Database db, Editor ed, Transaction tr, String BlockName, ref List<Blk2Plt> BlockCol)
        {
            BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
            foreach (ObjectId btrId in bt)
            {
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
                if (btr.IsLayout)
                {
                    Layout lo = (Layout)tr.GetObject(btr.LayoutId, OpenMode.ForRead);
                    BlockTableRecord ms = (BlockTableRecord)tr.GetObject(lo.BlockTableRecordId, OpenMode.ForRead);
                    foreach (ObjectId objId in ms)
                    {
                        Entity ent = (Entity)tr.GetObject(objId, OpenMode.ForRead);
                        if (!ent.GetType().ToString().Contains("BlockReference")) continue;
                        BlockReference blk = (BlockReference)ent;
                        string Effn = EffectiveName(blk);
                        if (!Effn.ToUpper().Contains(BlockName.ToUpper())) continue;
                        Blk2Plt theBlk = new Blk2Plt();
                        theBlk.BlockRef = blk;
                        theBlk.LayoutObj = lo;
                        BlockCol.Add(theBlk);
                    }
                }
            }
        }

        static void PlotBlockColToPDF(String BlockName, String PrinterName, String OutPath, String PaperSize = "ISO_A4_(297.00_x_210.00_MM)")
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
            Transaction tr = db.TransactionManager.StartTransaction();
            Object SysVarBackPlot = Application.GetSystemVariable("BACKGROUNDPLOT");
            Application.SetSystemVariable("BACKGROUNDPLOT", 0);
            using (tr)
            {
                List<Blk2Plt> BlocksToPlot = new List<Blk2Plt>();

                GetBlocksToPlotCollection(db, ed, tr, BlockName, ref BlocksToPlot);//Getting collection of blocks

                ed.WriteMessage("\nThe number of blocks found: " + BlocksToPlot.Count + "\n\n");
                if (BlocksToPlot.Count < 1) return;

                if (PlotFactory.ProcessPlotState == ProcessPlotState.NotPlotting)
                {
                    PlotEngine pe = PlotFactory.CreatePublishEngine();
                    using (pe)
                    {
                        PlotProgressDialog ppd = new PlotProgressDialog(false, BlocksToPlot.Count, true);
                        using (ppd)
                        {
                            int numSheet = 1;
                            // Setting up the PlotProgress dialog
                            ppd.set_PlotMsgString(PlotMessageIndex.DialogTitle, "Custom Plot Progress");
                            ppd.set_PlotMsgString(PlotMessageIndex.CancelJobButtonMessage, "Cancel Job");
                            ppd.set_PlotMsgString(PlotMessageIndex.CancelSheetButtonMessage, "Cancel Sheet");
                            ppd.set_PlotMsgString(PlotMessageIndex.SheetSetProgressCaption, "Sheet Set Progress");
                            ppd.set_PlotMsgString(PlotMessageIndex.SheetProgressCaption, "Sheet Progress");
                            ppd.LowerPlotProgressRange = 0;
                            ppd.UpperPlotProgressRange = 100;
                            ppd.PlotProgressPos = 0;
                            ppd.OnBeginPlot();
                            ppd.IsVisible = true;

                            pe.BeginPlot(ppd, null);

                            foreach (Blk2Plt gblk in BlocksToPlot)
                            {
                                // Starting new page
                                ppd.StatusMsgString = "Plotting block " + numSheet.ToString() + " of " + BlocksToPlot.Count.ToString();
                                ppd.OnBeginSheet();
                                ppd.LowerSheetProgressRange = 0;
                                ppd.UpperSheetProgressRange = 100;
                                ppd.SheetProgressPos = 0;

                                PlotInfoValidator piv = new PlotInfoValidator();
                                piv.MediaMatchingPolicy = MatchingPolicy.MatchEnabled;
                                PlotPageInfo ppi = new PlotPageInfo();
                                PlotInfo pi = new PlotInfo();
                                BlockReference blk = gblk.BlockRef;
                                Layout lo = gblk.LayoutObj;

                                // Getting coodinates of window to plot
                                Extents3d ext = (Extents3d)blk.Bounds;
                                Point3d first = ext.MaxPoint;
                                Point3d second = ext.MinPoint;
                                ResultBuffer rbFrom = new ResultBuffer(new TypedValue(5003, 1)), rbTo = new ResultBuffer(new TypedValue(5003, 2));
                                double[] firres = new double[] { 0, 0, 0 };
                                double[] secres = new double[] { 0, 0, 0 };
                                acedTrans(first.ToArray(), rbFrom.UnmanagedObject, rbTo.UnmanagedObject, 0, firres);
                                acedTrans(second.ToArray(), rbFrom.UnmanagedObject, rbTo.UnmanagedObject, 0, secres);
                                Extents2d window = new Extents2d(firres[0], firres[1], secres[0], secres[1]);

                                // We need a PlotSettings object based on the layout settings which we then customize
                                PlotSettings ps = new PlotSettings(lo.ModelType);
                                LayoutManager.Current.CurrentLayout = lo.LayoutName;
                                pi.Layout = lo.Id;
                                ps.CopyFrom(lo);

                                // The PlotSettingsValidator helps create a valid PlotSettings object
                                PlotSettingsValidator psv = PlotSettingsValidator.Current;
                                psv.SetPlotWindowArea(ps, window);
                                psv.SetPlotType(ps, Autodesk.AutoCAD.DatabaseServices.PlotType.Window);
                                psv.SetUseStandardScale(ps, true);
                                psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);
                                psv.SetPlotCentered(ps, true);
                                psv.SetPlotConfigurationName(ps, PrinterName, PaperSize);

                                pi.OverrideSettings = ps;
                                piv.Validate(pi);

                                if (numSheet == 1) pe.BeginDocument(pi, doc.Name, null, 1, true, OutPath); // Create document for the first page

                                // Plot the window
                                pe.BeginPage(ppi, pi, (numSheet == BlocksToPlot.Count), null);
                                pe.BeginGenerateGraphics(null);
                                ppd.SheetProgressPos = 50;
                                pe.EndGenerateGraphics(null);

                                // Finish the sheet
                                pe.EndPage(null);
                                ppd.SheetProgressPos = 100;
                                ppd.PlotProgressPos += Convert.ToInt32(100 / BlocksToPlot.Count);
                                ppd.OnEndSheet();
                                numSheet++;
                            }
                            // Finish the document and finish the plot
                            pe.EndDocument(null);
                            ppd.PlotProgressPos = 100;
                            ppd.OnEndPlot();
                            pe.EndPlot(null);
                            ed.WriteMessage("\nPlot completed successfully!\n\n");
                        }
                    }
                }
                else
                {
                    ed.WriteMessage("\nAnother plot is in progress.\n\n");
                }
                tr.Commit();
            }
            Application.SetSystemVariable("BACKGROUNDPLOT", SysVarBackPlot);
        }

        [CommandMethod("PlotToPdf")]
        static public void PlotToPdf()
        {
            String BlockName = "SHEETGOST";
            String PrinterName = "DWG To PDF.pc3";
            String PaperSize = "ISO_A3_(297.00_x_420.00_MM)";
            String OutPath = "c:\\plot2pdf";

            PlotBlockColToPDF(BlockName, PrinterName, OutPath, PaperSize);
        }
    }
}

 

 

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 10 of 10 (1,035 Views)

Re: Batching export to pdf from ACAD problem - C#

08-03-2012 01:25 AM in reply to: KoRORland

Thanks for the sharing,

Regards,

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.