ITextSharp RenameField Error?

I am trying to rename a checkbox which is a subclass. Let's say the flag name is MyForm.Check1.page0. When I run:

reader.AcroField.RenameField("MyForm.Check1.page0", "MyForm.Check1.newName");

The flag is renamed as "newName". Information about the subclass is discarded. I get from the documentation that the subclass cannot be changed, but that was unexpected.

According to the documentation:

"Renames the field. You can rename only the last part of the name. For example, if the source field is" ab.cd.ef ", then only the" ef "part can be renamed."

A long day has passed, but I would read it so that you can rename the field with a subclass of "ab.cd.ef" to "ab.cd.yz", and not when renaming "ab.cd.ef" to "ab.cd. yz "instead you get a field named" yz ".

I found the source class on GitHub and it looks like its error to me. From GitHub:

 public bool RenameField(String oldName, String newName) {
            int idx1 = oldName.LastIndexOf('.') + 1;
            int idx2 = newName.LastIndexOf('.') + 1;
            <snip>
            Item item = fields[oldName];
            newName = newName.Substring(idx2);

I think the problem is the last line. If it's by design, it seems very strange to me. I think I can get around this, but again it looks very strange.

Edit:

I copied and cleaned the code and made a sample command line that shows this problem. You just need to download a copy and change the path for the PDF files. All this comes from a much larger application, so it’s a little bloated as a test application, but it was faster than trying to rewrite everything. Some of the code is a bit sloppy as its work continues. I also refused the code that is not related to this problem (namely the JavaScript code that I am embedding).

, DropBox, .

.cs . #, . PDF , "TableStartPosition", fieldPositions FillCoverPage .

, "InkSaver.chk2.pageX" ( X - ). "pageX". RenameFields().

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace RenameFieldTest
{
    class Program
    {
        Stream _pdfTemplateStream;
        MemoryStream _pdfResultStream;

        PdfReader _pdfTemplateReader;
        PdfStamper _pdfResultStamper;

        static void Main(string[] args)
        {
            Program p = new Program();
            try
            {
                p.RunTest();
            }
            catch (Exception f)
            {
                Console.WriteLine(f.Message);
                Console.ReadLine();
            }
        }
        internal void RunTest()
        {
            FileStream fs = File.OpenRead(@"C:\temp\a\RenameFieldTest\RenameFieldTest\Library\CoverPage.pdf");
            _pdfTemplateStream = fs;
            _pdfResultStream = new MemoryStream();
            //PDFTemplateStream = new FileStream(_templatePath, FileMode.Open);
            _pdfTemplateReader = new PdfReader(_pdfTemplateStream);
            _pdfResultStamper = new PdfStamper(_pdfTemplateReader, _pdfResultStream);

            #region setup objects
            List<CustomCategory> Categories = new List<CustomCategory>();
            CustomCategory c1 = new CustomCategory();
            c1.CategorySizesInUse.Add(CustomCategory.AvailableSizes[1]);
            c1.CategorySizesInUse.Add(CustomCategory.AvailableSizes[2]);
            Categories.Add(c1);

            CustomCategory c2 = new CustomCategory();
            c2.CategorySizesInUse.Add(CustomCategory.AvailableSizes[0]);
            c2.CategorySizesInUse.Add(CustomCategory.AvailableSizes[1]);
            Categories.Add(c2);

            List<CustomObject> Items = new List<CustomObject>();
            CustomObject co1 = new CustomObject();
            co1.Category = c1;
            co1.Title = "Object 1";
            Items.Add(co1);

            CustomObject co2 = new CustomObject();
            co2.Category = c2;
            co2.Title = "Object 2";
            Items.Add(co2);

            #endregion

            FillCoverPage(Items);
            _pdfResultStamper.Close();
            _pdfTemplateReader.Close();

            List<MemoryStream> pdfStreams = new List<MemoryStream>();
            pdfStreams.Add(new MemoryStream(_pdfResultStream.ToArray()));

            MergePdfs(@"C:\temp\a\RenameFieldTest\RenameFieldTest\Library\Outfile.pdf", pdfStreams);

            _pdfResultStream.Dispose();
            _pdfTemplateStream.Dispose();
        }
        internal void FillCoverPage(List<CustomObject> Items)
        {

            //Before we start we need to figure out where to start adding the table
            var fieldPositions = _pdfResultStamper.AcroFields.GetFieldPositions("TableStartPosition");
            if (fieldPositions == null)
            { throw new Exception("Could not find the TableStartPosition field. Unable to determine point of origin for the table!"); }

            _pdfResultStamper.AcroFields.RemoveField("TableStartPosition");

            var fieldPosition = fieldPositions[0];
            // Get the position of the field
            var targetPosition = fieldPosition.position;

            //First, get all the available card sizes
            List<string> availableSizes = CustomCategory.AvailableSizes;


            //Generate a table with the number of available card sizes + 1 for the device name
            PdfPTable table = new PdfPTable(availableSizes.Count + 1);
            float[] columnWidth = new float[availableSizes.Count + 1];
            for (int y = 0; y < columnWidth.Length; y++)
            {
                if (y == 0)
                { columnWidth[y] = 320; }
                else
                { columnWidth[y] = 120; }
            }

            table.SetTotalWidth(columnWidth);
            table.WidthPercentage = 100;

            PdfContentByte canvas;

            List<PdfFormField> checkboxes = new List<PdfFormField>();

            //Build the header row
            table.Rows.Add(new PdfPRow(this.GetTableHeaderRow(availableSizes)));

            //Insert the global check boxes
            PdfPCell[] globalRow = new PdfPCell[availableSizes.Count + 1];
            Phrase tPhrase = new Phrase("Select/Unselect All");
            PdfPCell tCell = new PdfPCell();
            tCell.BackgroundColor = BaseColor.LIGHT_GRAY;
            tCell.AddElement(tPhrase);
            globalRow[0] = tCell;

            for (int x = 0; x < availableSizes.Count; x++)
            {
                tCell = new PdfPCell();
                tCell.BackgroundColor = BaseColor.LIGHT_GRAY;
                PdfFormField f = PdfFormField.CreateCheckBox(_pdfResultStamper.Writer);
                string fieldName = string.Format("InkSaver.Global.chk{0}", availableSizes[x].Replace(".", ""));
                //f.FieldName = fieldName;
                string js = string.Format("hideAll(event.target, '{0}');", availableSizes[x].Replace(".", ""));
                f.Action = PdfAction.JavaScript(js, _pdfResultStamper.Writer);
                tCell.CellEvent = new ChildFieldEvent(_pdfResultStamper.Writer, f, fieldName);
                globalRow[x + 1] = tCell;
                checkboxes.Add(f);
            }
            table.Rows.Add(new PdfPRow(globalRow));

            int status = 0;
            int pageNum = 1;

            for (int itemIndex = 0; itemIndex < Items.Count; itemIndex++)
            {
                tCell = new PdfPCell();
                Phrase p = new Phrase(Items[itemIndex].Title);
                tCell.AddElement(p);
                tCell.HorizontalAlignment = Element.ALIGN_LEFT;

                PdfPCell[] cells = new PdfPCell[availableSizes.Count + 1];
                cells[0] = tCell;

                for (int availCardSizeIndex = 0; availCardSizeIndex < availableSizes.Count; availCardSizeIndex++)
                {
                    if (Items[itemIndex].Category.CategorySizesInUse.Contains(availableSizes[availCardSizeIndex]))
                    {
                        string str = availableSizes[availCardSizeIndex];
                        tCell = new PdfPCell();
                        tCell.PaddingLeft = 10f;
                        tCell.PaddingRight = 10f;
                        cells[availCardSizeIndex + 1] = tCell;
                        cells[availCardSizeIndex].HorizontalAlignment = Element.ALIGN_CENTER;

                        PdfFormField f = PdfFormField.CreateCheckBox(_pdfResultStamper.Writer);
                        string fieldName = string.Format("InkSaver.chk{0}.{1}", availableSizes[availCardSizeIndex].Replace(".", ""), itemIndex + 1);
                        //f.FieldName = fieldName; <-- This causes the checkbox to be double-named (i.e. InkSaver.Global.chk0.InkSaver.Global.chk0
                        string js = string.Format("hideCardSize(event.target, {0}, '{1}');", itemIndex + 1, availableSizes[availCardSizeIndex]);
                        f.Action = PdfAction.JavaScript(js, _pdfResultStamper.Writer);
                        tCell.CellEvent = new ChildFieldEvent(_pdfResultStamper.Writer, f, fieldName);

                        checkboxes.Add(f);
                    }
                    else
                    {
                        //Add a blank cell
                        tCell = new PdfPCell();
                        cells[availCardSizeIndex + 1] = tCell;
                    }
                }
                //Test if the column text will fit

                table.Rows.Add(new PdfPRow(cells));

                canvas = _pdfResultStamper.GetUnderContent(pageNum);
                ColumnText ct2 = new ColumnText(canvas);
                ct2.AddElement(new PdfPTable(table));
                ct2.Alignment = Element.ALIGN_LEFT;
                ct2.SetSimpleColumn(targetPosition.Left, 0, targetPosition.Right, targetPosition.Top, 0, 0);
                status = ct2.Go(true);

                if ((status != ColumnText.NO_MORE_TEXT) || (itemIndex == (Items.Count - 1)))
                {
                    ColumnText ct3 = new ColumnText(canvas);
                    ct3.AddElement(table);
                    ct3.Alignment = Element.ALIGN_LEFT;
                    ct3.SetSimpleColumn(targetPosition.Left, 0, targetPosition.Right, targetPosition.Top, 0, 0);
                    ct3.Go();

                    foreach (PdfFormField f in checkboxes)
                    {
                        _pdfResultStamper.AddAnnotation(f, pageNum);
                    }
                    checkboxes.Clear();

                    if (itemIndex < (Items.Count - 1))
                    {
                        pageNum++;
                        _pdfResultStamper.InsertPage(pageNum, _pdfTemplateReader.GetPageSize(1));

                        table = new PdfPTable(availableSizes.Count + 1);
                        table.SetTotalWidth(columnWidth);
                        table.WidthPercentage = 100;
                        table.Rows.Add(new PdfPRow(this.GetTableHeaderRow(availableSizes)));
                    }
                }
            }
        }
        private PdfPCell[] GetTableHeaderRow(List<string> AvailableSizes)
        {
            PdfPCell[] sizeHeaders = new PdfPCell[AvailableSizes.Count + 1];
            Phrase devName = new Phrase("Device Name");
            PdfPCell deviceHeader = new PdfPCell(devName);
            deviceHeader.HorizontalAlignment = Element.ALIGN_CENTER;
            deviceHeader.BackgroundColor = BaseColor.GRAY;
            sizeHeaders[0] = deviceHeader;
            for (int x = 0; x < AvailableSizes.Count; x++)
            {
                PdfPCell hCell = new PdfPCell(new Phrase(AvailableSizes[x]));
                hCell.HorizontalAlignment = Element.ALIGN_CENTER;
                hCell.BackgroundColor = BaseColor.GRAY;
                sizeHeaders[x + 1] = hCell;
            }
            return sizeHeaders;
        }
        public void MergePdfs(string filePath, List<MemoryStream> pdfStreams)
        {
            //Create output stream            
            FileStream outStream = new FileStream(filePath, FileMode.Create);

            if (pdfStreams.Count > 0)
            {
                try
                {
                    int PriceCardCounter = 0;
                    //Create Main reader
                    PdfReader reader = new PdfReader(pdfStreams[0]);

                    //rename fields in the PDF.  This is required because PDF cannot have more than one field with the same name
                    RenameFields(reader, PriceCardCounter++);

                    //Create main writer
                    PdfCopyFields Writer = new PdfCopyFields(outStream);

                    //Open document for writing
                    ////Add pages
                    Writer.AddDocument(reader);

                    //For each additional pdf after first combine them into main document
                    foreach (var PdfStream in pdfStreams.Skip(1))
                    {
                        PdfReader reader2 = new PdfReader(PdfStream);
                        //rename PDF fields
                        RenameFields(reader2, PriceCardCounter++);
                        // Add content
                        Writer.AddDocument(reader2);
                    }

                    Writer.Close();
                }
                finally
                {
                    foreach (var Strm in pdfStreams)
                    {
                        try { if (null != Strm) Strm.Dispose(); }
                        catch { }
                    }
                    outStream.Close();
                }
            }
        }
        private void RenameFields(PdfReader reader, int PriceCardID)
        {
            int tempPageNum = 1;
            //rename all fields
            foreach (string field in reader.AcroFields.Fields.Keys)
            {
                if (((reader.AcroFields.GetFieldType(field) == 1) || (reader.AcroFields.GetFieldType(field) == 2)) && (field.StartsWith("InkSaver")))
                {
                    //This is a InkSaver button, set the name so its subclassed
                    string classPath;
                    if (reader.AcroFields.GetFieldType(field) == 2)
                    {
                        classPath = field.Substring(0, field.LastIndexOf("."));
                        if (field.StartsWith("InkSaver.chk"))
                        {
                            int a = field.LastIndexOf(".");
                            string sub = field.Substring(a + 1, (field.Length - a - 1));
                            int pageNum = int.Parse(sub);
                            int realPageNum = pageNum + tempPageNum;//PostProcessing.Instance.CoverPageLength;
                            PriceCardID = realPageNum;
                        }
                    }
                    else
                    {
                        classPath = field.Substring(0, field.LastIndexOf("."));
                    }
                    string newID = classPath + ".page" + PriceCardID.ToString();
                    bool ret = reader.AcroFields.RenameField(field, newID);
                }
                else
                {
                    reader.AcroFields.RenameField(field, field + "_" + PriceCardID.ToString());// field + Guid.NewGuid().ToString("N"));
                }
            }
        }
    }
    public class ChildFieldEvent : IPdfPCellEvent
    {
        protected PdfWriter writer;
        protected PdfFormField parent;
        protected string checkBoxName;

        internal ChildFieldEvent(PdfWriter writer, PdfFormField parent, string CheckBoxName)
        {
            this.writer = writer;
            this.parent = parent;
            this.checkBoxName = CheckBoxName;
        }

        public void CellLayout(PdfPCell cell, Rectangle rect, PdfContentByte[] cb)
        {
            createCheckboxField(rect);
        }
        private void createCheckboxField(Rectangle rect)
        {
            RadioCheckField bt = new RadioCheckField(this.writer, rect, this.checkBoxName, "Yes");
            bt.CheckType = RadioCheckField.TYPE_SQUARE;
            bt.Checked = true;
            this.parent.AddKid(bt.CheckField);
        }
    }
}
+4
2

, , , . , PDF AcroForm, : name owner.name. owner.name owner.name1 name name1. , (AcroFields.fields) name1, owner.name1, ( , owner.name). , name1 . , PDF.

Java iText:

// snippet from com.itextpdf.text.pdf.AcroFields.renameField
int idx2 = newName.lastIndexOf('.') + 1;
// cut the last part from the original name
newName = newName.substring(idx2);
PdfString ss = new PdfString(newName, PdfObject.TEXT_UNICODE);
// problem: only the last part will be registered, this must 
// be IMO the (original) whole name including the dots
fields.put(newName, item);
+1

, . . : person. , name address. person.name person.address. , , , street, city country, , person.address.street, person.address.city person.address.country.

, street, , PDF . , person.address.street, street. : person.address.street person.address.line1. person.address.street person.street, .

, , , .

, - , , . , ef , . , ab.cd.ef xy, , , PDF, .

, , .

:

RenameField. (subscribe.pdf) (subscribe_renamed.pdf). ? "personal.loginname" "personal.login". "personal.loginname" "login", ( , , ).

0

Source: https://habr.com/ru/post/1523640/


All Articles