back to top

Reading Sales Process details in the SalesLogix LAN client

The details about a Sales Process, like Stages and steps are contained in the Sales Process plugin data row in the Data column.  The data column is a binary field that stores an XML definition of the sales process.  Here is a sample of how you can read the data and do something with it.  In my case I am outputting it to a temporary table that can be used for some purpose.

Lets take a look at the main code, invoked from a button click event:

Sub Button1Click(Sender)
dim strSQL
dim objRS_SP

    PrepTempTable

    strSQL = “select pluginid from vFXSalesProcessPlugins”

‘create view sysdba.vFXSalesProcessPlugins
‘as
‘select pluginid from plugin where (type = 1 and basedon is not null)
‘union all
‘select pluginid from plugin where type = 1 and basedon is null and pluginid not in
‘(select basedon from plugin where type = 1 and basedon is not null)

    Set objRS_SP = CreateObject(“ADODB.Recordset”)
    objRS_SP.CursorType = 3 ‘adOpenStatic
    objRS_SP.CursorLocation = 3 ‘adUseClinet
    objRS_SP.LockType = 3 ‘adLockOptiomistic
    objRS_SP.Open strSQL, application.GetNewConnection
    with objRS_SP
        while not(.bof or .eof)
            ReadPlugin .Fields(“PLUGINID”).Value
            .movenext
        wend
    end with
    objRS_SP.Close
    set objRS_SP = nothing

    Msgbox “Table tmp_FXProcess populated”
End Sub

First off I am calling a method PrepTempTable.  This ensures my SQL temp table is in the database and if not it creates it.  If it is there it clears it out.

Sub PrepTempTable
        Application.GetNewConnection.Execute “exec sysdba.vFXPrepTempTable”

‘create procedure sysdba.vFXPrepTempTable
‘as
‘IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[sysdba].[tmp_FXProcess]’) AND type in (N’U’))
‘truncate TABLE [sysdba].[tmp_FXProcess]
‘else
‘create table sysdba.tmp_FXProcess (SPID varchar(12), SPName varchar(96), SPStage varchar(96))
‘GO
End Sub

Next we are getting all the Sales process plugins (These are plugins with a Type=1). With a recordset of the plugins, we need to loop through them and examine them.  In my case I wanted to get the released plugin records for all released sales process as well as unreleased processes.  Writing a SQL query that would pass though the provider was a little to complex so I handled it with a SQL view called “vFXSalesProcessPlugins”.

Inside the record set looping operation I am calling the ReadPlugin sub.  Lets look at this:

Sub ReadPlugin(byVal ID)
Dim strSQL, objRS_P
Dim objSTM, objXMLDoc, objCon
Dim strXML, strProcess, strID
Dim objSalesProcessNodes, objSalesProcessNode
Dim objStagesNodes, objStagesNode, objStageNode, objStageNodes, i

    set objCon = application.GetNewConnection
    strSQL  = “SELECT PLUGINID,NAME,DATA FROM PLUGIN WHERE PLUGINID='”& ID & “‘”
    Set objRS_P = CreateObject(“ADODB.Recordset”)
    objRS_P.CursorType = 3 ‘adOpenStatic
    objRS_P.CursorLocation = 3 ‘adUseClinet
    objRS_P.LockType = 3 ‘adLockOptiomistic
    objRS_P.Open strSQL, objCon  ‘Provider
    ‘ The Data Field is  a blob so we need to stream it in
    Set objSTM = CreateObject(“ADODB.STREAM”)
    objSTM.Type = adTypeBinary
    objSTM.Open
    objSTM.Write objRS_P.Fields(“DATA”).Value
    strID = objRS_P.Fields(“PLUGINID”).Value
    strProcess = objRS_P.Fields(“NAME”).Value
    objRS_P.Close
    set objRS_P = nothing
    ‘ Create XML Object and Load the Sales Process XML in to XML Object
    ‘ ———————————————————————
    objSTM.Position = 0
    objSTM.Type = adTypeText
    objSTM.Charset =”utf-8″
    Set objXMLDoc = CreateObject(“Msxml2.DOMDocument”)
    objXMLDoc.async = false
    strXML = objSTM.ReadText(objSTM.Size)
    If objXMLDoc.loadXML(strXML)= False Then
       msgbox “Invaild Sales Process XML”
       Exit Sub
    End If

    Set objSalesProcessNodes = objXMLDoc.documentElement.selectNodes(“//SalesProcess”)
    Set objSalesProcessNode = objSalesProcessNodes.item(0)
    Set objStagesNodes = objSalesProcessNode.selectNodes(“Stages”)
    Set objStagesNode = objStagesNodes.item(0)
    Set objStageNodes = objStagesNode.selectNodes(“Stage”)
    For i = 0 To objStageNodes.length – 1
        Set objStageNode = objStageNodes(i)
        WriteRecord strID, strProcess, objStageNode.selectSingleNode(“Name”).Text, objCon
    Next ‘ Stage Loop
End Sub

This sub accepts a single parameter, the Plugin ID of the sales process record to read. 

  1. First we open the specific plugin row. 
  2. Next we use an ADODB.Stream object to stream out the Data value of the plugin into an object.
  3. Then we create an XML document and load in the streamed plugin data into this.  At this point we have a workable XML document we can navigate through and read.
  4. With the XML file we loop through all of the Stage nodes.
  5. Inside the loop we finally call  a WriteRecord sub and pass into it values to use.

The WriteRecord sub inserts data into our temp table:

Sub WriteRecord(byval id, byval name, byval stage, objCon)
dim objRS_SP, strsql
    Set objRS_SP = CreateObject(“ADODB.Recordset”)
    objRS_SP.CursorType = 3 ‘adOpenStatic
    objRS_SP.CursorLocation = 3 ‘adUseClinet
    objRS_SP.LockType = 3 ‘adLockOptiomistic
    strSQL  = “SELECT * FROM tmp_FXProcess WHERE 1=2”
    objRS_SP.Open strSQL, objCon
    objRS_SP.AddNew
    objRS_SP.Fields(“SPID”).Value = id
    objRS_SP.Fields(“SPNAME”).Value = name
    objRS_SP.Fields(“SPSTAGE”).Value = stage
    objRS_SP.Update
    objRS_SP.Close
    set objRS_SP = nothing
End Sub

That is it.  lets take a look at it all together:

option explicit

Sub Button1Click(Sender)
dim strSQL
dim objRS_SP

    PrepTempTable

    strSQL = “select pluginid from vFXSalesProcessPlugins”

‘create view sysdba.vFXSalesProcessPlugins
‘as
‘select pluginid from plugin where (type = 1 and basedon is not null)
‘union all
‘select pluginid from plugin where type = 1 and basedon is null and pluginid not in
‘(select basedon from plugin where type = 1 and basedon is not null)

    Set objRS_SP = CreateObject(“ADODB.Recordset”)
    objRS_SP.CursorType = 3 ‘adOpenStatic
    objRS_SP.CursorLocation = 3 ‘adUseClinet
    objRS_SP.LockType = 3 ‘adLockOptiomistic
    objRS_SP.Open strSQL, application.GetNewConnection
    with objRS_SP
        while not(.bof or .eof)
            ReadPlugin .Fields(“PLUGINID”).Value
            .movenext
        wend
    end with
    objRS_SP.Close
    set objRS_SP = nothing

    Msgbox “Table tmp_FXProcess populated”
End Sub

Sub ReadPlugin(byVal ID)
Dim strSQL, objRS_P
Dim objSTM, objXMLDoc, objCon
Dim strXML, strProcess, strID
Dim objSalesProcessNodes, objSalesProcessNode
Dim objStagesNodes, objStagesNode, objStageNode, objStageNodes, i

    set objCon = application.GetNewConnection
    strSQL  = “SELECT PLUGINID,NAME,DATA FROM PLUGIN WHERE PLUGINID='”& ID & “‘”
    Set objRS_P = CreateObject(“ADODB.Recordset”)
    objRS_P.CursorType = 3 ‘adOpenStatic
    objRS_P.CursorLocation = 3 ‘adUseClinet
    objRS_P.LockType = 3 ‘adLockOptiomistic
    objRS_P.Open strSQL, objCon  ‘Provider
    ‘ The Data Field is  a blob so we need to stream it in
    Set objSTM = CreateObject(“ADODB.STREAM”)
    objSTM.Type = adTypeBinary
    objSTM.Open
    objSTM.Write objRS_P.Fields(“DATA”).Value
    strID = objRS_P.Fields(“PLUGINID”).Value
    strProcess = objRS_P.Fields(“NAME”).Value
    objRS_P.Close
    set objRS_P = nothing
    ‘ Create XML Object and Load the Sales Process XML in to XML Object
    ‘ ———————————————————————
    objSTM.Position = 0
    objSTM.Type = adTypeText
    objSTM.Charset =”utf-8″
    Set objXMLDoc = CreateObject(“Msxml2.DOMDocument”)
    objXMLDoc.async = false
    strXML = objSTM.ReadText(objSTM.Size)
    If objXMLDoc.loadXML(strXML)= False Then
       msgbox “Invaild Sales Process XML”
       Exit Sub
    End If

    Set objSalesProcessNodes = objXMLDoc.documentElement.selectNodes(“//SalesProcess”)
    Set objSalesProcessNode = objSalesProcessNodes.item(0)
    Set objStagesNodes = objSalesProcessNode.selectNodes(“Stages”)
    Set objStagesNode = objStagesNodes.item(0)
    Set objStageNodes = objStagesNode.selectNodes(“Stage”)
    For i = 0 To objStageNodes.length – 1
        Set objStageNode = objStageNodes(i)
        WriteRecord strID, strProcess, objStageNode.selectSingleNode(“Name”).Text, objCon
    Next ‘ Stage Loop
End Sub

Sub WriteRecord(byval id, byval name, byval stage, objCon)
dim objRS_SP, strsql
    Set objRS_SP = CreateObject(“ADODB.Recordset”)
    objRS_SP.CursorType = 3 ‘adOpenStatic
    objRS_SP.CursorLocation = 3 ‘adUseClinet
    objRS_SP.LockType = 3 ‘adLockOptiomistic
    strSQL  = “SELECT * FROM tmp_FXProcess WHERE 1=2”
    objRS_SP.Open strSQL, objCon
    objRS_SP.AddNew
    objRS_SP.Fields(“SPID”).Value = id
    objRS_SP.Fields(“SPNAME”).Value = name
    objRS_SP.Fields(“SPSTAGE”).Value = stage
    objRS_SP.Update
    objRS_SP.Close
    set objRS_SP = nothing
End Sub

Sub PrepTempTable
        Application.GetNewConnection.Execute “exec sysdba.vFXPrepTempTable”

‘create procedure sysdba.vFXPrepTempTable
‘as
‘IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[sysdba].[tmp_FXProcess]’) AND type in (N’U’))
‘truncate TABLE [sysdba].[tmp_FXProcess]
‘else
‘create table sysdba.tmp_FXProcess (SPID varchar(12), SPName varchar(96), SPStage varchar(96))
‘GO
End Sub

Contact Customer FX for your CRM project
We let our expertise speak for itself - let us know how our all-star team can help on your CRM project
About the Author
Kris Halsrud
Kris Halsrud
Kris Halsrud is a Senior Analyst / Developer for Customer FX Corporation.

1 COMMENT

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Infor CRM Sync for Exchange: Action Required by August 31, 2026

Using Infor CRM Sync for Exchange with Microsoft 365? Your Exchange administrator must update tenant settings by August 31, 2026 to prevent sync disruption.

[Webinar] What’s Coming Next for Infor CRM SLX and Why v10 Matters

See what’s coming next for Infor CRM SLX, including new marketing workflows, automation improvements, and reasons to consider upgrading to v10.

Disable Caching in Infor CRM SLX Web Client

In the rare case caching is causing issues in the Infor CRM SLX web client, it is possible to disable specific types of caching by making edits using Application Architect, and then deploying.

Exploring AI Options for Infor CRM v10

I've started taking a closer look at the AI capabilities built into Infor CRM v10. Over the next several posts, I'll share what I learn. From the built-in features and supported AI providers to implementation considerations, costs, and practical use cases.

Infor CRM SLX 10.0: Delegate Ownership Changes for “Everyone” Records

Learn how the new EveryoneOwnerAssignment secured action in Infor CRM SLX 10.0 allows designated users to change ownership of Everyone-owned records without requiring Administrator access.

Related Articles

Infor CRM Sync for Exchange: Action Required by August 31, 2026

Using Infor CRM Sync for Exchange with Microsoft 365? Your Exchange administrator must update tenant settings by August 31, 2026 to prevent sync disruption.

[Webinar] What’s Coming Next for Infor CRM SLX and Why v10 Matters

See what’s coming next for Infor CRM SLX, including new marketing workflows, automation improvements, and reasons to consider upgrading to v10.

Disable Caching in Infor CRM SLX Web Client

In the rare case caching is causing issues in the Infor CRM SLX web client, it is possible to disable specific types of caching by making edits using Application Architect, and then deploying.

Exploring AI Options for Infor CRM v10

I've started taking a closer look at the AI capabilities built into Infor CRM v10. Over the next several posts, I'll share what I learn. From the built-in features and supported AI providers to implementation considerations, costs, and practical use cases.

Related Videos