C2019-012: Merge pdfs

This commit is contained in:
2019-03-12 12:56:58 +00:00
parent cfcf9de352
commit 76bd61b435
13 changed files with 2331 additions and 1242 deletions

View File

@@ -0,0 +1,220 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using VEPROMS.CSLA.Library;
using iTextSharp.text;
using iTextSharp.text.pdf;
using DescriptiveEnum;
using JR.Utils.GUI.Forms;
namespace Volian.Print.Library
{
public class MergedPdfProc
{
private string _Title;
public string Title
{
get { return _Title; } // used for pdf outline
set { _Title = value; }
}
private int _PageCount; // number of pages in the particular pdf, to aid in determining total page count for merged pdf
public int PageCount
{
get { return _PageCount; }
set { _PageCount = value; }
}
private string _PdfFileName; // used for finding the procedure's pdf file to merge
public string PdfFileName
{
get { return _PdfFileName; }
set { _PdfFileName = value; }
}
public MergedPdfProc(string title, string pfname)
{
_Title = title;
_PdfFileName = pfname;
}
}
// this class will manage the data & do subsequent merging of pdf files. It is used if the user
// selects the 'Merge' button off of the print dialog when doing a Print All. (C2019-012)
public class MergedPdf
{
private List<MergedPdfProc> _mergedPdfs = null; // This list has all procedure pdfs that will be included in the merged file.
public List<MergedPdfProc> MergedPdfs
{
get { return _mergedPdfs; }
set { _mergedPdfs = value; }
}
string _mergedFileName = null; // this is the name to be given the merged file
public string MergedFileName
{
get { return _mergedFileName; }
set { _mergedFileName = value; }
}
private string _folder; // this is folder to create the merged file in
public string Folder
{
get { return _folder; }
set { _folder = value; }
}
private DocVersionInfo _docVersionInfo;
private string _pageof = null;
private iTextSharp.text.Font _itextFont = null;
private MergedPdfsPageNumCorner _corner;
private float _xloc = 0;
private float _yloc = 0;
// the following constructs the class that contains data for merging a group of pdfs.
public MergedPdf(string folder, DocVersionInfo dvi)
{
_folder = folder;
_docVersionInfo = dvi;
}
// the following merges the procedure pdfs into a single pdf
public bool DoTheMerge()
{
if (MergedPdfs == null)
{
FlexibleMessageBox.Show("There are no PDFs to merge.", "Merging Pdfs Error", MessageBoxButtons.OK);
return false;
}
iTextSharp.text.Document doc = new iTextSharp.text.Document();
string slashReplace = _docVersionInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SlashReplace ?? "_";
MergedFileName = _folder + @"\" + _docVersionInfo.MyFolder.Name.Replace("/", slashReplace).Replace("\\", slashReplace) + ".pdf";
MergedFileName = ItemInfo.StripRtfFormatting(MergedFileName);
PdfWriter writer = null;
// see if it can be created and if not, see if it is open and tell user:
try
{
writer = PdfWriter.GetInstance(doc, new FileStream(MergedFileName, FileMode.Create));
}
catch (Exception ex)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Could not create");
sb.AppendLine();
sb.AppendLine(MergedFileName + ".");
sb.AppendLine();
sb.AppendLine("If it is open, close and retry.");
FlexibleMessageBox.Show(sb.ToString(), "Error on CreatePdf", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
if (writer == null) return false;
doc.Open();
PdfContentByte canvas = writer.DirectContent;
int mergedPageNumber = 0; // this is the number that will be used for the <page> token (for <page> of <of>)
int totalPages = 0; // this is the number that will be used for the <of> token (for <page> of <of>)
foreach (MergedPdfProc mpp in MergedPdfs) totalPages += mpp.PageCount;
bool doPageNum = GetPageOfInfo(); // get the format and location of page number - this can be reused for each procedure
// the MergedPdfs contains a list of all of the procedures' pdfs that will be merged into the final pdf
foreach (MergedPdfProc mpp in MergedPdfs)
{
string pdffilename = _folder + @"\" + mpp.PdfFileName;
if (!File.Exists(pdffilename))
{
FlexibleMessageBox.Show("Error in finding pdf files to merge. Cannot print with date/time as part of pdf name. Or check that individual pdfs were generated.", "Error on CreatePdf", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
PdfReader reader = new PdfReader(_folder + @"\" + mpp.PdfFileName);
int numPages = reader.NumberOfPages;
int currentPageNumber = 0;
PdfOutline outline = null;
do // merging pages into complete...
{
currentPageNumber += 1;
mergedPageNumber += 1;
doc.SetPageSize(PageSize.LETTER);
doc.NewPage();
PdfImportedPage page = writer.GetImportedPage(reader, currentPageNumber); // gets a page that is 'ready' to be written to combined pdf
if (doPageNum) // get the string & fill in with <page> and <of> numbers
{
string outputpageof = _pageof.Replace("<page>", mergedPageNumber.ToString()).Replace("<of>", totalPages.ToString());
AddPageNumberToPage(page, canvas, outputpageof);
}
PdfDestination dest = new PdfDestination(PdfDestination.FIT);
// if on the first page, add the pdfname & title as part of outline. If on remaining pages, just put out page number.
// Later this may need expanded to put sections/steps/etc.
if (currentPageNumber == 1)
outline = new PdfOutline(canvas.RootOutline, dest, mpp.PdfFileName.Replace(".pdf", "")+" - "+mpp.Title, false);
else
new PdfOutline(outline, dest, "Page " + currentPageNumber.ToString(), false);
canvas.AddTemplate(page, 0, 0); // adds the page to the combined pdf
} while (currentPageNumber < numPages);
}
doc.Close();
return true;
}
// this method adds the page number to the page before it is merged in. It determines the position from the properties
// that were set on the doc version properties dialog (these values were set as local class variables from GetPageOfInfo)
private void AddPageNumberToPage(PdfImportedPage page, PdfContentByte cb, string outputpage)
{
float pgright = page.BoundingBox.Right;
float pgleft = page.BoundingBox.Left;
float pgtop = page.BoundingBox.Top;
float pgbot = page.BoundingBox.Bottom;
Phrase ph = new Phrase();
Chunk chk = new Chunk(outputpage, _itextFont);
ph.Add(chk);
Paragraph pg = new Paragraph(ph);
ColumnText columnText = new ColumnText(cb);
switch (_corner)
{
case MergedPdfsPageNumCorner.TopRight:
columnText.Alignment = Element.ALIGN_RIGHT;
columnText.SetSimpleColumn(0, pgtop - _yloc, pgright - _xloc, 0);
break;
case MergedPdfsPageNumCorner.BottomRight:
columnText.Alignment = Element.ALIGN_RIGHT;
columnText.SetSimpleColumn(0, _yloc, pgright - _xloc, 0);
break;
case MergedPdfsPageNumCorner.TopLeft:
columnText.SetSimpleColumn(_xloc, pgtop - _yloc, pgright, 0); // page alignment defaults to ALIGN_LEFT
break;
case MergedPdfsPageNumCorner.BottomLeft:
columnText.SetSimpleColumn(_xloc, _yloc, pgright, 0); // page alignment defaults to ALIGN_LEFT
break;
}
columnText.AddText(pg);
columnText.Go();
}
// this method gets the format, font & location data from the doc version properties that are stored on the doc version's
// config field. It saves them as local class variables to be used in other places in this class.
private bool GetPageOfInfo()
{
DocVersionConfig dvc = (DocVersionConfig) _docVersionInfo.MyConfig;
MergedPdfsPageOf po = dvc.Print_MergedPdfsPageOf;
string tmp = EnumDescConverter.GetEnumDescription((Enum)dvc.Print_MergedPdfsPageOf);
if (tmp == "None") return false; // no page number, return false so no page number is put out.
// If 'Other' for the format, use text in textbox to format the <page> of <of> string, note that <page> and <of> are
// resolved when adding pages to the merge document. The only other 'token' that is supported is '<set>'
if (tmp == "Other") tmp = dvc.Print_MergedPdfsPageNumFormatOther;
_pageof = tmp.Replace("<set>", _docVersionInfo.MyFolder.Name);
// If font data is not supplied, use the default from the format for this working draft
string famtmp = dvc.Print_MergedPdfsPageNumFont;
if (famtmp == null || famtmp == "")
{
famtmp = _docVersionInfo.ActiveFormat.PlantFormat.FormatData.Font.Family;
}
tmp = dvc.Print_MergedPdfsPageNumFontSize;
float? tmpi=0;
if (tmp == null || tmp == "")
{
// use the default from the format from this working draft
tmpi = _docVersionInfo.ActiveFormat.PlantFormat.FormatData.Font.Size;
}
else
tmpi = int.Parse(tmp);
// set local values of variables to be used in various other methods in this class.
_itextFont = Volian.Svg.Library.Svg.GetFont(famtmp, (float)tmpi, 0, System.Drawing.Color.Black);
_xloc = (float)dvc.Print_MergedPdfsPageNumLocX * 72;
_yloc = (float)dvc.Print_MergedPdfsPageNumLocY * 72;
_corner = dvc.Print_MergedPdfsPageNumCorner;
return true;
}
}
}

View File

@@ -259,9 +259,22 @@ namespace Volian.Print.Library
get { return _BlankPageText; }
set { _BlankPageText = value; }
}
// use DidAll & MergeNotIncuded to know that printing all (not single) was done. Used w/ merge code to know when to return, i.e. not include in merged pdf
private bool _DidAll;
public bool DidAll // value passed in from frmPdfStatusForm
{
get { return _DidAll; }
set { _DidAll = value; }
}
private bool _MergeNotIncluded;
public bool MergeNotIncluded
{
get { return _MergeNotIncluded; }
set { _MergeNotIncluded = value; }
}
public PromsPrinter(ItemInfo myItem, string rev, string watermark, bool debugOutput, bool origPgBrk, string backgroundFolder, bool openPDF, bool overWrite,
ChangeBarDefinition cbd, String pdfFile, bool insertBlankPages, bool batchPrint, string prefix, bool saveLinks, bool removeTrailngHardReturnsAndManualPageBreaks, string blankPageText)
ChangeBarDefinition cbd, String pdfFile, bool insertBlankPages, bool batchPrint, string prefix, bool saveLinks, bool removeTrailngHardReturnsAndManualPageBreaks, string blankPageText, bool didAll)
{
Prefix = prefix; // RHM20150506 Multiline ItemID TextBox
_MyItem = myItem;
@@ -280,6 +293,8 @@ namespace Volian.Print.Library
_SaveLinks = saveLinks;
_RemoveTrailingHardReturnsAndManualPageBreaks = removeTrailngHardReturnsAndManualPageBreaks;
_BlankPageText = blankPageText;
_DidAll = didAll;
_MergeNotIncluded = false;
//_MyReaderHelper.LoadTree(myItem);
}
// Pass 1 PDF Name
@@ -299,7 +314,14 @@ namespace Volian.Print.Library
public string Print(string pdfFolder, bool makePlacekeeper, bool makeContinuousActionSummary)
{
if (_MyItem is ProcedureInfo)
{ // B2017-186 First do Procedures that don't have page number transitions
{
ProcedureConfig pcfg = (ProcedureConfig)(_MyItem as ProcedureInfo).MyConfig;
if (DidAll && pcfg.Print_NotInMergeAll) // will be merging a pdf, so don't print this procedure if user set that on procedure propertures
{
_MergeNotIncluded = true;
return null;
}
// B2017-186 First do Procedures that don't have page number transitions
if (!(_MyItem.ActiveFormat.PlantFormat.FormatData.TransData.UseTransitionModifier ||
_MyItem.ActiveFormat.PlantFormat.FormatData.TransData.UseSpecificTransitionModifier))
{
@@ -446,11 +468,13 @@ namespace Volian.Print.Library
_PROMSVersionLayer.SetPrint("PROMS Version", true);
}
}
public static int ProcPageCount = -1; // Used to count page numbers in each pdf. This will be used if/when pdfs are merged together.
private void CloseDocument(string fileName)
{
int profileDepth = ProfileTimer.Push(">>>> CloseDocument");
try
{
ProcPageCount = MyContentByte.PdfWriter.CurrentPageNumber - 1;
MyContentByte.PdfDocument.Close();
MyContentByte = null;
}