pythonpdfadobe

How to Programmatically Add a Calculated Sum Field in an Adobe PDF Using Python, R or etc


I'm trying to insert a calculated sum field called "SummedAmount" in my Adobe PDF. This field should sum up the values of the text fields: perc1 + perc2 + perc3 + perc4 + perc5.

When using Adobe Acrobat Desktop, I can easily create this calculation through the UI. However, I automate PDF form filling and processing using Python (with pdfrw and other libraries). Unfortunately, this process seems to remove the calculation from the SummedAmount field, and I am unable to add it back programmatically.

I suspect Adobe enforces security restrictions that prevent me from fully automating this. I've attempted to add a JavaScript-based sum calculation via annotations, and while I can successfully insert the calculation, it does not trigger unless I manually edit the text field in Adobe Forms settings—defeating the purpose of automating it.

What I've Tried So Far I've attempted to inject the calculation using JavaScript in annotations, ensuring:

The SummedAmount field exists and is set to read-only.

A calculation script is added using AcroForm actions.

Document-level JavaScript is injected.

Despite these efforts, the calculation only runs after manually editing the form in Adobe Acrobat.

My Question Is there a way to programmatically insert a sum field without requiring manual intervention in Adobe Acrobat Desktop?

Are there alternative Python libraries or approaches that allow setting form field calculations?

Is Adobe preventing this modification due to security reasons, and if so, are there any workarounds?

Edit: Updated code to fix text alignment, font size, and inherited field positions for percentage fields and "SummedAmount". Thanks for the suggestions!

fields= {
    "SummedAmount": (10, 10, 100, 30),  # Arbitrary position
    "Percentage1": (10, 40, 100, 60),
    "Percentage2":(10, 70, 100, 90),
    "Percentage3":(10, 100, 100, 120),
    "Percentage4":(10, 130, 100, 150),
    "Percentage5":(10, 160, 100, 180)

}

import pymupdf

def add_calculation_to_pdf(input_pdf, output_pdf, fields):
    """Adds calculation fields to an existing PDF using provided field positions."""
# Open the PDF document
doc = pymupdf.open(input_pdf)
page = doc[0]  # Assuming calculations are on the first page
page_height = page.rect.height  # Get the page height for Y-axis flipping

# Create widgets for Percentage fields
percentage_fields = ["Percentage1", "Percentage2", "Percentage3", "Percentage4", "Percentage5"]

for field_name in percentage_fields:
    if field_name in fields:
        x1, y1, x2, y2 = fields[field_name]
        x1, y1, x2, y2 = float(x1), float(y1), float(x2), float(y2)
        w = pymupdf.Widget()
        w.field_name = field_name
        w.rect = pymupdf.Rect(x1, page_height - y2, x2, page_height - y1)
        w.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT
        w.field_value = "0"
        # w.text_align = 1  # Center the text
        w.field_flags = 2  # Editable field
        w.text_font = "Times-Roman"  # Set font to Times-Roman
        w.text_fontsize = 12  # Set font size to 12
        page.add_widget(w)

# Create SummedAmount widget using inherited field positions
if "SummedAmount" in fields:
    x1, y1, x2, y2 = fields["SummedAmount"]
    x1, y1, x2, y2 = float(x1), float(y1), float(x2), float(y2)
    w = pymupdf.Widget()
    w.field_name = "SummedAmount"
    w.rect = pymupdf.Rect(x1, page_height - y2, x2, page_height - y1)
    w.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT
    w.field_value = "0.00"
    # w.text_align = 1  # Center the text
    w.text_font = "Times-Roman"  # Set font to Times-Roman
    w.text_fontsize = 12  # Set font size to 12
    w.script_calc = 'AFSimple_Calculate("SUM", new Array("Percentage1", "Percentage2", "Percentage3", "Percentage4", "Percentage5"));'
    page.add_widget(w)

# Save the updated PDF
doc.save(output_pdf, pretty=True)

Solution

  • Here is a Python script which does this using PyMuPDF.

    import pymupdf
    
    r1 = pymupdf.Rect(100, 100, 300, 120)
    r2 = pymupdf.Rect(100, 130, 300, 150)
    r3 = pymupdf.Rect(100, 180, 300, 200)
    
    doc = pymupdf.open()
    for i in range(3):
        page = doc.new_page()
        print(f"page {page.number}")
        w = pymupdf.Widget()
        w.field_name = f"NUM1{page.number}"
        w.rect = r1
        w.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT
        w.field_value = f"{i*100+1}"
        w.field_flags = 2
        page.add_widget(w)
    
        w = pymupdf.Widget()
        w.field_name = f"NUM2{page.number}"
        w.rect = r2
        w.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT
        w.field_value = "200"
        w.field_flags = 2
        page.add_widget(w)
    
        w = pymupdf.Widget()
        w.field_name = f"RESULT{page.number}"
        w.rect = r3
        w.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT
        w.field_value = "Resultat?"
        w.script_calc = f'AFSimple_Calculate("SUM", new Array("NUM1{page.number}", "NUM2{page.number}"));'
        page.add_widget(w)
    
    doc.save(__file__.replace(".py", ".pdf"), pretty=True)
    

    Note: I am a maintainer and the original creator of PyMuPDF.