SAP Business One SDK

Copying data from a request form to a completion form in SAP Business One

You can do this two ways: write a UI API add-on that reads the source controls and writes the target controls, or have an agent watch you do the copy once and replay it through the accessibility tree with no add-on. Both are below, with the working event handler and the trade-offs.

M
Matthew Diakonov
8 min read

Direct answer (verified 2026-06-20)

Use the UI API, not the DI API. Register an event filter for the source form, and on the triggering item event (with BeforeAction == false) read each source control's value, switch the target form to add mode, write the values onto the matching target controls, set BubbleEvent = false, and call Update(). That add-on must be compiled, signed, and registered through Add-On Administration. The reference is the SAP Business One UI API documentation in the SAP SDK help.

Source: help.sap.com/docs/SAP_BUSINESS_ONE

The SDK route, step by step

Every other guide on this stops at "read the source, write the target." The parts that actually bite, reading bound fields before they paint, putting the target form in add mode, and stopping the event from re-firing, are below.

1

1. Register a UI API event filter for the source form

In your add-on Connect() routine, build an EventFilter, add the source form's FormType, and subscribe to et_FORM_DATA_LOAD and et_ITEM_PRESSED. The UI API only delivers events for form types you explicitly register, so an unfiltered listener will fire on every form in the company and slow the client.

2

2. Read the source values in the BeforeAction == false handler

On et_FORM_DATA_LOAD (or the button press that triggers the copy), grab the source SAPbouiCOM.Form by UID, then read each control: oForm.Items.Item("txtCardCode").Specific as EditText returns .Value. For bound fields read the DBDataSource or UserDataSource instead, because EditText.Value is empty until the control is painted.

3

3. Open or locate the completion form

Either find the already-open target form via SBO_Application.Forms.Item(uid), or load it from an .srf with LoadBatchActions. Hold its UID. Set the target to add mode (oTargetForm.Mode = bm_Add) before writing, otherwise the client rejects writes to a browse-mode record.

4

4. Write the captured values onto the completion form

Assign control by control: (oTargetForm.Items.Item("txtCardCode").Specific as EditText).Value = capturedCardCode. For matrix rows iterate oMatrix.Columns and call oMatrix.AddRow(); set DataTable / UserDataSource values so SAP B1 persists them on Update().

5

5. Validate, commit, and guard against re-entrancy

Set BubbleEvent = false on any event you handle so SAP B1 does not double-process it, run your field validation, then call oTargetForm.Update() inside a try/catch that reads SBO_Application.Company.GetLastError. Deploy the compiled add-on through the Add-On Administration and the SAP B1 license server before it runs on a user's machine.

The working event handler

This is the minimal copy on a button press. Note the four conditions on the event (form type, item UID, event type, and BeforeAction = False); drop any one and the handler fires at the wrong moment or on the wrong form.

' SAP Business One UI API (VB.NET) - copy CardCode + Amount
' from a "request" form to a "completion" form on button press
Private Sub SBO_Application_ItemEvent(ByVal FormUID As String, _
        ByRef pVal As SAPbouiCOM.ItemEvent, ByRef BubbleEvent As Boolean)

    If pVal.FormTypeEx = "REQ_FORM" AndAlso _
       pVal.ItemUID = "btnCopy" AndAlso _
       pVal.EventType = BoEventTypes.et_ITEM_PRESSED AndAlso _
       pVal.BeforeAction = False Then

        Dim src As SAPbouiCOM.Form = SBO_Application.Forms.Item(FormUID)
        Dim cardCode As String = _
            CType(src.Items.Item("txtCard").Specific, SAPbouiCOM.EditText).Value
        Dim amount As String = _
            CType(src.Items.Item("txtAmt").Specific, SAPbouiCOM.EditText).Value

        Dim tgt As SAPbouiCOM.Form = SBO_Application.Forms.Item("COMP_FORM")
        tgt.Mode = SAPbouiCOM.BoFormMode.fm_ADD_MODE
        CType(tgt.Items.Item("txtCard").Specific, SAPbouiCOM.EditText).Value = cardCode
        CType(tgt.Items.Item("txtAmt").Specific, SAPbouiCOM.EditText).Value = amount

        BubbleEvent = False ' stop SAP B1 from re-processing the click
    End If
End Sub

Item UIDs (txtCard, txtAmt) and form types (REQ_FORM) are illustrative. They are exactly the hard-coded strings that break on a renamed field or an upgrade.

Where the SDK route gets expensive

It is an add-on, not a script

The copy logic ships as a compiled, signed add-on registered in Add-On Administration and pushed to every client, and building it consumes a SAP development license. A one-line field change is a recompile-and-redeploy.

Hard-coded UIDs are brittle

The handler keys off Item UIDs and form types. Rename a UDF, reorder a matrix column, or change a form type on upgrade and the assignment silently writes to the wrong control or nulls the target.

Timing bugs are subtle

Read an EditText before it paints and you get an empty string; forget BubbleEvent = false and SAP B1 re-processes the click. These cost days the first time you hit them.

You need a developer to own it

The person who designed the request and completion forms usually is not the person who can maintain a VB.NET/C# add-on. The copy logic now lives outside the team that understands the workflow.

The same copy without writing SDK code

Mediar reads and writes the exact same SAP B1 controls, EditText, Matrix, ComboBox, but through the Windows accessibility tree (the interface screen readers use) instead of a compiled add-on. The anchor difference: it matches fields by their accessible label, not a hard-coded Item UID, so a renamed UDF does not silently null the target and there is nothing to recompile when a form changes.

You record the copy once by doing it yourself in the client. Mediar watches that single run and replays it, header fields and matrix rows alike. There is no add-on to sign, no development license to consume, and no add-on registration to push to every machine.

What it touches

SAP Business One (SAP GUI client)

Mediar reads and writes the same EditText, Matrix, and ComboBox controls the SDK targets, but through the OS accessibility tree, not a compiled add-on.

UI API control labels

Field-to-field copy keys off the visible/accessible label, so a renamed UDF does not silently null out the target like a hard-coded Item UID does.

DI API posting (optional)

When a workflow ends in a document post, Mediar can still hand off to the DI API for the commit while it handles the form-to-form data movement on screen.

User-defined objects (UDO)

Custom request and completion forms built as UDOs are watched and replayed the same way as standard B1 forms; no per-object event filter to register.

Honest scope: if your copy ends in a clean document post and you already maintain add-ons, the DI API commit is fine and you may not need either screen-level approach. The accessibility path earns its place when the workflow spans forms a user actually drives, when fields change often, or when the team that owns the workflow cannot own an add-on. Mediar's documented SAP B1 deployment, an F&B chain that moved off UiPath, reached production in days and told its board it was saving 70% on costs.

Skip the add-on for your request-to-completion copy

Show us the two forms on a call and we will record the copy with you and replay it, no SDK code, in days not months.

Frequently asked questions

Frequently asked questions

Which SAP B1 SDK do I use to copy data between two forms, the UI API or the DI API?

Use the UI API. Form-to-form copying is a screen-level operation: you read controls off the source SAPbouiCOM.Form and write them onto the target SAPbouiCOM.Form through item events. The DI API has no concept of an open form; it talks to business objects and the database, so it is the right tool for the final document post, not for moving values between two forms a user has open.

Why is EditText.Value empty when I try to read the source field?

An EditText only returns a .Value once its control has been painted, and bound controls mirror their DataSource rather than holding the value directly. Read the bound field from the form's DBDataSource or UserDataSource instead of the EditText, or read inside et_FORM_DATA_LOAD with BeforeAction = false so the data is already loaded.

Do I need a developer license and an add-on deployment for this?

Yes. SDK code runs as a compiled add-on registered through Add-On Administration, signed, and distributed to every client, and it consumes a SAP development license to build. That is the overhead the no-code accessibility path removes: there is no add-on to compile, sign, or push when a field changes.

What breaks the SDK copy when SAP B1 is upgraded or a field is renamed?

Hard-coded Item UIDs and FormType filters. If a UDF is renamed, a column is reordered in a matrix, or a form type changes after an upgrade, the assignment silently writes to the wrong control or nulls the target, and you recompile and redeploy the add-on. Matching on the accessible label instead of the UID is what lets the workflow survive a relabel.

Can Mediar copy matrix rows, not just header fields?

Yes. The matrix rows are exposed in the accessibility tree as a table, so Mediar reads each cell from the source grid and types it into the target grid row by row, the same iteration you would write by hand against oMatrix.Columns and AddRow(), without the SDK code.

How long does the no-SDK version take to stand up?

You record the copy once by doing it yourself in the SAP B1 client, and Mediar replays that path. Mediar's documented SAP B1 deployment, an F&B chain that moved off UiPath, reached production in days and reported saving 70% on costs versus the prior RPA tooling.

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.