logo
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Options
Go to last post Go to first unread
claudiu  
#1 Posted : Monday, July 15, 2019 1:50:14 PM(UTC)
claudiu

Rank: Newbie

Groups: Registered
Joined: 6/6/2019(UTC)
Posts: 4
Canada

Thanks: 2 times
Hello,

I have multiple documents with signature fields and my requirement is to merge the documents into one file before it is sent to signing. My problem is that after merge, my final document does not have the signature boxes. The merging is done by creating a new document and using ImportPages to concatenate the documents:

Code:

                var mergedPdf = PdfDocument.CreateNew();
                int bookmarkIndex = 0;
                foreach (var d in docs)
                {
                    var pass = CipherHelper.Decrypt<RijndaelManaged>(d.PASSWORD, ConfigHelper.Secret, ConfigHelper.Salt);
                    var tmpDoc = PdfDocument.Load(d.CONTENT,null, pass);
                    int index = mergedPdf.Pages.Count;
                    mergedPdf.Pages.ImportPages(tmpDoc, null, index);
                    if (mergedPdf.Pages.Count > 0)
                    {
                        mergedPdf.Bookmarks.InsertAt(bookmarkIndex, d.FILENAME, mergedPdf.Pages[index]);
                        bookmarkIndex++;
                    }
                }
 


Is there any way to fix this issue or an alternative merging method?

Thank You!
Paul Rayman  
#2 Posted : Tuesday, July 16, 2019 11:11:38 PM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 840

Thanks: 2 times
Was thanked: 103 time(s) in 101 post(s)
This happens because the AcroForm dictionary is not imported.
You can import this dictionary yourself. For example, like this:

Usage
Code:
var mergedPdf = PdfDocument.CreateNew();
var tmpDoc = PdfDocument.Load(@"e:\11\test.pdf");
mergedPdf.Pages.ImportPages(tmpDoc, null, 0);
ImportAcroForm(tmpDoc, mergedPdf);
mergedPdf.Save(@"e:\11\signew.pdf", Patagames.Pdf.Enums.SaveFlags.NoIncremental);


and ImportAcroForm
Code:
private void ImportAcroForm(PdfDocument srcDoc, PdfDocument dstDoc)
{
    if (!srcDoc.Root.ContainsKey("AcroForm"))
        return;

    var list = PdfIndirectList.FromPdfDocument(dstDoc);
    PdfTypeDictionary acroForm = srcDoc.Root["AcroForm"].As<PdfTypeDictionary>().Clone() as PdfTypeDictionary;
    list.Add(acroForm);
    dstDoc.Root.SetIndirectAt("AcroForm", list, acroForm);

    if (acroForm.ContainsKey("Fields"))
        acroForm["Fields"].As<PdfTypeArray>().Clear();
    else
        acroForm["Fields"] = PdfTypeArray.Create();

    foreach (var page in dstDoc.Pages)
    {
        if (page.Annots == null)
            continue;
        foreach(var annot in page.Annots)
        {
            if (annot is PdfWidgetAnnotation)
                acroForm["Fields"].As<PdfTypeArray>().AddIndirect(list, annot.Dictionary.ObjectNumber);
        }
    }
}


The correct structure of the document should be like in the image below. The code forms such a structure by cloning the AcroForm dictionary and by re-forms the array of fields with actual object numbers.

111.png (144kb) downloaded 8 time(s).
thanks 1 user thanked Paul Rayman for this useful post.
claudiu on 7/17/2019(UTC)
claudiu  
#3 Posted : Wednesday, July 17, 2019 6:58:40 PM(UTC)
claudiu

Rank: Newbie

Groups: Registered
Joined: 6/6/2019(UTC)
Posts: 4
Canada

Thanks: 2 times
Thanks Paul, it works a treat!
ryanthomas03  
#4 Posted : Friday, October 18, 2019 1:26:11 PM(UTC)
ryanthomas03

Rank: Newbie

Groups: Registered
Joined: 9/5/2019(UTC)
Posts: 3
United States

There are some problems with this logic as well as with the ImportPages(..) logic which prevents copying form fields that are not flat / not top level only.

1st: ImportPages(..) does not appear to properly handle copying / updating the 'Parent' and 'Kids' references from the source document to the destination document.

Using an example source document with:


Code:

"AcroForm" -> "Fields" -> [ 
    { "DA": ..., "FT": "Tx", "Kids": [ {Kid1, Kid2}], "T": "Field1" },
    { "DA": ..., "FT": "Tx", "Kids": [ {Kid3, Kid4}], "T": "Field2" },
    { "AP": .., "DA": .., "F": ..,  "FT": "Tx", "MK": .., "P", .., "Rect": .., "Subtype": .., "T": "Field3", ... }
]


There are essentially 5 annotation widgets (kid1, kid2, kid3, kid4, and Field3).

After calling ImportPages(..) kid1, kid2, kid3, kid4 and field3 will all be cloned and copied to the new document.

But ClonedKid1.Parent, ClonedKid2.Parent, ClonedKid3.Parent, and ClonedKid4.Parent will all still point back to the original Field1 and Field2 objects which were never cloned to the new document. Additionally Field1.Kids and Field2.Kids will point to the original document Kid1, Kid2, Kid3, Kid4, not the cloned ones.

In addition to the references pointing to the old document's objects, the ImportAcroForm(..) logic you provided copies the annotations to the fields array is if they're all top level. Given the above input 'fields' you would end up with a copied fields array that looks like:

Code:

"AcroForm (NewDocument)" -> "Fields (NewDocument)" -> [ 
    { ClonedKid1 },
    { ClonedKid2 },
    { ClonedKid3 },
    { ClonedKid4 },
    { Cloned Field3 }
]


I wrote a routine to take a stab at cloning/copying the parents to the new document and ensuring the field structure is preserved. It works up until the point I attempt to save the new pdf, then the execution environment crashes with an underlying win32 exception. I'm not sure why.

If I attempt to save to a file it outputs a file before crashing and the output file appears to be valid (at least valid enough that I can then re-open it as a pdf and/or inspect the fields and see that the structure was preserved).

The attempt is contained in this gist:
https://gist.github.com/...893a335ba99aca8cbd915822

Edited by user Friday, October 18, 2019 1:27:05 PM(UTC)  | Reason: Not specified

Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.