1

I am using itextsharp to programmatically generate replies to PDF annotations. Everything seems fine, except that the generated replies do not get sorted in chronologic order in Acrobat DC. It appears above manually-created replies, even though it has a later timestamp. Please see image below, showing how it appears on Acrobat DC.

Auto generated reply appearing above manual replies despite having a later timestamp:

Auto generated reply appearing above manual replies despite having a later timestamp

The following is my code:

PdfArray originalRect = originalAnnot.GetAsArray(PdfName.RECT);

Rectangle replyRect = new Rectangle(
    originalRect.GetAsNumber(0).FloatValue, originalRect.GetAsNumber(1).FloatValue,
    originalRect.GetAsNumber(2).FloatValue, originalRect.GetAsNumber(3).FloatValue
);

PdfAnnotation replySticky = PdfAnnotation.CreateText(stamper.Writer, replyRect, author, change.ReplyToAdd, true, "Comment");
replySticky.Put(PdfName.IRT, annots.getAsIndirectObject(i));
replySticky.Put(PdfName.CREATIONDATE, new PdfDate(DateTime.Now));
replySticky.Put(PdfName.M, new PdfDate(DateTime.Now));
replySticky.Put(PdfName.AUTHOR, new PdfString(author));
replySticky.Put(PdfName.NM, new PdfString(Guid.NewGuid().ToString()));

replySticky.Put(new PdfName("Subj"), new PdfString("Sticky Note"));
PdfNumber n = originalAnnot.GetAsNumber(PdfName.F);
replySticky.Put(PdfName.F, new PdfNumber(n.IntValue | PdfAnnotation.FLAGS_HIDDEN));

stamper.AddAnnotation(replySticky, page);

Am I missing some attribute that determines display order in Acrobat? Thanks!

Updated: There is a question on how I am getting the value for originalAnnot. Before writing to the PDF, I will retrieve all existing annotations, and store them in a dictionary, using a key that is a combination of the page number and the NM value of the annotation. Here is the code fragment:

Dictionary<string, Annotation> annotationMap = new Dictionary<string, Annotation>();

pdfReader = new PdfReader(inputPath, password);

// First pass to read annotations
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
    //get the PdfDictionary of the 1st page
    PdfDictionary pageDict = pdfReader.GetPageN(page);

    //get annotation array
    PdfArray annotArray = pageDict.GetAsArray(PdfName.ANNOTS);

    if (annotArray == null)
    {
        continue;
    }

    //iterate through annotation array
    int size = annotArray.Size;
    for (int i = 0; i < size; i++)
    {
        PdfDictionary dict = annotArray.GetAsDict(i);

        string name = getStringFromPDFString(dict.GetAsString(PdfName.NM));
        string author = getStringFromPDFString(dict.GetAsString(PdfName.T));

        if (name != string.Empty && author != string.Empty)
        {
            string contents = getStringFromPDFString(dict.GetAsString(PdfName.CONTENTS));
            string subType = getSubType((PdfName)dict.GetAsName(PdfName.SUBTYPE));
            string moddate = getStringFromPDFString(dict.GetAsString(PdfName.M));
            string state = getStringFromPDFString(dict.GetAsString(PdfName.STATE));
            string inreplyto = getStringFromPDFString(pdfDictionary.GetAsString(PdfName.NM));
            string key = string.Format("{0}={1}", page, name);

            if (annotationMap.ContainsKey(key))
            {
                Console.WriteLine(string.Format("Annotation with duplicate key {0} ignored", key));
                continue;
            }

            string context = string.Empty;
            string highlightedtext = getHighlightText(dict, page, pdfReader, out context);

            Annotation ann = new Annotation(name, moddate, subType, author, page, inputPath, contents, inreplyto, state, context, highlightedtext, dict, annotArray.GetAsIndirectObject(i));
            annotationMap.Add(ann.Identifier, ann);
        }
    } // Each annotation
} // Each page
mkl
  • 90,588
  • 15
  • 125
  • 265
Goh Kelvin
  • 11
  • 3
  • Could you add more code? I'd like to know what the originalAnnot is pointing towards. If it's the first annotation in the line of comments, then you're setting the IRT values incorrectly, but before I know that I can't say so with certainty. – Michaël Demey Aug 24 '17 at 14:53
  • Hi, I added more code to show how I read the read the original annotations into a dictionary. I will search for the annotation to reply to using its unique ID. – Goh Kelvin Aug 25 '17 at 01:47
  • 1
    Hi Michaël, what should I set the IRT to, in the above example? Should I set it to the NM value of the last reply (Manual reply 2) instead of the original comment? – Goh Kelvin Aug 25 '17 at 05:37

0 Answers0