Sage Summit 2015: Early Bird Registration Rates Extended to 5/15!


We are looking forward to what is sure to be another exciting Sage Summit! This year’s conference takes place July 27-30 in New Orleans, Louisiana at the Ernest N. Morial Convention Center.

Did you know Sage customers can take advantage of an early registration price of $399? This rate is in effect until April 30, 2015 has been extended through May 15!


Note that on the registration page, you’ll find tabs for hotel packages
and airfare discounts.

What is Sage Summit?

In case you are new to this annual event, we’ll give you the run-down. Sage Summit is a four-day convergence of Sage partners and customers, packed with training sessions, and informative presentations on topics relating to ERP solutions, technology, and specific industry sectors. It includes a showroom floor to enhance the networking opportunities and give customers a chance to explore new technologies.

Sage Summit keeps it high profile, too. Last year’s speakers included Magic Johnson, Biz Stone of Twitter, and Jessica Alba.

xkzero Representation

Sage also calls on those with the pulse on issues affecting the Sage community, including our own Paul Ziliak, co-founder of xkzero. He emphasized the significance of mobile ERP in this presentation: Why Mobile, Why Now?. Turns out people enjoyed it so much that Paul was invited to speak again this year. Stay tuned for details!

As always, we will have a presence on the showroom floor, where we look forward to connecting with present and future partners and customers. We welcome you to stop by for a demo of our mobile apps such as xkzero Mobile Commerce, iSales 100, and GetX, all of which integrate with Sage ERP solutions.

It’s been an exciting time for xkzero, as we have grown a bit since Sage Summit 2014. We bring new offerings such as xkzero Technical Services, and have expanded our channel sales territories. These changes have also led to additional staff who some of you might know from their years of success in the Sage community. Be sure to visit our booth to greet our whole team!

Sage Summit 2015 Sneak Peek

We don’t have all the sought-after details about special guests or closing night celebrations, but Sage has provided the following calendar information so you can start plotting your Summit story now!:

This just in! Sage announced that Paul Ziliak will speak in the thought leader series again. He will present these two talks:
TL-134: Why mobile, why now? A decision maker’s guide to business success
TL-139: Disrupt your industry: Making your mobile dream a reality


The inspirational energy at Sage Summit can be quite contagious. We hope to see you in New Orleans!


At xkzero, we believe that people perform best when they are confident, informed, and have a high level of trust in the tools they use. Maybe it’s time for your wholesale distribution business to start gearing up with mobile apps. If your ERP data tells the story of your customers and your inventory, shouldn’t you equip your team to have that information in their pockets?

Contact us at or 847-416-2009, we can help you create a mobile plan that works for you.

5 Important Things To Know About iSales 100


iSales 100



As you prepare to mobilize your sales force with a smart phone or tablet, here are a few things about iSales 100 you might like to know.


1.  iSales 100 Follows an Unlimited User and Device Licensing Model

No need to worry about additional iSales 100 user fees or set-up delays when you hire a new sales rep. iSales 100 is offered exclusively using an unlimited user and unlimited device model. That means that as you grow your sales team, your incremental cost of ownership won’t grow with it. xkzero offers 3 versions of iSales 100 – Inquiry/Business/Enterprise. Your xkzero account rep will be sure to identify the correct feature set for you.

As a bonus – let’s say you wanted to give one or more of your customers access to their account information – or perhaps even to have them enter their own orders directly from their iPhones or iPads. No problem! iSales 100 has the power and flexibility to provide your customers the access that is right for them. Isn’t an unlimited license model great?

2.  Management of iSales 100 is Native to Sage 100 ERP

iSales 100 was designed with native management within Sage 100 ERP for one simple reason:
When setting up users, assigning customers, establishing rules, etc. we felt the customers would want the easiest possible experience to administer the application. What better way to manage iSales 100 than to build it directly into your already familiar Sage 100 ERP interface?

The result is that system administrators who already know the Sage system can quickly and confidently set up and manage users and permissions. No middleware to learn here!

Native integration makes managing and adapting to your rules quick and easy

Native integration makes managing and adapting to your rules quick and easy.

3.  We Follow Your Rules

We’ve seen some nicely designed mobile sales apps that have one minor problem. As soon as the user presents a unique feature request in order to satisfy an important business process or rule, they find out that request cannot be accommodated.

Those nice looking apps turn out to lack the capability to adapt to unique and changing needs, and end up being a fancy electronic catalog (which is fine if that’s what you need).

At xkzero we’ve noticed that companies are willing to invest in mobile sales apps when their specific needs can be met. Not only are we mobile app developers, but we are ProvideX programmers too—really good ones.

With our native integration and ProvideX programming capabilities, we’re often able to take care of a custom request not by modifying iSales 100 itself, but often simply by making a slight change on the back end using ProvideX, and allowing the back end rules drive the user experience.

4.  iSales 100 May Be the Only “CRM” You Need

Calendar integration, email integration, phone integration.  Access to customer memos.

Create new order memos. View open orders and invoices. Check inventory warehouse quantities and prices.  Review customer last purchase history.

iSales 100 lets you do all of these things and more. What we’ve found is that many of our target customers—Distribution and Manufacturing companies—don’t need or want an expensive CRM system. For them, leveraging what is special about smart phones and tablets combined with direct Sage 100 ERP integration gives them all the “CRM” information they need to better serve customers and prospects.

Still Need CRM?

5.  Supports Apple Mobile Devices Only

“iSales 100 is great, but I already have Android phones.” We hear just that sort of thing frequently, but we continue to offer iSales 100 only for iOS (meaning Apple iPhone, iPad, iPad Mini and iPod Touch).

Why? At xkzero we believe that reliability, dependability and supportability are three non-negotiables when it comes to creating a great mobile sales app experience for the user. iSales 100 is used primarily as a tool to book a sale when it happens, often in customer facing situations. The last thing you can afford is for the app to not work.   Especially if you are scanning bar codes, swiping a card payment or printing a receipt or proof of delivery, a dependable and stable platform is a must.

No doubt you can do lots of cool things with Android and there are many passionate fans of that platform, but supporting Android means supporting potentially dozens if not hundreds of different hardware combinations. Each new hardware device introduces exponentially more possible failure points and we don’t care to take that risk. iSales 100 is not perfect and neither is Apple, but we’re rolling with the most stable, easiest to support platform for mobile today, and we think you get a better experience because of it.

At xkzero, we believe that people perform best when they are confident, informed, and have a high level of trust in the tools they use. Maybe it’s time for your wholesale distribution business to start gearing up with mobile apps. If your ERP data tells the story of your customers and your inventory, shouldn’t that knowledge by in your pocket?

Contact us at or 847-416-2009, we can help you create a mobile plan that works for you.




How to Prevent Duplicate Customer Names with Scripting

Scripting Tips for Sage 100 ERP

Blogger: Alnoor Cassim, xkzero Technical Services


One of the primary reasons users make customizations in Sage 100 ERP is to add business rules to accommodate a business process. Often, you can do this yourself with a script. To illustrate, let’s say we have been asked to do the following:

A script can be just what you need to prevent an action!

When a new customer is entered in Customer Maintenance, you want the following steps to occur:

  1. Check the customer name against all other records for duplicates.
  2. Prevent any duplicate customer names from being repeated on the new customer record.
  3. Display a message to indicate that the name is already being used. Include the customer number.
  4. Audibly reinforce the message with an alert sound or spoken words.

Is it possible to create these steps with scripting? Most certainly!
Note that a well thought-out and researched script can accomplish the task in an efficient and optimal way. However, a less carefully planned script (or modification) can run into performance issues and may not return the correct results 100% of the time.

The good news is you will see the well-designed version! It is a short script but appears to be longer because it is heavily commented. Bonus: Many concepts applied in this script can be also be applied to other scripts you write.

What kind of script do you need to create?
Create an event script (a.k.a. User Defined Script) that runs when the customer name is entered in Customer Maintenance. The event type we are using is called Column Pre-Validate. All of the “Pre” events (Pre-Validate, Pre-Write, Pre-Delete) are designed for you to add a user-defined validation and prevent an action from occurring.

How do you create this script?

Follow these steps:

  1. Go to the Custom Office/Main Menu, and make these selections:
    “User-Defined Field and Table Maintenance”
  2. Under the “Accounts Receivable” heading, choose: “AR Customer Master.”
  3. Right-click and choose “User Defined Scripts.”
  4. In the “User Defined Script” window, click the “Add” button. This will open the “Add Script” window.
  5. In the “User-Defined Script–Add Script” window, as shown below, make these choices:
    Event: “Column–Pre-Validate”
    Type in a name for your script, such as this:
    “Find Dupe Cust Name Play Sound”
  6. You will see a message indicating that the script file does not exist, followed by a question, “Do you want to create it? Yes/No?”
    Yes, you do want to create the script! Click: “Yes.”
  7. Now the “Edit Script” window will appear. Copy the following code and paste it into your script editor window. Note: It is important to use the code exactly as shown below, including line breaks and spaces.

'Alnoor Cassim - xkzero - Prevent Duplicate Customer Names and Play Sound

'Init VARs
DupeCustNo = "" : DupeCustName = ""

'Run only for new customers by verifying EditState = 2
'An EditState = 1 means an existing record, 0 means no record loaded.
'oBusObj is the primary connection to AR_Customer table.

If oBusObj.EditState = 2 Then

'Create a separate new connection to AR_Customer
'Use the service object since we are not writing back data
'Use this syntax

Set oCustomer = oSession.AsObject(oSession.GetObject("AR_Customer_svc"))

'Searching one record at a time from top to bottom would be slow
'Set the KNAME index as the browse index to do a fast search of Customer Name	
'KNAME from File Layouts: CustomerName+ARDivisionNo+CustomerNo

retVal = oCustomer.SetBrowseIndex("KNAME", "")

'The variable called "value" represents what you typed in for the Customer Name.
'Assign "value" to your own variable. We will call our variable "Name".
'Strip any trailing spaces and force Upper Case to avoid a case sensitive search.

Name = UCase(RTrim(value))

'We do not have the values for all 3 columns of KNAME index.
'So create a filter to pass in just the CustomerName as a partial value.
'This is done with the SetBrowseFilter() function.

retVal = oCustomer.SetBrowseFilter(Name)

'Now this MoveFirst() command will both be filtered by name and use the KNAME index.
'This will result in a fast search!

retFound = oCustomer.MoveFirst()

If retFound = 1 Then

'retFound is the return value. It will hold either a 1 (found) or 0 (not found).
'If 1 then we found at least a partial match but now check if it is an exact dupe.

retVal = oCustomer.GetValue("CustomerNo$", DupeCustNo)
retVal = oCustomer.GetValue("CustomerName$", DupeCustName)

'A short dupe is OK. Ex: You typed "Road" and the search found "RoadRunner"
'Only reject if you typed in RoadRunner. This is how:

If Name = UCase(RTrim(DupeCustName)) Then

'The SetError() function will both show the message and prevent the dupe name.

sMsg = "This name is already used with Customer No " & DupeCustNo
retVal = oScript.SetError(sMsg)

'Play a Windows sound event using the ProvideX PRINT BEEP function.
'This plays back sound on the wkstn even in Sage 100 Advanced and Premium

oScript.Execute("PRINT "+"'BEEP'"+CHR(40)+CHR(34)+"*.Default,w"+CHR(34)+")")

'That was the registered default event sound in Windows.
'Look in registry for more registered sounds. Leave the "*" in front.
'E.g. "*EmptyRecycleBin,w"

End If 'check if a duplicate name was found

End If 'allow for short duplicate names

End If 'check if on a new record

How does this script work?

To better understand the logic behind the script’s functionality, read this:

“Init VARs”
In the first section, we “initialize” (init) the variables to prepare for use later in the script.

Through these stated conditions, we apply logic to check if we’re in a new record, then later to check if we have found a customer name match, and then later to check for an exact name match.

How do we find out if the customer is new or existing?
We do this by checking the “edit state” as indicated by the following values:

2 = new customer
1 = existing customer
0 = no customer on the screen

How to Use a Secondary Customer Object
When the script starts we already have an existing Customer object in memory called oBusObj. For this script we need to create a secondary connection to the same Customer object by using the GetObject() function. We will call that second object oCustomer. In our case we set oCustomer as the handle for AR_Customer_Svc. However, if we need, to write back data we use AR_Customer_bus instead.

How to Use an Alternate Index for Searching, Set a Browse Filter, and Find the Result
The primary index is called KPRIMARY and contains the ARDivisionNo and CustomerNo columns. We can use KPRIMARY for finding the duplicates but would have to check the CustomerName column on every row until a match is found. This type of sequential top to bottom search is very slow.

Instead, we look for an index that starts off with CustomerName. From the File Layouts link in Sage 100 ERP, under AR_Customer table, we see the KNAME index contains what we need. We will apply this to the oCustomer handle. Also, to make sure we only change the index for the purpose of searching, we use the SetBrowseIndex() function with “KNAME” passed in as 1st argument and an empty string as the 2nd argument.

One issue with KNAME is that it comprises three columns that make up this alternate key, yet we only want to search by the one CustomerName column. So, we must set a partial key by creating a filter to pass in the CustomerName. This is done with the SetBrowseFilter() function and we apply it to the oCustomer handle as well.

Now we use the MoveFirst() function. Normally it would just move to the first row of the record set. In this case it finds the first matching result based on our browse filter and searches in KNAME order.

The retFound variable represents a return value, just like the retVal variable does. We can use any numeric variable for return values.

If our search finds a match, then retFound = 1.
Otherwise, retFound = 0.

Partial Duplicate vs Exact Match
After using MoveFirst() and after retFound = 1, we can have a situation where we have a partial duplicate match instead of an exact match.

For example, if you type “Grass” for the customer name, the MoveFirst() search result may include “GrassHopper Pesticide Corp.” You don’t want this search to prevent you from using “Grass,” so to find an exact match, we do the GetValue() function to compare the actual name against the searched name.

Rejecting the Customer Name
Once an exact match has been found, now we have to actually reject/prevent the customer name that was entered in the screen from being used. This is accomplished with the SetError(“User Defined Message”) function. It will both show your user defined message and prevent the name you enter on the screen from being used.

Playing a Windows System Sound
Use the PRINT BEEP command noted in the script to play a Windows sound event. In Advanced and Premium environments the sound will play on the workstation.

You’re almost done! 

Now you can accept the script.
This will return you to the “Add Script” window.

  1. To close this screen and return to the “User Defined Scripts” window, click “OK.”
  2. Next, to go back to the main “User Defined Field” and “Table Maintenance” window, click “Close.” Here, you must also click “Close” again to see the “Script Compile” window.
  3. IMPORTANT: When the “Script Compile” window appears, click the Compile” button.

Note that you can further edit the script, if necessary. To do so, from the “Custom Office/Main” menu, choose the “User Defined Script Maintenance” task. When done editing the script, to syntax check the script, click the Check Script button:

To save the script, click the Accept button.

The next step is to click the Compile button in the lower-left of the screen. When the Script Compile window appears, click the Compile button again followed by the Close button.

How to Use the Windows Text To Speech (TTS) API to Speak the Words
As an alternative to playing a system sound you can play back the spoken words of the error message using a Windows Accessibility feature called Text To Speech (TTS). This is challenging to use in Sage 100 Advanced and Premium because the playback needs to occur at the workstation, not the server. [Credit goes to Sage 100 VAR Vrakas/Blum for coming up with the TTS idea and asking how to play the voice on the workstation.]

Sage 100 ERP Advanced/Premium:

It turns out running any event script for Advanced/Premium is a challenge, since by design it executes on the server yet we need it to execute on the client. Button scripts have a nice option to “Execute Script on Client” vs “Execute Script on Server” but event scripts do not.

This is when we need to pull out our bag of tricks.

We will need a total of 2 scripts. The 1st script is actually the same one as above but we substitute the PRINT BEEP code with the following script:

'Text To Speech version of Playing Sound

'Check if we are on Sage 100 Advanced or Premium edition
If oSession.CS Then  

'Set location for Workstation Script. Change the file name as needed.

WSH = "WScript.exe "  'This is the Windows Scripting Host
vbsCMD = CHR(34) & WSH & WkstnScript & CHR(34) 'Form the o/s cmd to run a VB Script
oScript.Execute("ShellCMD$ = " & vbsCMD) 'Pass the cmd into a pvx variable ShellCMD$

'Fire off the script at the workstation. The [wdx] indicates run from the client.
oScript.Execute("CALL "+CHR(34)+"[wdx]SYZDLL;SHELL_AND_WAIT"+CHR(34)+",ShellCMD$")

'We are on Sage 100 Standard so it will already run from the client.

'Tap into TTS feature. More info can be found here:
If IsObject(oVoice) = False Then
Set oVoice = CreateObject("SAPI.SpVoice") 
End If

Words = "This customer name is already used."
retVal = oVoice.Speak(Words)

End If

The Text to Speech workstation script (for Advanced and Premium) will look like this:

'Workstation Script but physically located on server here
'NOTE: Rename the file as needed but you must save it as VBS not TXT.

'Tap into TTS feature. More info can be found here:
If IsObject(oVoice) = False Then
Set oVoice = CreateObject("SAPI.SpVoice") 
End If

Words = "This customer name is already used."
retVal = oVoice.Speak(Words)

This is one of many Sage 100 ERP scripting examples we will share through the xkzero blog. If you need help with scripting or other programming or technical issues with your Sage ERP, no matter how complex, please feel free to contact us: 

xkzero Technical Services
Call: 847-416-2009


What Do You Want from a Mobile Sales App?



What do you want from a mobile sales app?  If you haven’t answered that question yet, it’s likely your smart phone (or your tablet, or your Apple watch) has zero information about customers, inventory—or anything about your business that can make you and your team more nimble and better informed.

Most of us have no lifeline to our business—other than email—when we’re physically away from the office.

But here’s the thing—some companies actually do have all kinds of valuable business information in their pockets. They empower employees with everything they might possibly want to know about their customers, products, and even financials. These professionals have everything essential to their businesses—right in their pockets.

Employees of those companies can answer pretty much anything a customer or another team member might ask about an account, or about product or service. Any time. And with confidence.

That’s true whether they are on the road, at a customer site, at a tradeshow or conference, at the home office, or even on vacation. Those people are better prepared, better informed, and more able to serve the customer.

You can have that, too. To get started, all you need to do is answer this question: What do you want from a mobile sales app?

Driver and Technology

Driver and Technology


Having a hard time figuring out how to introduce mobile into your business? Want to grow your distributor or manufacturing company with mobile sales and other ERP system technology? We can help and we’d love to hear from you! or 847.416.2009 or @erp_apps or Paul Ziliak @PaulZiliak