232 lines
9.6 KiB
C#
232 lines
9.6 KiB
C#
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 static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
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 = null;
|
|
try // B2019-041: added a try/catch for when a corrupt pdf was created for a procedure, just skip & add message to error log.
|
|
{
|
|
reader = new PdfReader(_folder + @"\" + mpp.PdfFileName);
|
|
int numPages = reader.NumberOfPages;
|
|
int currentPageNumber = 0;
|
|
PdfOutline outline = null;
|
|
Rectangle paperSize = PDFPageSize.UsePaperSize(_docVersionInfo.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize); // C2020-002 paper size is now set in the format files
|
|
do // merging pages into complete...
|
|
{
|
|
currentPageNumber += 1;
|
|
mergedPageNumber += 1;
|
|
doc.SetPageSize(paperSize);
|
|
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);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
string tmp = string.Format("Error merging pdf {0}", mpp.PdfFileName);
|
|
_MyLog.Error(tmp, ex);
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
}
|