patterncsharpMinor
Changing PDF annotation with JavaScript code to jump to page into regular to Go To Page action
Viewed 0 times
jumpwithjavascriptintoregularactionpagecodechangingannotation
Problem
I have just written my first program in
I would appreciate if provide the changed code so and some comments so that I could see what was wrong and do some further reading to correct my mistakes. The program works fine.
```
using System;
using System.IO;
using System.Text.RegularExpressions;
using iTextSharp.text.pdf;
namespace pdfStamperMemory
{
class Program
{
static void Main(string[] args)
{
// searching for JS based on: http://stackoverflow.com/a/41386971/2657875
// MemoryStream based on: http://stackoverflow.com/a/23738927/2657875
byte[] bytes;
string script;
string input = Path.GetFullPath(args[0]);
string output = Path.Combine(Path.GetDirectoryName(input), Path.GetFileNameWithoutExtension(input) + "-itext.pdf");
using (var ms = new MemoryStream())
{
using (var reader = new PdfReader(input))
{
using (var stamper = new PdfStamper(reader, ms))
{
// get all page labels
string[] labels = PdfPageLabels.GetPageLabels(reader);
string[] arr = new string[labels.Length];
for (int i = 0; i = 1)
{
arr[i] = arr[i].Remove(0, 5);
}
}
for (int i = 1; i <= reader.NumberOfPages; i++)
{
// Get a page a PDF page
PdfDictionary page = reader.GetPageN(i);
// Get all the annotations of page i
PdfArray annotsArray = page.GetAsArray(PdfName.ANNOTS);
// If page does not have annotations
C#. Please explain:- Have I used any bad practices?
- How could the code be improved?
I would appreciate if provide the changed code so and some comments so that I could see what was wrong and do some further reading to correct my mistakes. The program works fine.
```
using System;
using System.IO;
using System.Text.RegularExpressions;
using iTextSharp.text.pdf;
namespace pdfStamperMemory
{
class Program
{
static void Main(string[] args)
{
// searching for JS based on: http://stackoverflow.com/a/41386971/2657875
// MemoryStream based on: http://stackoverflow.com/a/23738927/2657875
byte[] bytes;
string script;
string input = Path.GetFullPath(args[0]);
string output = Path.Combine(Path.GetDirectoryName(input), Path.GetFileNameWithoutExtension(input) + "-itext.pdf");
using (var ms = new MemoryStream())
{
using (var reader = new PdfReader(input))
{
using (var stamper = new PdfStamper(reader, ms))
{
// get all page labels
string[] labels = PdfPageLabels.GetPageLabels(reader);
string[] arr = new string[labels.Length];
for (int i = 0; i = 1)
{
arr[i] = arr[i].Remove(0, 5);
}
}
for (int i = 1; i <= reader.NumberOfPages; i++)
{
// Get a page a PDF page
PdfDictionary page = reader.GetPageN(i);
// Get all the annotations of page i
PdfArray annotsArray = page.GetAsArray(PdfName.ANNOTS);
// If page does not have annotations
Solution
Good things
Improvable things
-
Comments...if used they should describe why something is done in the way it is done. E.g showing edge cases, explain why a workaround of some kind is used.
Let the code itself tell the reader what is done by using meaningful and descriptive names for variables, methods and classes.
-
Naming things shouldn't involve abbreviations. For example look at these lines
Why don't you name it
-
Declarations of variables should be done as near as possible to their usage.Having e.g
-
If the right hand side of an assignement make the type of an object clear you should consider to use the var type.
Now let us dig a little bit into the code.
Using
this will save you two levels of indentation which prevents you from the need to scroll horizontally to see all of the code.
You have one big method where you stuffed in everything. You should check what parts of the code could be easily placed into a method.
Take for example this
by using a method like this
your main method will become shorter.
In general you should use more and shorter methods. This will makes it easier to read and understand the code and if you are hunting for a bug it will be easier to find.
This is a big no go. Don't place comments between an
If usingt the same regex like
Specifies that the regular expression is compiled to an assembly. This yields faster execution but increases startup time.
- You are using the
usingstatement to properly dispose objects which are implementingIDisposable.
- You are using braces
{}althought they might be optional
Improvable things
-
Comments...if used they should describe why something is done in the way it is done. E.g showing edge cases, explain why a workaround of some kind is used.
Let the code itself tell the reader what is done by using meaningful and descriptive names for variables, methods and classes.
-
Naming things shouldn't involve abbreviations. For example look at these lines
// For current annotation
PdfDictionary curAnnot = annotsArray.GetAsDict(j);Why don't you name it
currentAnnotation ? This would make the comment superflous. -
Declarations of variables should be done as near as possible to their usage.Having e.g
byte[] bytes; at the top of the method but using it only at the bottom of the method is not optimal. -
If the right hand side of an assignement make the type of an object clear you should consider to use the var type.
Now let us dig a little bit into the code.
using (var ms = new MemoryStream())
{
using (var reader = new PdfReader(input))
{
using (var stamper = new PdfStamper(reader, ms))
{Using
using is very good, but in this case it could/should be improved by stacking the usings like so using (var ms = new MemoryStream())
using (var reader = new PdfReader(input))
using (var stamper = new PdfStamper(reader, ms))
{this will save you two levels of indentation which prevents you from the need to scroll horizontally to see all of the code.
You have one big method where you stuffed in everything. You should check what parts of the code could be easily placed into a method.
Take for example this
// get all page labels
string[] labels = PdfPageLabels.GetPageLabels(reader);
string[] arr = new string[labels.Length];
for (int i = 0; i = 1)
{
arr[i] = arr[i].Remove(0, 5);
}
}by using a method like this
private static string[] GetPageLabels(PdfReader reader)
{
string[] labels = PdfPageLabels.GetPageLabels(reader);
if (!labels[0].Equals("Cover"))
{
return labels;
}
for (int i = 1; i < labels.Length; i++)
{
labels[i] = labels[i].Remove(0, 5);
}
return labels;
}your main method will become shorter.
In general you should use more and shorter methods. This will makes it easier to read and understand the code and if you are hunting for a bug it will be easier to find.
PdfDictionary annotAction = curAnnot.GetAsDict(PdfName.A);
if (annotAction == null)
{
Console.Write("Page {0} annotation {1}: no action\n", i, j);
}
// test if it is a JavaScript action
else if (PdfName.JAVASCRIPT.Equals(annotAction.Get(PdfName.S)))This is a big no go. Don't place comments between an
if and an else if. You or Sam the maintainer won't be able to see at first glance that they (if..else if) belong together. If usingt the same regex like
Regex regex = new Regex(@"pp_(.*)'"); in a loop you should consider to create the regex outside of the loop with this overloaded constructor using RegexOptions.Compiled Specifies that the regular expression is compiled to an assembly. This yields faster execution but increases startup time.
Code Snippets
// For current annotation
PdfDictionary curAnnot = annotsArray.GetAsDict(j);using (var ms = new MemoryStream())
{
using (var reader = new PdfReader(input))
{
using (var stamper = new PdfStamper(reader, ms))
{using (var ms = new MemoryStream())
using (var reader = new PdfReader(input))
using (var stamper = new PdfStamper(reader, ms))
{// get all page labels
string[] labels = PdfPageLabels.GetPageLabels(reader);
string[] arr = new string[labels.Length];
for (int i = 0; i < labels.Length; i++)
{
arr[i] += labels[i];
if ((arr[0].Equals("Cover")) && i >= 1)
{
arr[i] = arr[i].Remove(0, 5);
}
}private static string[] GetPageLabels(PdfReader reader)
{
string[] labels = PdfPageLabels.GetPageLabels(reader);
if (!labels[0].Equals("Cover"))
{
return labels;
}
for (int i = 1; i < labels.Length; i++)
{
labels[i] = labels[i].Remove(0, 5);
}
return labels;
}Context
StackExchange Code Review Q#154117, answer score: 3
Revisions (0)
No revisions yet.