Печать нескольких листов в PDF

Автор Тема: Печать нескольких листов в PDF  (Прочитано 8843 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн AlexxАвтор темы

  • ADN OPEN
  • **
  • Сообщений: 76
  • Карма: 1
Добрый день!

Пытаюсь сделать печать нескольких листов в PDF с сохранением слоев (OCG) в конечном PDF. Так же, как это делается при выполнении команды Publish в DWG TrueView. Пытался делать как описано в данной статье: http://through-the-interface.typepad.com/through_the_interface/2007/09/driving-a-multi.html
Но на выходе получается PDF у которой слои (OCG) только на первом листе, а на всех остальных листах слоев нет. Помогите, пожалуйста, разобраться с этой проблемой. Заранее спасибо!

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Печать нескольких листов в PDF
« Ответ #1 : 02-03-2016, 11:21:57 »
1. Код (полный проект).
2. Примеры чертежей.
3. Версия AutoCAD.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexxАвтор темы

  • ADN OPEN
  • **
  • Сообщений: 76
  • Карма: 1
Re: Печать нескольких листов в PDF
« Ответ #2 : 02-03-2016, 11:51:09 »
Полный проект выкладывать нет смысла, так как там очень много всего и куча ссылок на другие проекты. Вот код метода, который выводит листы на печать:

Код - C# [Выбрать]
  1.         public static void PlotToPdf(IEnumerable<string> sheets, string fileName)
  2.         {
  3.             if (PlotFactory.ProcessPlotState != ProcessPlotState.NotPlotting)
  4.                 throw new Exception("Печать уже запущена");
  5.  
  6.             var doc = Application.DocumentManager.MdiActiveDocument;
  7.             var db = doc.Database;
  8.  
  9.             using (var tr = db.TransactionManager.StartTransaction())
  10.             {
  11.                 using (var pe = PlotFactory.CreatePublishEngine())
  12.                 {
  13.                     var piv = new PlotInfoValidator();
  14.                     piv.MediaMatchingPolicy = MatchingPolicy.MatchEnabled;
  15.                    
  16.                     var numLayout = 1;
  17.                     var layouts = new List<string>(sheets);
  18.  
  19.                     foreach (string layout in layouts)
  20.                     {
  21.                         LayoutManager.Current.CurrentLayout = layout;
  22.  
  23.                         var btr = (BlockTableRecord)tr.GetObject(
  24.                             db.CurrentSpaceId, OpenMode.ForRead);
  25.  
  26.                         var lt = (Layout)tr.GetObject(
  27.                             btr.LayoutId, OpenMode.ForRead);
  28.  
  29.                         // PlotSettings
  30.                         var ps = new PlotSettings(lt.ModelType);
  31.                         ps.CopyFrom(lt);
  32.                         ps.PrintLineweights = true;
  33.                         ps.PlotTransparency = false;
  34.                         ps.PlotPlotStyles = true;
  35.                         ps.PlotHidden = false;
  36.                        
  37.                         // PlotSettingsValidator
  38.                         var psv = PlotSettingsValidator.Current;
  39.                         psv.RefreshLists(ps);
  40.                         psv.SetPlotType(ps, Autodesk.AutoCAD.DatabaseServices.PlotType.Extents);
  41.                         psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);
  42.                         psv.SetUseStandardScale(ps, true);
  43.                         psv.SetPlotCentered(ps, true);
  44.                         psv.SetCurrentStyleSheet(ps, "monochrome.ctb");
  45.                         psv.SetPlotConfigurationName(ps, "DWG To PDF.pc3",
  46.                             "ISO_full_bleed_A1_(594.00_x_841.00_MM)");
  47.  
  48.                         // PlotInfo
  49.                         var pi = new PlotInfo();
  50.                         pi.Layout = lt.Id;
  51.                         pi.OverrideSettings = ps;
  52.  
  53.                         // PlotInfoValidator
  54.                         piv.Validate(pi);
  55.  
  56.                         if (numLayout == 1)
  57.                         {
  58.                             // PlotEngine
  59.                             pe.BeginPlot(null, null);
  60.                             pe.BeginDocument(pi, doc.Name, null, 1, true, fileName);
  61.                         }
  62.  
  63.                         // PlotEngine
  64.                         var ppi = new PlotPageInfo();
  65.                         pe.BeginPage(ppi, pi, (layouts.Count == numLayout), null);
  66.                         pe.BeginGenerateGraphics(null);
  67.                         pe.EndGenerateGraphics(null);
  68.                         pe.EndPage(null);
  69.  
  70.                         numLayout++;
  71.                     }
  72.  
  73.                     // PlotEngine
  74.                     pe.EndDocument(null);
  75.                     pe.EndPlot(null);
  76.                 }
  77.             }
  78.         }

Чертеж подойдет любой, где есть несколько слоев и объекты на них.
Версия -  AutoCAD 2014

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Печать нескольких листов в PDF
« Ответ #3 : 02-03-2016, 14:36:03 »
Полный проект выкладывать нет смысла, так как там очень много всего и куча ссылок на другие проекты.
Я имел в виду не твой проект, а специально подготовленный тестовый проект, на котором я смог бы воспроизвести (или не воспроизвести) указанное тобой поведение. И если такое поведение воспроизводится отправить его в ADN DevHelp для того, чтобы они подсказали как исправить такое поведение.
Короче говоря, если ты заинтересован в помощи, то подготовь тестовый проект, пример чертежа, запиши видео что у тебя получается и что бы ты хотел получить.

Ну и заодно проверь какой результат даёт стандартная команда _PUBLISH в этом случае. Честно говоря я не очень понимаю на какой список слоёв ты расчитываешь в многостраничном файле. Скорее всего этот список действительно формируется из первого файла (страницы).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexxАвтор темы

  • ADN OPEN
  • **
  • Сообщений: 76
  • Карма: 1
Re: Печать нескольких листов в PDF
« Ответ #4 : 02-03-2016, 15:39:38 »
В архиве тестовый проект, чертеж и PDF-файлы, полученные при помощи публикации AutoCAD и при помощи плагина.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Печать нескольких листов в PDF
« Ответ #5 : 02-03-2016, 19:43:08 »
Я посмотрел пример и исходники и понял, что таким путём ты не получишь нужного тебе результата. Только _PUBLISH или Autodesk.AutoCAD. Publishing.Publisher.PublishExecute() (http://adndevblog.typepad.com/autocad/2012/05/how-to-use-autodeskautocadpublishingpublisherpublishexecute.html).
Т.е. тебе сначала нужно создать правильный DSD-файл, а затем выполнить публикацию. Можно так, как по ссылке выше, а можно с использованием COM: http://adn-cis.org/publikacziya-listov-v-pdf-s-pomoshhyu-com-api.html
При использовании CreatePublishEngine создаётся многолистовой PDF, но примитивы не имеют слоев во втором и последующих листах.
Я не знаю баг ли это или так и задумано, но факт остаётся фактом.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexxАвтор темы

  • ADN OPEN
  • **
  • Сообщений: 76
  • Карма: 1
Re: Печать нескольких листов в PDF
« Ответ #6 : 02-03-2016, 20:19:49 »
Александр, спасибо Вам за ответ. Проблема в том, что мне нужно вывести на печать не все листы, а выбранные. Насколько я понял, в первом примере можно это сделать, а в примере с COM - нельзя?

Отмечено как Решение Alexx 03-03-2016, 13:37:27

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Печать нескольких листов в PDF
« Ответ #7 : 02-03-2016, 21:27:09 »
Вот решение от Gilles Chanteau: http://www.acadnetwork.com/index.php?topic=315.0
От меня лишь минимальные исправления, связанные с опечатками у него в коде:
Код - C# [Выбрать]
  1. using System.IO;
  2. using System.Collections.Generic;
  3. using Autodesk.AutoCAD.Runtime;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.PlottingServices;
  6. using Autodesk.AutoCAD.ApplicationServices;
  7. using Autodesk.AutoCAD.EditorInput;
  8.  
  9. using System.Text;
  10. using Autodesk.AutoCAD.Publishing;
  11. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  12.  
  13. namespace Plottings
  14. {
  15.   public class MultiSheetsPdf
  16.   {
  17.     private string dwgFile, pdfFile, dsdFile, outputDir;
  18.     private int sheetNum;
  19.     private IEnumerable<Layout> layouts;
  20.  
  21.     private const string LOG = "publish.log";
  22.  
  23.     public MultiSheetsPdf(string pdfFile, IEnumerable<Layout> layouts)
  24.     {
  25.       Database db = HostApplicationServices.WorkingDatabase;
  26.       this.dwgFile = db.Filename;
  27.       this.pdfFile = pdfFile;
  28.       this.outputDir = Path.GetDirectoryName(this.pdfFile);
  29.       this.dsdFile = Path.ChangeExtension(this.pdfFile, "dsd");
  30.       this.layouts = layouts;
  31.     }
  32.  
  33.     public void Publish()
  34.     {
  35.       if (TryCreateDSD())
  36.       {
  37.         Publisher publisher = AcAp.Publisher;
  38.         PlotProgressDialog plotDlg = new PlotProgressDialog(false, this.sheetNum, true);
  39.         publisher.PublishDsd(this.dsdFile, plotDlg);
  40.         plotDlg.Destroy();
  41.         File.Delete(this.dsdFile);
  42.       }
  43.     }
  44.  
  45.     private bool TryCreateDSD()
  46.     {
  47.       using (DsdData dsd = new DsdData())
  48.       using (DsdEntryCollection dsdEntries = CreateDsdEntryCollection(this.layouts))
  49.       {
  50.         if (dsdEntries == null || dsdEntries.Count <= 0) return false;
  51.  
  52.         if (!Directory.Exists(this.outputDir))
  53.           Directory.CreateDirectory(this.outputDir);
  54.  
  55.         this.sheetNum = dsdEntries.Count;
  56.  
  57.         dsd.SetDsdEntryCollection(dsdEntries);
  58.  
  59.         dsd.SetUnrecognizedData("PwdProtectPublishedDWF", "FALSE");
  60.         dsd.SetUnrecognizedData("PromptForPwd", "FALSE");
  61.         dsd.SheetType = SheetType.MultiDwf;
  62.         dsd.NoOfCopies = 1;
  63.         dsd.DestinationName = this.pdfFile;
  64.         dsd.IsHomogeneous = false;
  65.         dsd.LogFilePath = Path.Combine(this.outputDir, LOG);
  66.  
  67.         PostProcessDSD(dsd);
  68.  
  69.         return true;
  70.       }
  71.     }
  72.  
  73.     private DsdEntryCollection CreateDsdEntryCollection(IEnumerable<Layout> layouts)
  74.     {
  75.       DsdEntryCollection entries = new DsdEntryCollection();
  76.  
  77.       foreach (Layout layout in layouts)
  78.       {
  79.         DsdEntry dsdEntry = new DsdEntry();
  80.         dsdEntry.DwgName = this.dwgFile;
  81.         dsdEntry.Layout = layout.LayoutName;
  82.         dsdEntry.Title = Path.GetFileNameWithoutExtension(this.dwgFile) + "-" + layout.LayoutName;
  83.         dsdEntry.Nps = layout.TabOrder.ToString();
  84.         entries.Add(dsdEntry);
  85.       }
  86.       return entries;
  87.     }
  88.  
  89.     private void PostProcessDSD(DsdData dsd)
  90.     {
  91.       string str, newStr;
  92.       string tmpFile = Path.Combine(this.outputDir, "temp.dsd");
  93.  
  94.       dsd.WriteDsd(tmpFile);
  95.  
  96.       using (StreamReader reader = new StreamReader(tmpFile, Encoding.Default))
  97.       using (StreamWriter writer = new StreamWriter(this.dsdFile, false, Encoding.Default))
  98.       {
  99.         while (!reader.EndOfStream)
  100.         {
  101.           str = reader.ReadLine();
  102.           if (str.Contains("Has3DDWF"))
  103.           {
  104.             newStr = "Has3DDWF=0";
  105.           }
  106.           else if (str.Contains("OriginalSheetPath"))
  107.           {
  108.             newStr = "OriginalSheetPath=" + this.dwgFile;
  109.           }
  110.           else if (str.Contains("Type"))
  111.           {
  112.             newStr = "Type=6";
  113.           }
  114.           else if (str.Contains("OUT"))
  115.           {
  116.             newStr = "OUT=" + this.outputDir;
  117.           }
  118.           else if (str.Contains("IncludeLayer"))
  119.           {
  120.             newStr = "IncludeLayer=TRUE";
  121.           }
  122.           else if (str.Contains("PromptForDwfName"))
  123.           {
  124.             newStr = "PromptForDwfName=FALSE";
  125.           }
  126.           else if (str.Contains("LogFilePath"))
  127.           {
  128.             newStr = "LogFilePath=" + Path.Combine(this.outputDir, LOG);
  129.           }
  130.           else
  131.           {
  132.             newStr = str;
  133.           }
  134.           writer.WriteLine(newStr);
  135.         }
  136.       }
  137.       File.Delete(tmpFile);
  138.     }
  139.   }
  140. }
  141.  
  142.  
  143.  
  144. namespace PublishToPdf
  145. {
  146.   public class Commands : IExtensionApplication
  147.   {
  148.     [CommandMethod("PlotPdf")]
  149.     public void PlotPdf()
  150.     {
  151.       Database db = HostApplicationServices.WorkingDatabase;
  152.       short bgp = (short)AcAp.GetSystemVariable("BACKGROUNDPLOT");
  153.       try
  154.       {
  155.         AcAp.SetSystemVariable("BACKGROUNDPLOT", 0);
  156.         using (Transaction tr = db.TransactionManager.StartTransaction())
  157.         {
  158.           List<Layout> layouts = new List<Layout>();
  159.           DBDictionary layoutDict =
  160.               (DBDictionary)db.LayoutDictionaryId.GetObject(OpenMode.ForRead);
  161.           foreach (DBDictionaryEntry entry in layoutDict)
  162.           {
  163.             layouts.Add((Layout)tr.GetObject(entry.Value, OpenMode.ForRead));
  164.           }
  165.           layouts.Sort((l1, l2) => l1.TabOrder.CompareTo(l2.TabOrder));
  166.  
  167.           string filename = Path.ChangeExtension(db.Filename, "pdf");
  168.  
  169.           Plottings.MultiSheetsPdf plotter = new Plottings.MultiSheetsPdf(filename, layouts);
  170.           plotter.Publish();
  171.  
  172.           tr.Commit();
  173.         }
  174.       }
  175.       catch (System.Exception e)
  176.       {
  177.         Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
  178.         ed.WriteMessage("\nError: {0}\n{1}", e.Message, e.StackTrace);
  179.       }
  180.       finally
  181.       {
  182.         AcAp.SetSystemVariable("BACKGROUNDPLOT", bgp);
  183.       }
  184.     }
  185.  
  186.     public void Initialize() { }
  187.     public void Terminate() { }
  188.   }
  189. }

Проверял в AutoCAD 2016, но думаю что и в предыдущих нормально работает.
Результат работы для твоего файла смотри в прикреплении.
Какие именно листы ты будешь печатать определяешь в функции PlotPdf передавая правильную коллекцию layouts.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Печать нескольких листов в PDF
« Ответ #8 : 02-03-2016, 21:33:06 »
Насколько я понял, в первом примере можно это сделать, а в примере с COM - нельзя?
Можно. Нужно в DSD-файл записать только нужные листы.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexxАвтор темы

  • ADN OPEN
  • **
  • Сообщений: 76
  • Карма: 1
Re: Печать нескольких листов в PDF
« Ответ #9 : 02-03-2016, 22:16:44 »
Александр, спасибо большое! Завтра доберусь до компа и проверю. После обязательно отпишусь)

Оффлайн AlexxАвтор темы

  • ADN OPEN
  • **
  • Сообщений: 76
  • Карма: 1
Re: Печать нескольких листов в PDF
« Ответ #10 : 03-03-2016, 13:37:51 »
Александр, все получилось! Спасибо большое!

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Печать нескольких листов в PDF
« Ответ #11 : 03-03-2016, 13:43:25 »
Ну и отлично. Единственное ограничение - листы должны быть подготовлены для печати, т.е. должна быть предварительно установлена конфигурация печати для каждого из листов.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexxАвтор темы

  • ADN OPEN
  • **
  • Сообщений: 76
  • Карма: 1
Re: Печать нескольких листов в PDF
« Ответ #12 : 03-03-2016, 17:18:28 »
Да, это я понял.

Кстати визуально сравнил PDF сделанный через PUBLISH и через PLOT (надеюсь, понятно выразился).
Судя по всему при PUBLISH в PDF добавляется рамка (содержимое получается немного сжатым):

Наложил изображение, полученное при PUBLISH (черным) на изображение, полученное при PLOT (зеленым):



Интересно, есть способ сделать PDF идентичным тому, что получается через PLOT, т.е. без "рамки"?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Печать нескольких листов в PDF
« Ответ #13 : 03-03-2016, 17:22:26 »
Интересно, есть способ сделать PDF идентичным тому, что получается через PLOT, т.е. без "рамки"?
Сомневаюсь. Кстати, в DSD-файле AutoCAD 2016 появились новые опции. Возможно они могли бы помочь.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexxАвтор темы

  • ADN OPEN
  • **
  • Сообщений: 76
  • Карма: 1
Re: Печать нескольких листов в PDF
« Ответ #14 : 03-03-2016, 17:24:37 »
Да в принципе ничего страшного :) Просто немного удивило.
Еще раз спасибо за помощь!