Hi all.
This thread is posted to share and document (like a How to)
Any question, correction,... is wellcome.
Object.
These example illustrates how to add new fields into a system form and obtain valid values from a CFL.
These tutorial is exampled by the+ form 150+
1.
The first step is to add for the table OITM the field to stores the customized information for a Item.a.
Add the new field(s) for a desired form (in the example the 150)Public Sub AddUserFields() Dim oUserFieldsMD As SAPbobsCOM.UserFieldsMD If Not UserFieldsExist("OITM", "XX_MODEL") Then oUserFieldsMD = _ oCompany.GetBusinessObject(BoObjectTypes.oUserFields) oUserFieldsMD.TableName = "OITM" oUserFieldsMD.Name = "XX_MODEL" oUserFieldsMD.Description = "Model " oUserFieldsMD.Type = BoFieldTypes.db_Alpha oUserFieldsMD.SubType = BoFldSubTypes.st_None oUserFieldsMD.EditSize = 20 oUserFieldsMD.Mandatory = BoYesNoEnum.tNO oUserFields.Add(oUserFieldsMD) System.Runtime.InteropServices.Marshal.ReleaseComObject( oUserFieldsMD) End If End Sub Public Function UserFieldsExist(ByVal tableName As String, ByVal fieldName As String) As Boolean Dim oTmpRecordset As SAPbobsCOM.Recordset oTmpRecordset = _ CType(oCompany.GetBusinessObject(BoObjectTypes.BoRecordset), _ SAPbobsCOM.Recordset) oTmpRecordset.DoQuery("Select Count(*) From CUFD Where TableId ='"& tableName & "' And AliasID = '" & fieldName & "'") System.Windows.Forms.Application.DoEvents() If CInt(oTmpRecordset.Fields.Item(0).Value) > 0 Then UserFieldsExist = True Else UserFieldsExist = False End If System.Runtime.InteropServices.Marshal.ReleaseComObject(oTmpRecordset) End Function
b.
After data add you must to create a user table and UDO objectPublic Sub AddUserTables() If Not UserTablesExist(userTables(XX_MARCA, 0)) Then If AddUserTable(userTables(i, 0), _ BoUTBTableType.bott_MasterData, userTables(XX_MARCA, MARCA)) = 0 Then AddUDO( XX_MARCA, Marca) End If End If End Sub Public Function UserTablesExist(ByVal tableName As String) As Boolean Dim oTmpRecordset As SAPbobsCOM.Recordset oTmpRecordset = _ CType(oCompany.GetBusinessObject(BoObjectTypes.BoRecordset), _ SAPbobsCOM.Recordset) oTmpRecordset.DoQuery("Select Count(*) From OUTB Where TableName='"& tableName & "'") System.Windows.Forms.Application.DoEvents() If CInt(oTmpRecordset.Fields.Item(0).Value) > 0 Then UserTablesExist = True Else UserTablesExist = False End If System.Runtime.InteropServices.Marshal.ReleaseComObject( oTmpRecordset) oTmpRecordset = Nothing GC.Collect() End Function Public Function AddUserTable(ByVal tableName As String, _ ByVal type As BoUTBTableType, _ ByVal tableDescription As String) Dim oUserTablesMD As SAPbobsCOM.UserTablesMD Dim lretcode As Integer Dim errMsg As String = "" If String.IsNullOrEmpty(tableDescription) Then tableDescription = tableName End If oUserTablesMD = oCompany.GetBusinessObject(BoObjectTypes.oUserTables) oUserTablesMD.TableName = tableName oUserTablesMD.TableDescription = tableDescription oUserTablesMD.TableType = type lretcode = oUserTablesMD.Add If lretcode <> 0 Then oCompany.GetLastError(lretcode, errMsg) MessageBox.Show(errMsg) End If System.Runtime.InteropServices.Marshal.ReleaseComObject(oUserTablesMD) oUserTablesMD = Nothing GC.Collect() Return lretcode End Function Public Function AddUDO(ByVal tableName As String, _ ByVal nameAlias As String) As Integer Dim oUserObjectMD As SAPbobsCOM.UserObjectsMD Dim lretcode As Integer Dim errMsg As String = "" oUserObjectMD = _ oCompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.oUserObjectsMD) oUserObjectMD.CanCancel = BoYesNoEnum.tYES oUserObjectMD.CanClose = BoYesNoEnum.tYES oUserObjectMD.CanCreateDefaultForm = BoYesNoEnum.tYES oUserObjectMD.CanDelete = BoYesNoEnum.tNO oUserObjectMD.CanFind = BoYesNoEnum.tYES oUserObjectMD.TableName = tableName oUserObjectMD.Code = "O" & tableName oUserObjectMD.ManageSeries = BoYesNoEnum.tNO oUserObjectMD.Name = "O" & tableName oUserObjectMD.ObjectType = BoUDOObjType.boud_MasterData oUserObjectMD.FormColumns.FormColumnAlias = "Code" oUserObjectMD.FormColumns.FormColumnDescription = "Código" oUserObjectMD.FormColumns.Add() oUserObjectMD.FormColumns.FormColumnAlias = "Name" oUserObjectMD.FormColumns.FormColumnDescription = nameAlias oUserObjectMD.FormColumns.Add() oUserObjectMD.CanFind = BoYesNoEnum.tYES oUserObjectMD.FindColumns.ColumnAlias = "Code" oUserObjectMD.FindColumns.Add() oUserObjectMD.FindColumns.ColumnAlias = "Name" oUserObjectMD.FindColumns.Add() lretcode = oUserObjectMD.Add() If lretcode <> 0 Then oCompany.GetLastError(lretcode, errMsg) MessageBox.Show(errMsg) End If oUserObjectMD = Nothing GC.Collect() Return lretcode End Function
For standard we name the UDO object as the same name of the table name. But associated with the prefix O. There is not required but makes very ease to remember ant maintain the system.
For the release of SAP (6.80.319) SP:01 PL:22 there have a bug. You must to enter in the menu Tools
>UDO
> Wizard and force to update any object. If you omit this recommendation the UDO arent available for use.
Don't forget
to set corrected values for a oUserObjectMD . If the behaviour of the CFL isnt correct inspect it.2.
Add the user table, user object and user form for a valid values..
In the sample the
3.
Add the field into the form 150These step is implemented in a init method. We recommend to declare a module for each form to manipulate.
In the module you processes all of the events desired for these event (there not is the target for this tutorial).
Of course you implement a FORM_INIT method.
Public Sub FRM150_INIT() Dim oItem As SAPbouiCOM.Item Dim oStaticText As SAPbouiCOM.StaticText Dim oEditText As SAPbouiCOM.EditText Dim oFolder As SAPbouiCOM.Folder ' put your init code here. 'In the example we add the field into a separate folder (recommended) ' oTmpForm is a global variable in the module oItem = oTmpForm.Items.Add("xx_flropc", SAPbouiCOM.BoFormItemTypes.it_FOLDER) oItem.AffectsFormMode = False oItemRef = oTmpForm.Items.Item("9") oItem.Width = oItemRef.Width + 80 oFolder = oItem.Specific oFolder.Caption = "Options" oFolder.GroupWith("9") 'now add the new field and bind it to the OITM table oItem = oTmpForm.Items.Add("U_XX_MARCA", _ SAPbouiCOM.BoFormItemTypes.it_EDIT) oItem.AffectsFormMode = True oItem.Top = 155 oItem.Left = 10 oItem.Width = 100 oItem.FromPane = 8 oItem.ToPane = 8 oEditText = oItem.Specific oItem.DisplayDesc = True oEditText.DataBind.SetBound(True, "OITM", "U_XX_MARCA") End Sub
After these step the form is ready to show and update the data into the new added field.
4.
Add the CFL and link it to the new fieldThe CFL is linked in the after data load event.
Public Sub FRM150_AfterDataLoad(ByVal boi As _ BusinessObjectInfo , ByVal bubbleevent As Boolean) Dim oCFLCreationParams As ChooseFromListCreationParams Dim oCFLs As ChooseFromListCollection Dim oCFL As ChooseFromList Dim oEditTextMarca As SAPbouiCOM.EditText = _ oTmpForm.Items.Item("U_XX_MARCA").Specific oCFLs = oTmpForm.ChooseFromLists Try oCFLCreationParams = oAplicacion.SBOapp.CreateObject( _ BoCreatableObjectType.cot_ChooseFromListCreationParams) oCFLCreationParams.MultiSelection = False oCFLCreationParams.ObjectType = "OXX_MARC" oCFLCreationParams.UniqueID = "CFLMRC" oCFL = oCFLs.Add(oCFLCreationParams) oEditTextMarca.ChooseFromListUID = "CFLMRC" oEditTextMarca.ChooseFromListAlias = "Code" Catch ex As Exception End Try End sub
With these step the values for the new field are linked and restricted to the new user table .
5.
Capture the CFL event and update the selected valuePublic Sub FRM150_AFTER(ByVal FormUI As String, _ ByVal pval As IItemEvent, _ ByRef BubbleEvent As Boolean) Select Case pval.EventType Case BoEventTypes.et_CHOOSE_FROM_LIST Dim oCFLEvent As SAPbouiCOM.IChooseFromListEvent Dim oDataTable As SAPbouiCOM.DataTable = Nothing Dim value As String = Nothing Dim oEdit As SAPbouiCOM.EditText oCFLEvent = pval oDataTable = oCFLEvent.SelectedObjects Try value = oDataTable.GetValue(0, 0) Catch ex As Exception End Try If value Is Nothing Then Exit Select End If If Not oCFLEvent.Before_Action Then If pval.ItemUID = "U_XX_MARCA" Then oEdit = oTmpForm.Items.Item("U_XX_MARCA").Specific Try 'surround these line with a try .. catch block. oEdit.String = value Catch ex As Exception End Try ' place here for another CFLs End If oEditText = oTmpForm.Items.Item("7").Specific 'These step are for force to update mode. Try oEditText.Value = oEditText.Value Catch ex As Exception End Try BubbleEvent = False End If ' your code for another after data events End Sub
Regards
Hi Alfonso... One addition to your code
oDataTable = oCFLEvent.SelectedObjects
After this line you should test if oDataTable is null/Nothing... Otherwice you will get an error if you ope the choosefrom list but close it by clicking Cancel
Hi Alfonso,
I didn't have time yet to look at your sample, but I would like to thank you for sharing your sample with the community + I have linked it to the FAQ in the B1-Wiki: https://wiki.sdn.sap.com/wiki/label/B1/b1_faq
I would suggest that you consider posting it as a Blog...?
Thanks anyway,
Frank
Hi Alfonso, first of all thanks for your guide.
I'm trying to use it, but i have a problem when i have to get the value from CFL.
The CFL opens, but when i select my value and try to get back to my form (UDO), it happens that other 2 CFL opens and i get "Invalid form" error
I post here the code i've written to handle the et_CHOOSE_FROM_LIST event
Private Sub SBO_Application_ItemEvent(ByVal FormUID As String, ByRef pVal As SAPbouiCOM.ItemEvent, ByRef BubbleEvent As Boolean) Handles SBO_Application.ItemEvent Dim oForm As SAPbouiCOM.Form Dim oItem As SAPbouiCOM.Item Dim oEditText As SAPbouiCOM.EditText If (FormUID = "FRDA") Then Try oForm = SBO_Application.Forms.Item(FormUID) 'If (pVal.Before_Action = False) Then If pVal.EventType = SAPbouiCOM.BoEventTypes.et_CHOOSE_FROM_LIST Then Dim oCFLEvent As SAPbouiCOM.IChooseFromListEvent Dim oDataTable As SAPbouiCOM.DataTable = Nothing Dim value As String = Nothing Dim oEdit As SAPbouiCOM.EditText oCFLEvent = pVal oDataTable = oCFLEvent.SelectedObjects Try value = oDataTable.GetValue(0, 0) Catch ex As Exception End Try If Not oCFLEvent.Before_Action Then If pVal.ItemUID = "txtCode" Then oEdit = oForm.Items.Item("txtCode").Specific Try 'surround these line with a try .. catch block. oEdit.String = value Catch ex As Exception End Try End If oEditText = oForm.Items.Item("txtCode").Specific 'These step are for force to update mode. Try oEditText.Value = oEditText.Value Catch ex As Exception End Try BubbleEvent = False End If End If 'End If Catch ex As Exception If (ex.Message.StartsWith("Cast from") = False) Then 'oForm = SBO_Application.Forms.Item(FormUID) 'SBO_Application.MessageBox("Error on form" & oForm.UniqueID & " : " & ex.Message) 'MessageBox.Show(ex.Message) End If End Try End If End Sub
Hope you can help me. I draw my form with Screen Painter and i've bound on it the edittext using the CFL with a user table directly on the screen painter.
I hope i've been clear
Thanks in advance
Nick
Add a comment