TextBoxField not working as expected

I am replacing text fragments on my pdf with textbox fields to allow for digital editing of the document but when I add the textbox fields the document takes over 30 seconds to generate, where before it was milliseconds. The text fields are also not working as expected. When I click on them, they are only appearing in the header of the table and it is only a cursor and doesn’t allow editing at all.

@jjwynes

Would you please share your sample document and sample code snippet for our reference? Because, we need to test the scenario in our environment accordingly and we will address it as well.

So we have built a wrapper library around the Aspose PDF code, but the attached file will you give you the gist of what we are doing. I can’t attach the entire library of code due to privacy reasons. If you take a look at the method below (which is contained in the attached document) you will see where we are adding the TextBoxField to the PDF document. Basically you will see the Build method and where it is looping through our library code to create the PDF document and export it out.

I have attached the file that is now being generated since I have tried adding editable text boxes, and I also attached the file before making the changes. As you will see in it we are simply using text fragments and it works fine with them. It is only when we try to add TextboxField components that it is very slow generating, and they are not being added in the correct space and don’t allow editing.
new_response.pdf (252.0 KB)

old_response.pdf.pdf (140.2 KB)

AsposePdfHelper.zip (4.7 KB)

public static TextBoxField BuildTextBoxField(EditableTextComponent component)
        {
            TextBoxField textBoxField = new(currentPage, new Rectangle(10, 10, 30, 30))
            {
                
            };

            textBoxField.Value = component.DisplayText;
            textBoxField.Multiline = component.IsMultiline;
            textBoxField.Width = component.Width;
            textBoxField.VerticalAlignment = (Aspose.Pdf.VerticalAlignment)(int)component.VerticalAlignment;
            textBoxField.TextVerticalAlignment = (Aspose.Pdf.VerticalAlignment)(int)component.VerticalAlignment;
            textBoxField.MaxLen = component.MaxLength;
            textBoxField.Height = component.Height;
            textBoxField.ReadOnly = component.IsReadOnly;
            textBoxField.TextHorizontalAlignment = (Aspose.Pdf.HorizontalAlignment)(int)component.HorizontalAlignment;
            
            if (component.TabOrder > 0)
            {
                textBoxField.TabOrder = component.TabOrder;
            }
            
            if (component.Border != null)
            {
                textBoxField.Border = new Border(textBoxField)
                {
                    Width = 1,
                    Style = BorderStyle.Solid
                }; 
            }

            if (component.Color != null)
            {
                textBoxField.Color = BuildColor(component.Color);
            }

            if (component.Margin != null)
            {
                textBoxField.Margin = BuildMargin(component.Margin);
            }
            
            asposeDocument!.Form.Add(textBoxField);

            return textBoxField;
        }

@jjwynes

Thanks for sharing the sample files and the code snippet. As you mentioned, the code part you sent cannot be used simply to test the case. However, we did look into it and noticed that you are specifying hardcoded values for the Rectangle object to add the text box. This might be the reason that text boxes are not getting displayed on correct positions.

We request if you can, please share a minimal code snippet that would add the text box against certain text fragment. We will be able to get an idea of how your are executing your program routine and address if accordingly.

The constructor of the TextBoxField requires a Page and Rectangle, and the constructor of the Rectangle requires llx, lly, urx, and ury values, so that is why I hardcoded it for now. I noticed that I can pass the Document object into the TextBoxField constructor as well, but that doesn’t work either. It throws the following error:

System.ArgumentException: Page was not specified at page creation
   at Aspose.Pdf.Forms.Form.Add(Field field)
   at ProAg.Common.DocumentBuilder.Helpers.AsposePdfHelper.BuildTextBoxField(EditableTextComponent component) in C:\DevOps\proag-field-mgmt\src\ProAg.Common.DocumentBuilder\Helpers\AsposePdfHelper.cs:line 251
   at ProAg.Common.DocumentBuilder.Helpers.AsposePdfHelper.BuildCell(TableComponent tableComponent, TableColumnComponent tableColumnComponent) in C:\DevOps\proag-field-mgmt\src\ProAg.Common.DocumentBuilder\Helpers\AsposePdfHelper.cs:line 621
   at ProAg.Common.DocumentBuilder.Helpers.AsposePdfHelper.BuildRow(TableComponent tableComponent, TableRowComponent tableRowComponent) in C:\DevOps\proag-field-mgmt\src\ProAg.Common.DocumentBuilder\Helpers\AsposePdfHelper.cs:line 534

@jjwynes

Please check the attached minimal and sample code snippet that we used in our environment:

// Load the PDF document
Document pdfDocument = new Document(dataDir+ "old_response.pdf");

// Create TextAbsorber object to extract text
TextFragmentAbsorber textAbsorber = new TextFragmentAbsorber("(907) 915-5143");
pdfDocument.Pages[1].Accept(textAbsorber);

// Iterate over the extracted text fragments
foreach (TextFragment textFragment in textAbsorber.TextFragments)
{
    // Get the rectangle of the text fragment
    Rectangle rect = textFragment.Rectangle;

    // Create a textbox field using the same rectangle
    TextBoxField textBox = new TextBoxField(pdfDocument.Pages[1], rect);
    textBox.PartialName = "TextBox1"; // Set a unique name for the textbox
    textBox.Value = textFragment.Text; // Set the extracted text as the initial value
    // Add the textbox field to the form
    pdfDocument.Form.Add(textBox, 1);
    textFragment.Text = String.Empty;
}

// Save the modified document
pdfDocument.Save(dataDir + "output.pdf");

We used it to find phone number’s location on PDF by extracting its value through TextFragmentAbsorber class and then added a textbox field on the same position. In the attached PDF generated by the above code, the textbox field is working correctly and is rendering correctly as well. Please let us know if given code snippet helps you in achieving your original requirements.
output.pdf (137.9 KB)

The issue with your sample code is to use the absorber you have to search by a value in the component you are replacing. In this case it will be an empty value in a table cell where I am trying to add the TextBoxField to the cell paragraphs collection.

@jjwynes

But then how you are calculating where should the text box be placed? Please note that the form fields need coordinates to render or to be placed on a page inside PDF. Do you have values of coordinates somewhere as well? Please help us understanding the complete scenario as per your requirements so that we can assist you accordingly.

I am trying to place the editable text field in a table cell, so I am not giving it coordinates. I am happy to share more code with you, but I do not want to upload it to a public forum. Do you have a way I can send this to you other than posting it here? On another note, I was able to try your earlier suggestion by adding the word “EDITABLE” to the text fragment display text, and then use the absorber to find the text fragments with the word “EDITABLE” in them and I tried to replace them with TextBoxFields, but it doesn’t seem to be working as suspected. I am building this document dynamically and never physically saving it. I am simply saving it in a memory stream and returning a FileContentResult from my endpoint. Anyway, here is the latest generated PDF for you to review as well. If you can give me a secure way to send you all of my code I will happily send it to you with more detailed explanations as well.
response_blah.pdf (207.0 KB)

@jjwynes

Thanks for explaining your process further. It looks like you are trying to generate a PDF that has table and you want to add text boxes in the table cells for better alignment or to achieve desired format. Please check below simple code snippet that adds form fields (checkbox and textbox) inside table cell. An output PDF is also attached for your reference:

Document mypdf = new Document();
Aspose.Pdf.Page page = mypdf.Pages.Add();
var pageNumber = 1;

// Creating table and adding rows
Aspose.Pdf.Table tableCheckList = new Aspose.Pdf.Table();
tableCheckList.DefaultCellBorder = new BorderInfo(Aspose.Pdf.BorderSide.All, 1F);
tableCheckList.DefaultCellPadding = new MarginInfo() { Top = 5f, Left = 5f, Bottom = 5f, Right = 3f };
tableCheckList.DefaultCellTextState = new TextState(8);
var tablesWidth = 450;// tableCheckList.GetWidth();
string completionWidth = (tablesWidth / 3).ToString();
tableCheckList.ColumnWidths = completionWidth;
tableCheckList.Rows.Add();
tableCheckList.Rows[0].Cells.Add("MyItem \r\n \r\n");
tableCheckList.Rows[0].Cells.Add("MyStatus \r\n \r\n");
tableCheckList.Rows[0].Cells.Add("MyComments \r\n \r\n");
mypdf.Pages[pageNumber].Paragraphs.Add(tableCheckList);

var Row2 = tableCheckList.Rows.Add();


Aspose.Pdf.Forms.CheckboxField ch = new Aspose.Pdf.Forms.CheckboxField();
Aspose.Pdf.Forms.TextBoxField txtBox = new TextBoxField();
txtBox.Height = 15;
txtBox.Width = 120;

ch.Height = 20;
ch.Width = 20;
Cell cells = Row2.Cells.Add();
Cell cells1 = Row2.Cells.Add();
txtBox.Color = Aspose.Pdf.Color.FromRgb(System.Drawing.Color.Green);

cells.Paragraphs.Add(ch);
cells1.Paragraphs.Add(txtBox);

mypdf.Save(dataDir + "TableCell_23.12.pdf");

TableCell_23.12.pdf (9.9 KB)

We really hope that above code snippet would help you in achieving your requirements. However, if you are still not able to do so OR we have still misunderstood your requirements, you can share your code snippet in a private message by clicking on the username and pressing the blue message button.
image.png (17.0 KB)

I was able to finally get this working. Thanks for your help.

@jjwynes

It is nice to hear that things are working at your end now. Please feel free to create a new topic in case you need further assistance.