In this video, I take a look at Field Transfers, the functionality that ensures that field values are moving correctly from master data via journals/drafts to posted data. Several different approaches are used to ensure that and those are explored in the video as well as what to do if you want to transfer your own fields through the system.

In this video, Erik explores one of the most fundamental concepts in Business Central development: field transfers — the mechanism by which data flows from one table to another throughout the system. He demonstrates how field values propagate when you create and post a sales order, shows a fascinating look at how this was handled in version 3.56 from the mid-1990s, and walks through the modern approaches for adding your own field transfers using event subscribers and table extensions.
What Are Field Transfers?
Field transfers are the process by which field values get copied from one record to another as you work through Business Central. Every time you perform a seemingly simple action — like selecting a customer on a sales order — a cascade of field transfers takes place behind the scenes.
Consider what happens when you create and post a sales order:
- Customer Card → Sales Header: When you select a customer, fields like address, city, province, postal code, email, and contact are transferred from the customer card to the sales header.
- Item Card → Sales Line: When you select an item on a line, the item description, unit of measure, unit price, and other fields are transferred from the item card to the sales line.
- Sales Header → Sales Line: When a new line is created, certain fields from the sales header are automatically replicated onto the line.
- Sales Header → Posted Sales Invoice Header (Table 112): When the order is posted, fields are copied from the sales order header to the posted sales invoice header.
- Sales Line (Table 37) → Sales Invoice Line (Table 113): Similarly, line values are transferred to the posted invoice lines.
- Sales Header/Line → General Journal Line → G/L Entry: Fields also flow through the general journal line into ledger entries, though this happens in multiple hops.
Throughout a simple operation like creating and posting a sales order, an abundant number of field transfers happen — values are copied and shuffled around the system by different means. Understanding these routes is critical when you need to carry a custom field value all the way through the posting process.
A History Lesson: Field Transfers in Version 3.56
Erik takes a brief detour into Navision version 3.56 from the mid-1990s to show how field transfers used to work. In that version, tables (called “files” back then) had a dedicated Field Transfer option built right into the system. You could open a table like Sales Line and see a structured list defining exactly which fields get copied from which source — for example, from the header (client number, delivery date, department code, location, price group) or from the product/item (booking group, discount code, name, unit, etc.).
This was a declarative system where you could simply add a new field transfer entry to control the flow. Unfortunately, this capability was lost during the evolution of the product into what we know today as Business Central. It was a really elegant approach that made the data flow visible in one place.
How Field Transfers Work Today
In modern Business Central, field transfers are accomplished in two primary ways:
1. The TransferFields Method
The TransferFields method is a built-in record function that copies all matching fields from one record to another. “Matching” means the field must have the same field number, same name, and same data type in both tables. There’s also a parameter to control whether primary key fields should be included (useful when copying within the same table).
Microsoft uses TransferFields extensively in the posting routines. For example, in Codeunit 80 (Sales-Post), you’ll find patterns like:
SalesShipmentHeader.TransferFields(SalesHeader)— copies from the sales header to the shipment headerSalesInvoiceHeader.TransferFields(SalesHeader)— copies to the posted invoice headerSalesCrMemoHeader.TransferFields(SalesHeader)— copies to the credit memo headerPurchRcptLine.TransferFields(PurchaseLine)— copies purchase lines to receipt lines
This means that if you add a custom field with the same field number and definition to both the source and destination tables, your field value will automatically be carried over wherever Microsoft uses TransferFields. For instance, adding MyField (field 50100, Integer) to both the Sales Header and the Sales Shipment Header ensures the value transfers during posting:
tableextension 50100 "Sales Header" extends "Sales Header"
{
fields
{
field(50100; MyField; Integer)
{
}
}
}
tableextension 50102 SalesShip extends "Sales Shipment Header"
{
fields
{
field(50100; MyField; Integer)
{
}
}
}
Because Microsoft’s posting code calls SalesShipmentHeader.TransferFields(SalesHeader), your field 50100 will be automatically included in that transfer — no additional code required.
2. Event Subscribers and Manual Field Assignments
For transfers that don’t use the TransferFields method — such as copying fields from a customer card to a sales header, or from an item card to a sales line — Microsoft uses explicit field-by-field assignment in dedicated “CopyFrom” procedures. These procedures typically have events you can subscribe to.
For example, when you validate the “Sell-to Customer No.” on the Sales Header, BC calls a procedure like CopySellToCustomerAddressFieldsFromCustomer, which contains individual assignments like:
"Sell-to Customer Name" := Customer.Name"Sell-to Customer Name 2" := Customer."Name 2"
At the end of this procedure, there’s an event called OnAfterCopySellToCustomerAddressFieldsFromCustomer that you can subscribe to in order to add your own field transfers:
codeunit 50100 "Field Tranfers"
{
[EventSubscriber(ObjectType::Table, Database::"Sales Header",
'OnAfterCopySellToCustomerAddressFieldsFromCustomer', '', true, true)]
local procedure MyProcedure(var SalesHeader: Record "Sales Header";
SellToCustomer: Record Customer)
begin
SalesHeader."Sell-to E-Mail" := SellToCustomer."E-Mail";
end;
}
3. Table Extension Triggers (OnAfterValidate)
An alternative approach is to use the OnAfterValidate trigger on a modified field within a table extension. This achieves the same result but through a different mechanism:
tableextension 50100 "Sales Header" extends "Sales Header"
{
fields
{
field(50100; MyField; Integer)
{
}
modify("Sell-to Customer No.")
{
trigger OnAfterValidate()
var
Customer: Record Customer;
begin
Customer.Get("Sell-to Customer No.");
Rec."Sell-to E-Mail" := Customer."E-Mail";
end;
}
}
}
Both the event subscriber approach and the table extension trigger approach accomplish the same goal — the choice depends on your circumstances and preferences.
Handling Sales Line Transfers
The same patterns apply on the Sales Line (Table 37). When you validate the “No.” field, BC determines the line type (Item, Resource, G/L Account, etc.) and calls the appropriate “CopyFrom” procedure. For items, it calls CopyFromItem, which has events like OnAfterCopyFromItem where you can add your own field transfers.
If you use the table extension approach instead, you need to replicate the type-checking logic yourself:
tableextension 50101 "Sales Line" extends "Sales Line"
{
fields
{
modify("No.")
{
trigger OnBeforeValidate()
var
Item: Record Item;
Res: Record Resource;
begin
case Type of
Type::Resource:
begin
Res.Get("No.");
Rec.Field := Res.Field;
end;
Type::Item:
begin
Item.get("No.");
Rec.Field := Item.Field;
end;
end;
end;
}
}
}
Note that the “No.” field on a sales line can represent different entity types (Item, Resource, G/L Account, etc.), so you must use a case statement on the Type field to handle each scenario appropriately.
Summary and Key Takeaways
When you need to transfer custom data around the Business Central system, you need to piggyback on the existing field transfer approaches. Here’s a recap of your options:
- Use TransferFields (matching fields): Add the same field (same number, name, and type) to both the source and destination tables. Wherever Microsoft uses the
TransferFieldsmethod, your field will be included automatically. This works well for draft-to-posted table transfers (e.g., Sales Header → Sales Shipment Header, Sales Invoice Header, etc.). - Subscribe to “OnAfterCopyFrom” events: For explicit field-by-field transfers (like Customer → Sales Header or Item → Sales Line), subscribe to the appropriate event and add your field assignment there.
- Use table extension triggers (OnAfterValidate): Modify the key field in a table extension and add your transfer logic in the
OnAfterValidatetrigger. This requires you to replicate some of the conditional logic (like checking the line type).
The critical first step is always to understand the route your data takes through the system. Trace the path from the source (a card or setup table) through intermediate documents (headers, lines, journals) to the final destination (posted entries, ledger entries). Once you know the route, you can determine which field transfer mechanism applies at each step and ensure your custom fields travel along with the data.