Other ERPsFree generatorPDF, Excel, Word exportSage 100All Sage X3 and Sage 100 tools

Sage 100 BOI Sales Order Script Generator

This generator writes a 32-bit PowerShell script that creates a Sage 100 sales order through the Business Object Interface (BOI), the COM layer Sage 100 itself uses. It covers login, company and module date, task rights, header, one line and Sage's own error text on failure.

Fill in

Generated code
Download:

New-SageSalesOrder.ps1 (run in 32-bit PowerShell)

# Run with: C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -File .\New-SageSalesOrder.ps1
$ErrorActionPreference = 'Stop'
$pvx = New-Object -ComObject ProvideX.Script
$pvx.Init('C:\Sage\Sage 100\MAS90\Home')
$ss = $pvx.NewObject('SY_Session')
$so = $null
try {
    if ($ss.nSetUser('BOIUSER', 'ChangeMe1') -ne 1) { throw ('SetUser: ' + $ss.sLastErrorMsg) }
    if ($ss.nSetCompany('ABC') -ne 1) { throw ('SetCompany: ' + $ss.sLastErrorMsg) }
    [void]$ss.nSetDate('S/O', '20261022')
    [void]$ss.nSetModule('S/O')
    $task = $ss.nLookupTask('SO_SalesOrder_ui')
    if ($ss.nSetProgram($task) -eq 0) { throw ('SetProgram: ' + $ss.sLastErrorMsg) }

    $so = $pvx.NewObject('SO_SalesOrder_bus', $ss)

    $soNo = '[Sales order number (blank = next number)]'
    if ([string]::IsNullOrWhiteSpace($soNo)) {
        $next = [ref]''
        [void]$so.nGetNextSalesOrderNo($next)
        $soNo = $next.Value
    }
    if ($so.nSetKey($soNo) -eq 0) { throw ('SetKey: ' + $so.sLastErrorMsg) }

    if ($so.nSetValue('ARDivisionNo$', '01') -eq 0) { throw ('Division: ' + $so.sLastErrorMsg) }
    if ($so.nSetValue('CustomerNo$', 'ABF') -eq 0) { throw ('Customer: ' + $so.sLastErrorMsg) }

    $lines = $so.oLines
    [void]$lines.nAddLine()
    if ($lines.nSetValue('ItemCode$', '1001-HON-H252') -eq 0) { throw ('Item: ' + $lines.sLastErrorMsg) }
    if ($lines.nSetValue('QuantityOrdered', [double]'2') -eq 0) { throw ('Qty: ' + $lines.sLastErrorMsg) }
    if ($lines.nWrite() -ne 1) { throw ('Line write: ' + $lines.sLastErrorMsg) }

    if ($so.nWrite() -ne 1) { throw ('Order write: ' + $so.sLastErrorMsg) }
    Write-Output ('Created sales order ' + $soNo)
}
finally {
    if ($so -ne $null) { [void]$so.DropObject() }
    [void]$ss.nCleanup()
    [void]$ss.DropObject()
}

Run on a machine with a Sage 100 workstation install (the ProvideX.Script COM server is 32-bit, so 64-bit PowerShell cannot create it). The Sage 100 user needs role rights to Sales Order Entry, and the company may need Allow External Access checked in Company Maintenance. BOI availability depends on your Sage 100 edition and licensing; confirm with your reseller. Methods return 1 for success and 0 for failure (read sLastErrorMsg); nSetKey returns 2 for a new record. If [ref] does not return a number on your setup, fill in the order number field or use the VBScript form: retVal = oSO.nGetNextSalesOrderNo(sNo), which passes by reference natively under 32-bit cscript.exe. Do not store the password in the script in production.

Planning a Sage 100 integration?

Tell us what needs to flow in and out of Sage 100 and we will suggest BOI, VI or read-only access for each piece.

Optional. The tool and every export work without this. No spam.

Was this tool useful?

How to use it

Fill in the MAS90 Home path from the workstation install, a Sage 100 user created for integrations, the company code, the module date and the order data. Leave the order number blank to take the next number from Sales Order Options. Save the output as a .ps1 file and run it with the 32-bit PowerShell in SysWOW64. Test in a copy of the company first. A successful run prints the new order number; a failure throws with the method name and Sage's sLastErrorMsg, for example a customer on hold or an invalid item.

  • Use a dedicated Sage 100 user with only the roles the integration needs.
  • Keep the module date in YYYYMMDD format.
  • Run from the server or a workstation with the same Sage 100 version and product update.

What the calls do

ProvideX.Script Init points the COM server at the Home folder. SY_Session nSetUser and nSetCompany log in, nSetDate and nSetModule set the S/O module date, and nSetProgram with nLookupTask('SO_SalesOrder_ui') applies the security of the Sales Order Entry task, without which the business object refuses to open. SO_SalesOrder_bus is the same object Sales Order Entry uses, so every validation, default and user-defined script runs. nSetKey selects or creates the order, nSetValue sets fields (string fields end in $), oLines is the detail object with nAddLine, nSetValue and nWrite per line, and the header nWrite saves the whole order. DropObject and nCleanup release licences.

API options for Sage 100

On-premise Sage 100 has no native REST API. Integrations use BOI (COM, Windows only), Visual Integrator for file-based imports, ODBC for read-only reporting (or SQL Server reads on Premium) and eBusiness Web Services (SOAP) where installed. REST endpoints for Sage 100 come from third-party connectors that wrap BOI. BOI is the right choice when you need Sage's business rules on write; ODBC or SQL reads are enough for reporting.

Gotchas

Always clean up in finally: an abandoned session can hold a user licence until it times out. A return of 0 from nSetProgram usually means the user lacks rights to the task. PowerShell treats $ inside double quotes as a variable, which is why the script uses single quotes around ItemCode$ and CustomerNo$. Quantities are numeric, so pass a number, not a string. When a user-defined script on the order calls SetError, the header nWrite returns 0 and sLastErrorMsg carries that message.

Frequently Asked Questions

Does Sage 100 have a REST API?

Not natively for on-premise Sage 100. The supported programmatic route is the Business Object Interface (COM), plus Visual Integrator for imports, ODBC for reads and eBusiness Web Services where installed. REST APIs for Sage 100 are provided by third-party connectors, which call BOI underneath, so the same licensing and rights rules apply.

Why does New-Object ProvideX.Script fail in PowerShell?

Most often because the script runs in 64-bit PowerShell and the ProvideX COM server is registered as 32-bit. Run C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe instead. The other cause is a machine without a Sage 100 workstation install, where the COM class is not registered at all.

How do I read the error when nWrite returns 0?

Read sLastErrorMsg on the same object immediately after the failing call, for example $so.sLastErrorMsg after the header write or $lines.sLastErrorMsg after a line write. It holds the same text Sales Order Entry would show the user, such as an invalid item, a credit hold or a user-defined script SetError message.

Why does nSetProgram return 0?

The Sage 100 user you logged in with does not have rights to the task returned by nLookupTask, or the module date and module were not set first. Check the user's roles in Role Maintenance for Sales Order Entry, and call nSetDate and nSetModule for S/O before nSetProgram.

If you want a private assistant that reads Sage 100 orders and drafts entries for approval on your own servers, we can build it on the same BOI layer.

ArchRay builder
Design the on-prem AI stack for Sage X3 and Sage 100: model, GPUs, RAG pipeline, guardrails
See memory, speed and cost as you swap parts, then export the diagram. Free, in your browser.
Open the builder

Keep exploring

Free tools

ERP fixes and how-tos

AI on your ERP

Integrations

Software