This is related to my (unanswered) question here, but the code has changed considerably since I asked that question. I have a method that takes the filename of a PDF file and a Script object, and applies the Script to the PDF. If you are not familiar, PDFs support JavaScript to perform various tasks such as changing the content of documents, and scripts can be executed on various events such as on printing or saving.
A Script
has a ScriptText
, a ScriptField
, and a ScriptTiming
. The text is the JavaScript itself, the field is an object with a string Title
and four integers representing the coordinates of the field on the document, and the timing is an enum value used to determine when the script should be executed.
The method to add the script to the PDF is as follows:
private void AddScriptToPdf(string filename, Script script)
{
try
{
using (var pdfReader = new iTextSharp.text.pdf.PdfReader(filename))
{
using (var pdfStamper = new iTextSharp.text.pdf.PdfStamper(
pdfReader,
new System.IO.FileStream(
GetOutputPath(filename),
System.IO.FileMode.Create)))
{
var parentField
= iTextSharp.text.pdf.PdfFormField.CreateTextField(
pdfStamper.Writer,
false,
false,
0);
parentField.FieldName = script.ScriptField.Title;
for (var pageNumber = PdfFirstPageNumber;
pageNumber <= pdfReader.NumberOfPages;
pageNumber++)
{
var pdfContentByte = pdfStamper.GetOverContent(
pageNumber);
var textField = new iTextSharp.text.pdf.TextField(
pdfStamper.Writer,
new iTextSharp.text.Rectangle(
script.ScriptField.TopLeftX,
script.ScriptField.TopLeftY,
script.ScriptField.BottomRightX,
script.ScriptField.BottomRightY),
null);
var childField = textField.GetTextField();
parentField.AddKid(childField);
childField.PlaceInPage = pageNumber;
}
pdfStamper.AddAnnotation(parentField, 1);
var pdfAction
= iTextSharp.text.pdf.PdfAction.JavaScript(
script.ScriptText,
pdfStamper.Writer);
iTextSharp.text.pdf.PdfName actionType = null;
switch (script.ScriptTiming)
{
case ScriptTiming.DidPrint:
actionType
= iTextSharp.text.pdf.PdfWriter.DID_PRINT;
break;
case ScriptTiming.DidSave:
actionType
= iTextSharp.text.pdf.PdfWriter.DID_SAVE;
break;
case ScriptTiming.WillPrint:
actionType
= iTextSharp.text.pdf.PdfWriter.WILL_PRINT;
break;
case ScriptTiming.WillSave:
actionType
= iTextSharp.text.pdf.PdfWriter.WILL_SAVE;
break;
}
pdfStamper.Writer.SetAdditionalAction(
actionType,
pdfAction);
}
}
}
catch (iTextSharp.text.exceptions.InvalidPdfException e)
{
ShowMessage(e.Message + filename);
}
}
The method is long, but requires very little logic. It's pretty much step-by-step instructions. I know I could split it into several smaller methods, but considering they only ever run in sequence, I don't see the point of that. Is there any way I could actually make it better (or shorter)?