--- title: "Formula Fields – An Advanced Guide to Manual Formula Creation" slug: "formula-fields-an-advanced-guide-to-manual-formula-creation" updated: 2025-08-28T12:59:11Z published: 2025-08-28T12:59:11Z canonical: "knowledge-base.rossum.ai/formula-fields-an-advanced-guide-to-manual-formula-creation" --- > ## Documentation Index > Fetch the complete documentation index at: https://knowledge-base.rossum.ai/llms.txt > Use this file to discover all available pages before exploring further. # Formula Fields – An Advanced Guide to Manual Formula Creation For most tasks, Copilot handles everything without needing code. But if you want to explore formula coding, this page is for you. We recommend using Copilot for the best results, as it’s constantly improving with new features. This guide offers detailed instructions and examples to help you master formula fields. If you are looking for a general guide on using formula fields or Copilot, check out [this link](/help/docs/formula-fields-in-rossum). ## Basic rules **Code**: Rossum formulas use TxScript that is based on Python, in addition including a variety of additional predefined functions and variables. More information in [this link](https://elis.rossum.ai/api/docs/#rossum-transaction-scripts). **No return statements**: The last expression evaluated in the code is automatically used as the output. **Referring to a field on the document**: Use the field. prefix to access document fields. Referencing a field name without this prefix is incorrect. - Example: field.invoice_id **Conditional Logic**: Use Python’s if-else syntax for conditional operations. Ensure the last evaluated expression is the result you want. **Check for Field Values**: Rossum provides the custom is_empty(field) function to check if a field contains a value. Use this to avoid errors when a field might be empty – returns True if the field is empty. **Default Values**: Use the Rossum-provided default_to(field, default_value) function to set a fallback value when a field is empty or missing. This ensures your formula works as expected. - Example: default_to(field.discount_rate, 0) sets the discount rate to 0 if it’s not available. **Value Overwriting**: formula fields cannot conditionally overwrite their own value — if no value is returned, the field remains empty. Ensure the formula always produces a result. **Working with Line Items**: - Line items are rows in a table (e.g., items on an invoice). Each field within a line item is treated independently for each row. - Formulas applied to line items work on each row individually, not on the entire set of rows. - Example: field.item_quantity * field.item_price calculates the total price per line item. - To aggregate data across all line items, [use the all_values property](/help/docs/formula-fields-an-advanced-guide-to-manual-formula-creation#line-item-aggregation). This lets you access all values from a column in the line items as a list, enabling operations like summing or finding maximum values. **Avoid Circular References**: A formula field should never reference itself, as this will cause circular references and errors. **Datetime Operations**: [Perform date and time calculations](/help/docs/formula-fields-an-advanced-guide-to-manual-formula-creation#datetime-operations) using Python’s datetime and timedelta modules. Note that timedelta, datetime, date and re (for regular expressions) are pre-imported by default. If you need other datetime functions, you must import them manually. **Messaging Functions**: Formula fields let you provide direct feedback to users by displaying info, warning, or error messages. ## Examples This section gives you easy examples to help you get started. ### Copying a field value Goal: Copy the value from one field to another field. ```plaintext field.total_amount ``` In this example, you copy the value from the total_amount field to the formula field you’re defining. ### String manipulation Goal: Convert the vendor name to uppercase. ```plaintext field.vendor_name.upper() ``` ### Conditional logic Goal: Apply a discount based on specific conditions. ```plaintext 20 if field.total_amount > 20000 else 0 ``` In this example, a discount of 20 is applied if the total amount exceeds 20,000; otherwise, no discount is applied. ### Datetime operations Goal: Add 14 days to the issue date. ```plaintext field.date_issue + timedelta(days=14) ``` Here, we’re using the timedelta function from the Python datetime module. This function is already imported by default in the formula environment, so you don’t need to import it yourself. ### Line item aggregation Goal: Calculate the total sum of the amount across all line items. ```plaintext sum(field.item_total_amount.all_values) ``` In this case, item_total_amount is a value within a line item. Line item values have an all_values property that provides a list of all values in the column across the table. ### Conditional discounted price calculation Goal: Calculate the discounted price based on the total amount. ```plaintext field.amount_total * 0.8 if field.amount_total > 20000 else field.amount_total ``` In this example, the discounted price is 80% of the total amount if it exceeds 20,000; otherwise, the discounted price is the same as the total amount. ## Messaging functions Formula fields let you provide direct feedback to users by displaying info, warning, or error messages. ### Info messages Use show_info("message content", field.XYZ) to display field-specific informational messages. ```plaintext show_info("Invoice is coming from the EU.", field.vendor_country) ``` Use show_info("message content") to display document level informational messages. ```plaintext show_info("Invoice is coming from the EU.") ``` ### Warning messages Use show_warning("message content", field.XYZ) to highlight potential issues on a field level. ```plaintext show_warning("This value seems unusually high.", field.invoice_total) ``` Use show_warning("message content") to highlight potential issues on a document level. ```plaintext show_warning("This value seems unusually high.") ``` ### Error messages Use show_error("message content", field.XYZ) to show critical errors on a field level and block document processing. ```plaintext show_error("Invalid date format detected.", field.date_issue) ``` Use show_error("message content") to show critical errors on a document level and block document processing. ```plaintext show_error("Invalid date format detected.") ``` ## Additional examples Use invoice date as a backup invoice ID. ```plaintext default_to(field.document_id, field.date_issue.strftime('%Y-%m-%d')) ``` Use invoice date as a backup invoice ID, but not for credit notes. ```plaintext if field.document_type != 'credit_note': default_to(field.document_id, field.date_issue.strftime('%Y-%m-%d')) else: field.document_id ``` If there is no gross amount, use net amount. If there is no net amount, use the sum of line items. ```plaintext default_to(default_to(field.amount_total, field.amount_total_base), sum(default_to(field.item_amount_total.all_values, 0))) ``` Remove non-alphanumeric characters from Vendor VAT ID. ```plaintext substitute(r'[^a-z0-9]', '', field.sender_vat_id, flags=re.IGNORECASE) ``` Calculate base amount if it’s missing. ```plaintext if is_set(field.amount_total_base): field.amount_total_base else: field.amount_total - default_to(field.amount_total_tax, 0) ``` Distribute PO number into line items, but only if there is no PO on that line item. ```plaintext if is_set(field.item_order_id): field.item_order_id else: field.order_id ``` Check if sum of line items equals total amount. ```plaintext line_items_sum = sum(default_to(field.item_amount_total.all_values, 0)) if round(line_items_sum, 2) != round(field.amount_total, 2): show_warning('Sum of line items does not equal total amount!', field.amount_total) ``` Check if the invoice date is within 60 days from today and block automation otherwise. ```plaintext if field.date_issue < date.today - timedelta(days=60): reason = 'Invoice date is more than 60 days in the past.' show_warning(reason, field.date_issue) automation_blocker(reason, field.date_issue) elif field date_issue > date.today() + timedelta(days=60): reason = 'Invoice date is more than 60 days in the future.' show_warning(reason, field.date_issue) automation_blocker(reason, field.date_issue) ``` Check line items for negative total amounts. ```plaintext for row in field.line_items: if is_set(row.item_amount_total) and row.item_amount_total < 0: show_error("Negative amount", row.item_amount_total) ``` Show an info message with the number of line items without item code. ```plaintext missing_count = 0 for row in field.line_items: if is_empty(row.item_code): missing_count+=1 if missing_count > 0: show_info(f'Number of line items without code: {missing_count}') ```