gile 发表于 2013-3-17 06:24:18

Hi,
Here's a little class to be used to plot layouts to a single multi sheets PDF file.
using System.Collections.Generic;
using System.IO;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.PlottingServices;
using Autodesk.AutoCAD.Publishing;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace Plottings
{
    public class MultiSheetsPdf
    {
      private string dwgFile, pdfFile, dsdFile, outputDir;
      private int sheetNum;
      IEnumerable layouts;

      private const string LOG = "publish.log";

      public MultiSheetsPdf(string pdfFile, IEnumerable layouts)
      {
            Database db = HostApplicationServices.WorkingDatabase;
            this.dwgFile = db.Filename;
            this.pdfFile = pdfFile;
            this.outputDir = Path.GetDirectoryName(this.pdfFile);
            this.dsdFile = Path.ChangeExtension(this.pdfFile, "dsd");
            this.layouts = layouts;
      }

      public void Publish()
      {
            if (TryCreateDSD())
            {
                Publisher publisher = AcAp.Publisher;
                PlotProgressDialog plotDlg = new PlotProgressDialog(false, this.sheetNum, true);
                publisher.PublishDsd(this.dsdFile, plotDlg);
                plotDlg.Destroy();
                File.Delete(this.dsdFile);
            }
      }

      private bool TryCreateDSD()
      {
            using (DsdData dsd = new DsdData())
            using (DsdEntryCollection dsdEntries = CreateDsdEntryCollection(this.layouts))
            {
                if (dsdEntries == null || dsdEntries.Count

                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.SheetType = SheetType.MultiDwf;
                dsd.NoOfCopies = 1;
                dsd.DestinationName = this.pdfFile;
                dsd.IsHomogeneous = false;
                dsd.LogFilePath = Path.Combine(this.outputDir, LOG);

                PostProcessDSD(dsd);

                return true;
            }
      }

      private DsdEntryCollection CreateDsdEntryCollection(IEnumerable 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;
      }

      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=6";
                  }
                  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);
      }
    }
}

Using example which creates a new instance of MultiSheetsPdf passing to the constructor the current drawing file name with "pdf" extension and all layouts except "Model":
      
      public void PlotPdf()
      {
            Database db = HostApplicationServices.WorkingDatabase;
            short bgp = (short)AcAp.GetSystemVariable("BACKGROUNDPLOT");
            try
            {
                AcAp.SetSystemVariable("BACKGROUNDPLOT", 0);
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                  List layouts = new List();
                  DBDictionary layoutDict =
                        (DBDictionary)db.LayoutDictionaryId.GetObject(OpenMode.ForRead);
                  foreach (DBDictionaryEntry entry in layoutDict)
                  {
                        if (entry.Key != "Model")
                        {
                            layouts.Add((Layout)tr.GetObject(entry.Value, OpenMode.ForRead));
                        }
                  }
                  layouts.Sort((l1, l2) => l1.TabOrder.CompareTo(l2.TabOrder));

                  string filename = Path.ChangeExtension(db.Filename, "pdf");

                  MultiSheetsPdf plotter = new MultiSheetsPdf(filename, layouts);
                  plotter.Publish();

                  tr.Commit();
                }
            }
            catch (System.Exception e)
            {
                Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
                ed.WriteMessage("\nError: {0}\n{1}", e.Message, e.StackTrace);
            }
            finally
            {
                AcAp.SetSystemVariable("BACKGROUNDPLOT", bgp);
            }
      }

T.Willey 发表于 2013-3-24 04:36:07

Hi Giles, "public MultiSheetsPdfPlot(" should be "public void MultiSheetsPdf(", if I am not wrong (always possible). Regards, Dale

BlackBox 发表于 2013-3-24 13:37:08

Oops !...
Indeed MultiSheetsPdfPlot should be MultiSheetsPdf (code edited), but not with void: it's a class constructor.

gile 发表于 2013-3-25 05:13:33

Yes of course. I actually had it correct on the second go.. I've been trying to build your routine into a batch (db.ReadDwgFile) process, but am finding it difficult. AutoCAD responds "A plot or publish job is already being processed in the background" etc, and just does a couple. I would post my code but I have been down so many rabbit holes that it is beyond posting atthe moment. I also used some guidance from the ADN plugin BatchPublish. Hmmm tricky. If I manage something useful I'll post. Dale
页: 1 [2]
查看完整版本: .NET Layout,ViewPort,Plot Routines