I have an issue in the .Net library AP Sage300 (Version 2019)

SUGGESTED

I have an issue in the .Net library I have no issue creating a vendor using a macro:

Dim mDBLinkCmpRW As AccpacCOMAPI.AccpacDBLink
Set mDBLinkCmpRW = OpenDBLink(DBLINK_COMPANY, DBLINK_FLG_READWRITE)

Dim mDBLinkSysRW As AccpacCOMAPI.AccpacDBLink
Set mDBLinkSysRW = OpenDBLink(DBLINK_SYSTEM, DBLINK_FLG_READWRITE)

Dim temp As Boolean
Dim APVENDOR1header As AccpacCOMAPI.AccpacView
Dim APVENDOR1headerFields As AccpacCOMAPI.AccpacViewFields
mDBLinkCmpRW.OpenView "AP0015", APVENDOR1header
Set APVENDOR1headerFields = APVENDOR1header.Fields

Dim APVENDOR1detail As AccpacCOMAPI.AccpacView
Dim APVENDOR1detailFields As AccpacCOMAPI.AccpacViewFields
mDBLinkCmpRW.OpenView "AP0407", APVENDOR1detail
Set APVENDOR1detailFields = APVENDOR1detail.Fields

APVENDOR1header.Compose Array(APVENDOR1detail)

APVENDOR1detail.Compose Array(APVENDOR1header)


Dim APVENDSTAT2 As AccpacCOMAPI.AccpacView
Dim APVENDSTAT2Fields As AccpacCOMAPI.AccpacViewFields
mDBLinkCmpRW.OpenView "AP0019", APVENDSTAT2
Set APVENDSTAT2Fields = APVENDSTAT2.Fields


Dim APVENDCMNT3 As AccpacCOMAPI.AccpacView
Dim APVENDCMNT3Fields As AccpacCOMAPI.AccpacViewFields
mDBLinkCmpRW.OpenView "AP0014", APVENDCMNT3
Set APVENDCMNT3Fields = APVENDCMNT3.Fields


APVENDSTAT2Fields("YTDACTIVE").Value = "1" ' Enable YTD Calculations
APVENDOR1header.RecordClear
APVENDSTAT2.RecordClear

APVENDSTAT2Fields("CNTYR").PutWithoutVerification ("2020") ' Year
APVENDOR1headerFields("VENDORID").Value = "TEST1" ' Vendor Number
temp = APVENDOR1header.Exists

APVENDOR1headerFields("VENDNAME").Value = "Test1" ' Vendor Name

APVENDOR1headerFields("IDGRP").Value = "ANFL" ' Group Code

APVENDOR1header.Insert
APVENDSTAT2.RecordClear

APVENDSTAT2Fields("VENDORID").PutWithoutVerification ("TEST1") ' Vendor Number
APVENDSTAT2Fields("CNTYR").PutWithoutVerification ("2020") ' Year


But using .net :

ACCPAC.Advantage.View apVendorHeaderView = dbLink.OpenView("AP0015");
ACCPAC.Advantage.View apVendorDetailView = dbLink.OpenView("AP0407");
ACCPAC.Advantage.View apVendorStatsView = dbLink.OpenView("AP0019");
ACCPAC.Advantage.View apVendorCmntView = dbLink.OpenView("AP0014");

apVendorHeaderView.Compose(new ACCPAC.Advantage.View[] { apVendorDetailView });
apVendorDetailView.Compose(new ACCPAC.Advantage.View[] { apVendorHeaderView });

apVendorStatsView.Fields.FieldByName("YTDACTIVE").SetValue(1, true);
apVendorHeaderView.RecordClear();
apVendorStatsView.RecordClear();
apVendorStatsView.Fields.FieldByName("CNTYR").SetValue(DateTime.Now.Year, false);
apVendorHeaderView.Fields.FieldByName("VENDORID").SetValue(vendors.Tables[0].Rows[0]["ConsultantReference"].ToString(), false);
bool exist = apVendorHeaderView.Exists;
apVendorHeaderView.Fields.FieldByName("VENDNAME").SetValue(vendors.Tables[0].Rows[0]["CompanyName"].ToString(), false);
apVendorHeaderView.Fields.FieldByName("IDGRP").SetValue(vendors.Tables[0].Rows[0]["IDGRP"].ToString(), false);
apVendorHeaderView.Insert();

I get the error "Tax group cannot be blank."

I don't see I am missing anything, since IDGRP is set, the tax group should be deducted as in the macro

  • Looks like you're reading info from an Excel sheet in the .Net example.  Did you try explicit values to ensure it's not an issue reading data from Excel?

  • I verified all values they are all valid at execution time

  • 0 in reply to johnny9864

    Use PutWithoutVerification, not SetValue.

  • 0 in reply to Jay Converse Acumen

    Doesn't exist in .net libraries

  • 0
    SUGGESTED

    First I'd write a small Windows forms app to add a vendor. Then I would modify it to pull data from wherever you're getting data.

    In C#, when you create a forms project and call it AddVendor, set the debug and release to be x86 in the project properties. Add a reference to the Accpac Advatange and Accpac Advantage Types DLLs which should be found in C:\Program Files (x86)\Common Files\Sage\Sage 300 ERP\ACCPAC.Advantage.Types.dll and ACCPAC.Advantage.dll.

    I created a form with a couple of text boxes so I could put in a new vendor ID and name and a button to add it to Sage. The code is here:

    using ACCPAC.Advantage;
    using System;
    using System.Windows.Forms;
    
    namespace AddVendor
    {
        public partial class Form1 : Form
        {
            Session accpacSession;
            DBLink mDBLinkCmpRW;
    
            ACCPAC.Advantage.View APVENDOR1header;
            ACCPAC.Advantage.View APVENDOR1detail1;
            ACCPAC.Advantage.View APVENDOR1detail2;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                try
                {
                    // Create the session
                    accpacSession = new Session();
                    accpacSession.Init("", "XY", "XY1000", "67A");
                    accpacSession.Open("ADMIN", "ADMIN", "SAMLTD", DateTime.Today, 0);
                    mDBLinkCmpRW = accpacSession.OpenDBLink(DBLinkType.Company, DBLinkFlags.ReadWrite);
    
                    // Open the views
                    APVENDOR1header = mDBLinkCmpRW.OpenView("AP0015");
                    APVENDOR1detail1 = mDBLinkCmpRW.OpenView("AP0407");
                    APVENDOR1detail2 = mDBLinkCmpRW.OpenView("AP0222");
    
                    // Compose
                    APVENDOR1header.Compose(new ACCPAC.Advantage.View[] { APVENDOR1detail1, APVENDOR1detail2 });
                    APVENDOR1detail1.Compose(new ACCPAC.Advantage.View[] { APVENDOR1header });
                    APVENDOR1detail2.Compose(new ACCPAC.Advantage.View[] { APVENDOR1header });
    
                    // Add data to views
                    APVENDOR1header.Fields.FieldByName("VENDORID").SetValue(textBox1.Text.Trim(), true);
                    APVENDOR1header.Fields.FieldByName("PROCESSCMD").SetValue("0", false);
                    APVENDOR1header.Process();
                    APVENDOR1header.Fields.FieldByName("VENDNAME").SetValue(textBox2.Text.Trim(), true);
                    APVENDOR1header.Fields.FieldByName("IDGRP").SetValue("MIS", true);
                    APVENDOR1header.Fields.FieldByName("PROCESSCMD").SetValue("0", false);
                    APVENDOR1header.Process();
                    APVENDOR1header.Fields.FieldByName("LEGALNAME").SetValue("Legal Name", true);
                    APVENDOR1header.Fields.FieldByName("TEXTSTRE1").SetValue("Address 1", true);
                    APVENDOR1header.Fields.FieldByName("TEXTSTRE2").SetValue("Address 2", true);
                    APVENDOR1header.Fields.FieldByName("TEXTSTRE3").SetValue("Address 3", true);
                    APVENDOR1header.Fields.FieldByName("TEXTSTRE4").SetValue("Address 4", true);
                    APVENDOR1header.Fields.FieldByName("NAMECITY").SetValue("City", true);
                    APVENDOR1header.Fields.FieldByName("CODEPSTL").SetValue("Postcode", true);
                    APVENDOR1header.Fields.FieldByName("CODESTTE").SetValue("County", true);
                    APVENDOR1header.Fields.FieldByName("CODECTRY").SetValue("UK", true);
                    APVENDOR1header.Fields.FieldByName("TEXTPHON1").SetValue("111222333444", true);
                    APVENDOR1header.Fields.FieldByName("TEXTPHON2").SetValue("555666777888", true);
                    APVENDOR1header.Fields.FieldByName("EMAIL2").SetValue("[email protected]", true);
                    APVENDOR1header.Fields.FieldByName("WEBSITE").SetValue("www.example.com", true);
                    APVENDOR1header.Fields.FieldByName("NAMECTAC").SetValue("Contact Name", true);
                    APVENDOR1header.Fields.FieldByName("CTACPHONE").SetValue("888777666555", true);
                    APVENDOR1header.Fields.FieldByName("CTACFAX").SetValue("444333222111", true);
                    APVENDOR1header.Fields.FieldByName("EMAIL1").SetValue("[email protected]", true);
                    APVENDOR1header.Insert();
    
                    // Dispose and cleanup
                    if (APVENDOR1detail2 != null) APVENDOR1detail2.Dispose();
                    if (APVENDOR1detail1 != null) APVENDOR1detail1.Dispose();
                    if (APVENDOR1header != null) APVENDOR1header.Dispose();
                    if (mDBLinkCmpRW != null) mDBLinkCmpRW.Dispose();
                    if (accpacSession != null) accpacSession.Dispose();
                }
                catch(Exception ex)
                {
                    label2.Text = $"Status: {ex.Message}";
                    ShowSageErrors();
                }
            }
    
            private void ShowSageErrors()
            {
                for (int i = 0; i < accpacSession.Errors.Count; i++)
                {
                    label3.Text = $"Session errors: {accpacSession.Errors[i].Message}";
                }
    
                accpacSession.Errors.Clear();
            }
        }
    }

    There are a couple of labels for status responses in the exception handler and to show the errors from the session, but this works. When recording a macro, record all fields. There is a lot of code that is unnecessary when converting, but you get a feel for that as you do it more often. In some the boolean value in the SetValue function is true and in some false. If the macros shows PutWithoutVerification then the bool is false. If it doesn't then it is true. You need to process the views as you go along where the macro says to do it which is usually when you set values in a field that has a finder lookup, such as IDGRP. The RecordClear functions aren't usually necessary to keep in but on occasion I find that they are needed. This was written against a Sage 2020 installation but the code will be much the same for other versions. I've never seen a need to add code to deal with the stats views. You need to clean up after yourself so disposing the views is good practice. You can use using blocks to auto dispose if you want but I prefer to do it this way as I find the code clearer.