cancel
Showing results for 
Search instead for 
Did you mean: 

Can't remove a user defined field with DI API.

Former Member
0 Kudos

Hi,

I'm using the code below to remove a user field. However, the first time I run it, I get the message that:

"Ref count for this object is higher then 0"

The second time I run it, I get the message that:

"No matching records found (ODBC -2028)"

As you can see, I am killing the UserFieldsMD object. In fact, when the function is entered, the object is nothing but later instantiated with oCompany.

The result in both cases is that the field doesn't get removed. What am I missing? Any ideas?

Thanks,

Mike

Public Function RemoveUserField(ByVal FieldName As String, ByVal TableName As String, ByRef ErrMsg As String) As Boolean

Dim Result As Boolean = False

Dim Err As Integer

Dim oUserFieldsMD As SAPbobsCOM.UserFieldsMD

Try

If Not FieldExists(TableName, FieldName) Then

Result = True

Else

oUserFieldsMD = oCompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.oUserFields)

With oUserFieldsMD

.TableName = TableName

.Name = FieldName

Err = .Remove

If Err Then

oUtilCompany.GetLastError(Err, ErrMsg)

If ErrMsg = "No matching records found (ODBC -2028)" Then

Result = True

Else

ErrMsg = "Was not able to remove field " & FieldName & " from table " & TableName & " programmatically." & vbCrLf & _

"Please remove it manually using the Tools menu."

End If

Else

Result = True

End If

End With

End If

Catch ex As Exception

Throw ex

Finally

KillObject(oUserFieldsMD)

End Try

Return Result

End Function

Public Sub KillObject(ByRef Obj As Object)

If Not Obj Is Nothing Then ObjectRelease(Obj)

End Sub

Private Sub ObjectRelease(ByRef Obj As Object)

'This routine releases objects that were acquired with oCompany.GetBusinessObject().

System.Runtime.InteropServices.Marshal.ReleaseComObject(Obj)

Obj = Nothing

GC.Collect()

End Sub

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

I am wondering why you need to remove a UDF through DI API. To my knowledge, any operations with adding or deleting UDF should be exclusively done when no uses connect to B1. Do you need to delete UDF very often from time to time?

Thanks,

Gordon

Former Member
0 Kudos

Hi Gordon,

We have many customers and many versions. We create fields using the DI API all the time but only when the add-on is being loaded; however, at a later date we may want to deprecate a few of them. We donu2019t want to depend on the user to delete a field manually because it is error prone and not seamless. The restriction you mention apparently does not apply when adding fields. At any rate, the SDK help file says it is possible to remove fields and doesnu2019t mention any restrictions. Also, when I start the add-on, I am using my computer and I am the only user.

Thanks,

Mike

Former Member
0 Kudos

Hi,

It looks like nobody has an answer for this issue. However, since the help file very clearly says it's possible and because the SDK doesn't do it, I think it is an SAP bug. (I'm using patch level 47.) With current version of the SAP website, I can't figure out how to report a bug. Does anyone know how to report a bug?

Thanks,

Mike

former_member201110
Active Contributor
0 Kudos

Hi Mike,

The issue with your code is that you are not calling the GetByKey method of the field object. Until you do this the FieldID property is 0 so when the Remove method is called it will not try and remove the correct UDF (if you run SQL profiler then you'll see that SBO is looking for the UDF based on the table and fieldID values).

Something like the following works for me:


private void DeleteUDF(string sTableID, string sFieldName)
{
    SAPbobsCOM.UserFieldsMD sboField = (SAPbobsCOM.UserFieldsMD)_sboCompany.GetBusinessObject(BoObjectTypes.oUserFields);

    try
    {
        int iFieldID = GetFieldID(sTableID, sFieldName);
        if(sboField.GetByKey(sTableID, iFieldID))
        {
            if (sboField.Remove() != 0)_sboApp.SetStatusBarMessage("Error removing UDF: " + _sboCompany.GetLastErrorDescription(), SAPbouiCOM.BoMessageTime.bmt_Short, true);
        }
    }
    finally
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(sboField);
        sboField = null;
        GC.Collect();
    }
}

private int GetFieldID(string sTableID, string sAliasID)
{
    int iRetVal = 0;
    SAPbobsCOM.Recordset sboRec = (SAPbobsCOM.Recordset)_sboCompany.GetBusinessObject(BoObjectTypes.BoRecordset);
    try
    {
        sboRec.DoQuery("select FieldID from CUFD where TableID = '" + sTableID + "' and AliasID = '" + sAliasID + "'");
        if (!sboRec.EoF) iRetVal = Convert.ToInt32(sboRec.Fields.Item("FieldID").Value.ToString());
    }
    finally
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(sboRec);
        sboRec = null;
        GC.Collect();
    }
    return iRetVal;
}

Note that the parameter sAliasID is the field name without the U_ prefix.

Kind Regards,

Owen

Former Member
0 Kudos

Thanks Owen!!!

The GetByKey did the trick. I even modified the FieldExists function by adding a ByRef parameter that returns the FieldID if the field exists. I use that with the TableName to get the proper reference to the field object and then remove it.

Thanks again!

Mike

Answers (0)