Sage 100 Business Object Interface (BOI): Working VBScript Example
Sage 100 business object interface VBScript example
Also searched as
- Sage 100 BOI ProvideX.Script SY_Session example
- how to create a sales order in Sage 100 with code
- Sage 100 COM automation nSetKeyValue nWrite
- Sage 100 BOI error sLastErrorMsg
Short answer
The Sage 100 Business Object Interface exposes the same business objects the screens use through a COM object called ProvideX.Script. You initialise it with the MAS90\Home path, create an SY_Session object, log on, set the company, then create a business object such as AR_Customer_bus and read or write through it. Because it runs the real business logic, it is the supported way to write data in code, unlike direct file or ODBC writes.
Applies to: Sage 100 Standard, Advanced and Premium (formerly Sage 100 ERP / MAS 90 / MAS 200), 32-bit and 64-bit clients; behaviour of the COM class depends on the installed version
Connect to Sage 100 through BOI and read a customer
- 1On the machine that will run the script, make sure a Sage 100 workstation install is present, because the COM class is registered by the workstation setup. A server-only install is not enough for client scripts.
- 2In Sage 100 Library Master, give the logon user a role that allows external access (look for the Allow External Access task permission in Role Maintenance, and the matching user-level setting). Without it the logon fails even with a valid password.
- 3Create the ProvideX.Script object and call Init with the full path to the MAS90\Home folder as it appears to the machine running the script (a UNC path is safest).
- 4Create the session with NewObject("SY_Session"), call nLogon, then nSetCompany with the company code and nSetDate and nSetModule for the module whose objects you will use.
- 5Create the business object with NewObject("AR_Customer_bus", oSS), set the key with nSetKeyValue for each key segment, then call nSetKey to load the record.
- 6Read fields with nGetValue (the field name carries the dollar suffix for string fields) and write with nSetValue followed by nWrite. Always test the return value; 1 means success and 0 means failure.
- 7On any 0 return, read oSS.sLastErrorMsg for the session, or the business object's own sLastErrorMsg, and log it before you continue.
- 8Release the objects in reverse order and set them to Nothing so the session and licence are freed.
A minimal read example
The pattern below logs on, selects a company, loads customer 01-ABF and prints the name and balance. The same shape applies to nearly every BOI object: AR_Customer_bus, AR_Invoice_bus, SO_SalesOrder_bus, IM_Item_bus, PO_PurchaseOrder_bus and others. The object names follow module prefix, entity, then _bus.
Two details trip people up. First, string fields carry a trailing dollar sign and numeric fields do not (CustomerName$ versus CurrentBalance). Second, nGetValue returns its result through a by-reference argument, so in VBScript you pass a variable rather than using the return value of the call.
Set oScript = CreateObject("ProvideX.Script")
oScript.Init "\\server\Sage\Sage 100 Advanced\MAS90\Home"
Set oSS = oScript.NewObject("SY_Session")
If oSS.nLogon() = 0 Then WScript.Echo oSS.sLastErrorMsg : WScript.Quit
oSS.nSetCompany "ABC"
oSS.nSetDate "A/R", "20260131"
oSS.nSetModule "A/R"
Set oCust = oScript.NewObject("AR_Customer_bus", oSS)
oCust.nSetKeyValue "ARDivisionNo$", "01"
oCust.nSetKeyValue "CustomerNo$", "ABF"
If oCust.nSetKey() = 1 Then
oCust.nGetValue "CustomerName$", sName
oCust.nGetValue "Balance", nBal
WScript.Echo sName & " " & nBal
Else
WScript.Echo oCust.sLastErrorMsg
End IfWriting a record safely
For a new record call nSetKeyValue for the key segments, then nSetKey, which returns a value indicating the key does not exist yet; then use nSetValue for each field and finish with nWrite. For an existing record, nSetKey loads it and you call nSetValue then nWrite to update. If nWrite returns 0, the record is not saved, and sLastErrorMsg normally names the field that failed validation.
Because BOI runs the same validation as data entry, it enforces required fields, valid terms codes, credit-limit rules and the company's own UDF validation. That is the main reason to prefer it over writing directly to the .M4T data files or through ODBC. Direct file writes skip sort-file maintenance, audit trails and posting dependencies, and can corrupt data that Sage then reports as damaged files.
For sales orders, use SO_SalesOrder_bus for the header and its Lines child object (reached through the business object's GetChildHandle method) to add detail lines before the header write. Set SalesOrderNo to the next number via the object's own number-assignment logic instead of inventing one, so you do not collide with users entering orders at the same time.
Why logon and Init fail
The most common failures are path and bitness. Init needs a folder the script's user account can read, and a scheduled task running as a service account often cannot see mapped drive letters, so use a UNC path. A 32-bit script host talking to a 64-bit-only install, or the reverse, produces a CreateObject failure; run the script with the matching WScript or CScript from SysWOW64 or System32.
If CreateObject itself fails, the COM class is not registered on that machine; run the workstation setup there. If nLogon returns 0, read sLastErrorMsg: typical text points to an invalid user or password, a user without external access, a company in the middle of an update, or a licence limit. Every BOI session consumes a Sage 100 user licence for as long as it is open, so unreleased sessions from crashed scripts can exhaust licences.
Alternatives and when to use them
For reporting, ODBC with the Sage 100 driver is simpler and read-only, and fits Excel, Power BI and Crystal. For bulk imports of tabular data, the built-in Visual Integrator imports (Library Master, Main, Visual Integrator) call the same business logic and need no code. For larger programmatic integrations, Sage also publishes later web-service style options on newer releases, so check the release you run.
BOI is the right tool when the logic must be scripted: creating orders from a web store, posting a nightly batch from another system, or synchronising customers. Expect to write retry and error logging yourself, because the interface returns terse text.
Common pitfalls
- !Writing to the data files or through ODBC instead of BOI: it bypasses validation and can corrupt sort files and break audit trails.
- !Using a mapped drive letter in Init for a scheduled task: the service account does not see your drive mappings.
- !Forgetting the dollar suffix on string field names, which returns empty values with no obvious error.
- !Ignoring return values: BOI methods return 0 on failure and a script that keeps going will half-write documents.
- !Leaving sessions open after errors, which holds Sage 100 licences until the process ends.
- !Setting company code or module date inconsistently, so records are written with the wrong posting period or date.
How an ERP-grounded AI assistant handles this
An assistant grounded in the Sage 100 data dictionary can draft the BOI script for a stated task, check field names and types against the dictionary (including UDFs), and explain a returned sLastErrorMsg. Netray's ERPray approach is read-first: it answers questions over the data with the query shown, and any write goes through the business object layer with human approval rather than through direct file access. It does not replace testing the script against a copy company.
Frequently asked questions
Is BOI the same as the Sage 100 ODBC driver?
No. ODBC is read-only access to the data tables for reporting and tools like Excel or Power BI. BOI is a COM interface to the business objects, so it can read and write while running the same validation and posting rules as the screens.
Do I need a Sage 100 licence for each BOI script?
A BOI session logs on as a Sage 100 user and consumes a user seat while it is open. Plan for that in schedule design, and always close the session. Check your licence agreement for any rules on integration users.
Why does CreateObject("ProvideX.Script") fail?
The COM class is registered by the Sage 100 workstation install, so a machine without that install, or a bitness mismatch between the script host and the install, fails at that line. Install the workstation setup and run the matching 32-bit or 64-bit script host.
Can I use PowerShell or C# instead of VBScript?
Yes. Any COM-capable language can create ProvideX.Script. The method names and by-reference argument behaviour stay the same, but by-reference outputs need extra care in .NET, where a variant or ref parameter is required.
Related
How to Void a Check in Sage 100
Sage 100 voids checks through Accounts Payable > Main > Check and Payment Voiding. Select the bank code, choose the check number, and Sage reverses the Cash Disbursements Journal entry and reopens the invoice it paid. A check that already cleared in Bank Reconciliation or falls in a closed period needs an extra step before it can be voided cleanly.
Error fixFix Sage 100 SOTAMAS90 ODBC Connection Errors
Most Sage 100 ODBC failures are one of four things: the DSN was created in the wrong 32-bit or 64-bit ODBC administrator for the tool you use, the DSN path or company code is wrong, the Windows account cannot read the MAS90 folder, or the Sage 100 user lacks external access. Recreate the DSN in the matching administrator and test with the driver's own Test button before blaming Excel or Power BI.
How-toHow to Add User Defined Fields (UDFs) in Sage 100
In Sage 100 you add a user defined field through Custom Office: open the Customizer Selection for the module, create the field with a name, type and length, then place it on the relevant data entry panel using the Customizer. UDFs are stored in the module's tables with a UDF_ prefix, which is how they appear in ODBC, Crystal and imports once the field is defined.
How-toSage X3 REST API: Reading Sales Orders Through Syracuse
Sage X3 (version 7 and later) exposes data through Syracuse at a URL of the form /api1/x3/erp/ENDPOINT/REPRESENTATION, where the endpoint is the folder and the representation is a published object such as SORDER. A GET with credentials returns JSON, and you filter with a where clause and page with count and a link to the next page. Your integration user needs the right Syracuse and X3 rights for that representation.
How-toHow to Create a Generic Inquiry in Acumatica
Generic Inquiries (GI) are Acumatica's no-code query builder for joining tables, adding filters, and exposing the result as an inquiry screen, dashboard data source, or API endpoint. Open System > Customization > Generic Inquiry, add your base table, define joins and conditions, then run and save. No SQL or customization project is required.
Error fixFix Odoo AccessError: You Are Not Allowed to Access Records
Odoo raises AccessError when a user's security groups do not grant a CRUD right on a model through ir.model.access.csv, or when an ir.rule record rule filters the specific record out for that user or company. Fix it by adding the user to the group named in the error, editing the model's access rights, or reviewing the record rule's domain under Settings > Technical > Security.
AI for ERPAI for Sage 100, Grounded in Your MAS90/200 Data
Put AI on Sage 100 and the Sage 100 Manufacturing (MRP) data set without sending data to a public model. Private LLMs and agents grounded in your MAS90/200 tables.
Stuck on Sage 100?
Talk to engineers who work inside Sage 100 every week, and who build private AI that answers these questions from your own ERP data.