C# Create Sales Invoice From Sales Order; nSetKey() fails, sLastErrorMsg = "The [InvoiceNo] is invalid"

I am on Sage 100c Standard 2016 (Version 5.30.5.0) (yes, I know it is very old, and have plans to upgrade to a supported version).  I am attempting to create a program in C# that creates a sales invoice from a sales order.

When my program executes the this line of code... cmd.InvokeMethod("nSetKey"); ... something terrible must happen.

No matter what I try MessageBox.Show(cmd.GetProperty("sLastErrorMsg").ToString()); pops up "The 0292983 is invalid".  Except, each time that it runs, it obviously increments the invoice# by 1.

If I change "cmd.InvokeMethod("nSetKey");" to "success = (int)cmd.InvokeMethod("nSetKey");" it produces an exception of "System.NullReferenceException: Object reference not set to an instance of an object"

I've been searching this forum for clues, but I've been spinning my wheels for days, and cannot get passed this error.  I am hoping there is someone out here that can help with with this problem.

Thanks.

using (DispatchObject pvx = new DispatchObject("ProvideX.Script"))
{
pvx.InvokeMethod("Init", strsage_path);
using (DispatchObject oSS = new DispatchObject(pvx.InvokeMethod("NewObject", "SY_Session")))
{
success = (int)oSS.InvokeMethod("nSetUser", strusername, strpassword);
if (success == 1)
{
success = (int)oSS.InvokeMethod("nSetCompany", strcompany);
if (success == 1)
{
success = (int)oSS.InvokeMethod("nSetDate", "S/O", DateTime.Today.ToString("MMddyyyy"));
if (success == 1)
{
success = (int)oSS.InvokeMethod("nSetModule", "S/O");
if (success == 1)
{
task_id = (int)oSS.InvokeMethod("nLookupTask", "SO_Invoice_ui");
if (task_id > 0)
{
oSS.InvokeMethod("nSetProgram", task_id);
using (DispatchObject cmd = new DispatchObject(pvx.InvokeMethod("NewObject", "SO_Invoice_bus", oSS.GetObject())))
{
if (new_batch_flag == true)
{
strBatchNo = "";
param = new object[] { strBatchNo, "N", "BOL " + DateTime.Today.ToString("MM/dd/yyyy") };
success = (int)cmd.InvokeMethodByRef("nSelectNewBatch", param);
if (success == 1)
{
strBatchNo = param[0].ToString();
}
else
{
strBatchNo = "";
Cursor.Current = Cursors.Default;
MessageBox.Show(cmd.GetProperty("sLastErrorMsg").ToString());
}
}
if (strBatchNo.Length > 0)
{
success = (int)cmd.InvokeMethod("nSelectBatch", strBatchNo);
if (success == 1)
{
InvoiceNo = new object[] { "" };
success = (int)cmd.InvokeMethodByRef("nGetNextInvoiceNo", InvoiceNo);
if (success == 1)
{
tbxInvoiceNo.Text = InvoiceNo[0].ToString();
param = new object[] { "InvoiceNo$", InvoiceNo[0].ToString() };
success = (int)cmd.InvokeMethod("nSetKeyValue", param);
cmd.InvokeMethod("nSetKey");
MessageBox.Show(cmd.GetProperty("sLastErrorMsg").ToString());

  • in reply to Patrick Hartnett

    Sorry Patrick...  I did NOT find a solution to that problem. I had to abandon Object Interface, and do what I needed to do in Visual Integrator instead.  Once I upgrade to the latest version of Sage, I figure I'll try Object Interface again.

  • in reply to B26354

    If you want to post the whole project to github or pastebin I might be able to help you through it. I have not tried moving an order to an order-invoice, but I do actively create and edit sales orders through the BOI. 

    My call for generating an SO is as follows: 

        object[] oNextSalesOrder = new object[] { "" };
        Core.SageObject.Process(so_order.InvokeMethodByRef("nGetNextSalesOrderNo", oNextSalesOrder), so_order);
        Core.SageObject.Process(so_order.InvokeMethod("nSetKey", oNextSalesOrder), so_order);
        //Update the order objerct to the correct number
        Order.SalesOrderNo = (string)oNextSalesOrder[0];

    Where "Core.SageObject.Process" is: 

            public class SageObject
            {
                // All errors are passed into this event
                // Handle these error messages however you want
                // in your application => Logging or a message box
                public static event RaiseEvent SageError;
                public delegate void RaiseEvent(string EventText);
    
                public int ReturnCode { get; set; }
                public string LastErrorMessage { get; set; }
    
                public static SageObject Process(object Method, DispatchObject Object)
                {
                    object retVal;
                    string ErrorMessage = string.Empty;
                    retVal = Method;
    
                    if ((int)retVal != 1)
                    {
                        ErrorMessage = Object.GetProperty("sLastErrorMsg").ToString();
                        if (SageError != null) { SageError(ErrorMessage); }
                    }
    
                    return new SageObject(ErrorMessage, (int)retVal);
                }
    
                public SageObject(string LastErrorMessage, int ReturnCode)
                {
                    this.LastErrorMessage = LastErrorMessage;
                    this.ReturnCode = ReturnCode;
                }
            }