如何在SAP B1的UDO矩阵中实现物料代码多选?
我太懂这种无奈了——SAP B1里UDO矩阵的原生UDV确实只支持单选,批量选物料的时候效率低到让人抓狂。之前帮朋友解决过类似的问题,核心思路是绕开原生UDV的限制,自己做一个带复选框的多选物料弹窗,然后把选中的物料批量塞回UDO矩阵里。下面是具体的实现方案和代码,你可以直接参考调整:
解决方案思路
原生UDV没有批量多选的接口,所以我们需要:
- 拦截UDV的触发事件,不让原生弹窗出来
- 自己创建一个带复选框的自定义表单,加载所有可选物料
- 用户勾选完物料后,把选中的条目批量添加到UDO矩阵中(还要避免重复添加)
具体代码实现
首先,在你的主表单ItemEvent里拦截UDV的点击事件:
Private Sub SBO_Application_ItemEvent(ByVal FormUID As String, ByRef pVal As SAPbouiCOM.ItemEvent, ByRef BubbleEvent As Boolean) Handles SBO_Application.ItemEvent ' 替换成你实际的UDO表单UID、矩阵ID和物料代码列ID Const UDO_FORM_UID As String = "UDO_MY_FORM" Const MATRIX_ID As String = "mtxItems" Const ITEM_CODE_COL_ID As String = "colItemCode" ' 判断是否是点击了物料代码列的UDV If pVal.FormUID = UDO_FORM_UID AndAlso pVal.ItemUID = MATRIX_ID AndAlso pVal.ColUID = ITEM_CODE_COL_ID Then If pVal.EventType = SAPbouiCOM.BoEventTypes.et_CLICK AndAlso pVal.BeforeAction Then ' 取消原生UDV弹窗 BubbleEvent = False ' 打开自定义多选物料表单 OpenMultiItemSelectForm() End If End If End Sub
然后实现打开多选表单的方法,这里会创建一个带矩阵和复选框的弹窗,加载所有有效物料:
Private Sub OpenMultiItemSelectForm() Dim oForm As SAPbouiCOM.Form Dim oMatrix As SAPbouiCOM.Matrix Dim oItem As SAPbouiCOM.Item Dim oRS As SAPbobsCOM.Recordset Dim rowIndex As Integer = 1 ' 先检查表单是否已打开,避免重复创建 Try oForm = SBO_Application.Forms.Item("FRM_MULTI_ITEM_SELECT") oForm.Visible = True Exit Sub Catch ' 表单不存在,创建新表单 End Try ' 创建表单参数 Dim formParams As SAPbouiCOM.FormCreationParams = SBO_Application.CreateObject(SAPbouiCOM.BoCreatableObjectType.cot_FormCreationParams) formParams.UniqueID = "FRM_MULTI_ITEM_SELECT" formParams.FormType = "MTX_ITEM_SELECT" formParams.BorderStyle = SAPbouiCOM.BoFormBorderStyle.fbs_Sizable oForm = SBO_Application.Forms.AddEx(formParams) ' 设置表单属性 oForm.Title = "批量选择物料" oForm.SetBounds(150, 150, 650, 450) ' 添加物料矩阵 oItem = oForm.Items.Add("mtxItems", SAPbouiCOM.BoFormItemTypes.it_MATRIX) oItem.SetBounds(15, 15, 620, 360) oMatrix = oItem.Specific ' 配置矩阵列:复选框、物料代码、物料名称 With oMatrix.Columns ' 复选框列 .Add("colSelect", SAPbouiCOM.BoFormItemTypes.it_CHECK_BOX).Width = 70 .Item("colSelect").TitleObject.Caption = "选择" ' 物料代码列 .Add("colItemCode", SAPbouiCOM.BoFormItemTypes.it_EDIT).Width = 180 .Item("colItemCode").TitleObject.Caption = "物料代码" .Item("colItemCode").Editable = False ' 物料名称列 .Add("colItemName", SAPbouiCOM.BoFormItemTypes.it_EDIT).Width = 360 .Item("colItemName").TitleObject.Caption = "物料名称" .Item("colItemName").Editable = False End With ' 加载所有有效物料到矩阵 oRS = SBO_Application.Company.GetBusinessObject(SAPbobsCOM.BoObjectTypes.BoRecordset) ' 可以修改查询条件,比如筛选特定物料组、库存不为0的物料等 oRS.DoQuery("SELECT ItemCode, ItemName FROM OITM WHERE ValidFor = 'Y' ORDER BY ItemCode") If oRS.RecordCount > 0 Then oMatrix.RowCount = oRS.RecordCount Do While Not oRS.EoF oMatrix.Columns.Item("colItemCode").Cells.Item(rowIndex).Specific.Value = oRS.Fields("ItemCode").Value oMatrix.Columns.Item("colItemName").Cells.Item(rowIndex).Specific.Value = oRS.Fields("ItemName").Value rowIndex += 1 oRS.MoveNext() Loop End If ' 添加确定和取消按钮 oItem = oForm.Items.Add("btnConfirm", SAPbouiCOM.BoFormItemTypes.it_BUTTON) oItem.SetBounds(500, 390, 80, 25) oItem.Specific.Caption = "确定" oItem = oForm.Items.Add("btnCancel", SAPbouiCOM.BoFormItemTypes.it_BUTTON) oItem.SetBounds(410, 390, 80, 25) oItem.Specific.Caption = "取消" ' 注册多选表单的事件处理 AddHandler SBO_Application.ItemEvent, AddressOf MultiSelectForm_ItemHandler End Sub
最后是多选表单的按钮事件处理,负责把选中的物料添加到UDO矩阵:
Private Sub MultiSelectForm_ItemHandler(ByVal FormUID As String, ByRef pVal As SAPbouiCOM.ItemEvent, ByRef BubbleEvent As Boolean) If FormUID <> "FRM_MULTI_ITEM_SELECT" Then Exit Sub If pVal.EventType = SAPbouiCOM.BoEventTypes.et_ITEM_PRESSED AndAlso Not pVal.BeforeAction Then Select Case pVal.ItemUID Case "btnConfirm" Dim oMultiForm As SAPbouiCOM.Form = SBO_Application.Forms.Item(FormUID) Dim oMultiMatrix As SAPbouiCOM.Matrix = oMultiForm.Items.Item("mtxItems").Specific Dim oUDOForm As SAPbouiCOM.Form = SBO_Application.Forms.Item("UDO_MY_FORM") ' 替换成你的UDO表单UID Dim oUDOMatrix As SAPbouiCOM.Matrix = oUDOForm.Items.Item("mtxItems").Specific ' 替换成你的UDO矩阵ID ' 遍历多选矩阵,处理选中的物料 For row As Integer = 1 To oMultiMatrix.RowCount Dim chkBox As SAPbouiCOM.CheckBox = oMultiMatrix.Columns.Item("colSelect").Cells.Item(row).Specific If chkBox.Checked Then Dim itemCode As String = oMultiMatrix.Columns.Item("colItemCode").Cells.Item(row).Specific.Value Dim itemName As String = oMultiMatrix.Columns.Item("colItemName").Cells.Item(row).Specific.Value ' 检查UDO矩阵中是否已存在该物料,避免重复 Dim isDuplicate As Boolean = False For udoRow As Integer = 1 To oUDOMatrix.RowCount If oUDOMatrix.Columns.Item("colItemCode").Cells.Item(udoRow).Specific.Value = itemCode Then isDuplicate = True Exit For End If Next If Not isDuplicate Then ' 添加新行到UDO矩阵 oUDOMatrix.AddRow() Dim newRow As Integer = oUDOMatrix.RowCount oUDOMatrix.Columns.Item("colItemCode").Cells.Item(newRow).Specific.Value = itemCode ' 如果需要自动填充物料名称,这里直接赋值 oUDOMatrix.Columns.Item("colItemName").Cells.Item(newRow).Specific.Value = itemName End If End If Next ' 关闭多选表单 oMultiForm.Close() ' 移除事件绑定,避免内存泄漏 RemoveHandler SBO_Application.ItemEvent, AddressOf MultiSelectForm_ItemHandler Case "btnCancel" SBO_Application.Forms.Item(FormUID).Close() RemoveHandler SBO_Application.ItemEvent, AddressOf MultiSelectForm_ItemHandler End Select End If End Sub
注意事项
- 一定要替换代码中所有占位符(比如
UDO_MY_FORM、mtxItems等)为你实际的表单、矩阵和列ID - 可以修改物料查询的SQL语句,比如添加
WHERE ItemGroupCode = X来筛选特定组的物料,或者加入库存条件 - 如果你的UDO矩阵有其他需要自动填充的字段(比如单位、价格),可以在添加行时通过查询OITM/OITB等表获取数据后填充
- 记得测试权限问题,确保用户有打开自定义表单和修改UDO矩阵的权限
内容的提问来源于stack exchange,提问作者Schadrack Rurangwa




