Build a VB.Net DataTable out of an SAPBouiCOM Matrix: This is a method that I wrote that’s fairly simple, but that I’m proud of for its simplicity. It takes in a reference to our AddOnApp, the pVal ItemEvent, the UID for the specific Matrix that you want to work with, and the UID for the “key field” that must be populated for a row to be a valid row. Then it spits back out a VB.net DataTable:

”’

”’ Builds a VB.NET DataTable based on an SAP form Matrix

”’

”’A reference to the AddOnApp

”’A reference to the ItemEvent pVal

”’The UID for the matrix (different for different types of forms)

”’The UID for the “Key” Field, the one that must be populated for it to be a valid row

”’ A VB.Net DataTable clone of the SAP matrix

”’ This method was primarily built so that we can query the data in the matrix without having to constantly go through it. Use the DT.Select statement

Public Shared Function buildMatrixTable(ByRef oAddOnApp As IAddOnApp, ByRef pVal As SAPbouiCOM.ItemEvent, ByVal sMatrixUID As String, ByVal sKeyFieldID As String) As DataTable

Dim oForm As SAPbouiCOM.Form = Nothing

Dim oMatrix As SAPbouiCOM.Matrix = Nothing

Try

Dim oDT As New DataTable

oForm = oAddOnApp.SBO_Application.Forms.GetForm(pVal.FormType, pVal.FormTypeCount)

oMatrix = oForm.Items.Item(sMatrixUID).Specific

‘Add all of the columns by unique ID to the DataTable

For iCol As Integer = 0 To oMatrix.Columns.Count – 1

‘Skip invisible columns

If oMatrix.Columns.Item(iCol).Visible = False Then Continue For

oDT.Columns.Add(oMatrix.Columns.Item(iCol).UniqueID)

Next

‘Now, add all of the data into the DataTable

For iRow As Integer = 1 To oMatrix.RowCount

Dim oRow As DataRow = oDT.NewRow

For iCol As Integer = 0 To oMatrix.Columns.Count – 1

If oMatrix.Columns.Item(iCol).Visible = False Then Continue For

oRow.Item(oMatrix.Columns.Item(iCol).UniqueID) = oMatrix.Columns.Item(iCol).Cells.Item(iRow).Specific.Value

Next

‘If the Key field has no value, then the row is empty, skip adding it.

If oRow(sKeyFieldID).ToString.Trim = “” Then Continue For

oDT.Rows.Add(oRow)

Next

Return oDT

Catch ex As Exception

AsapSharedClasses.ErrorLog.AddEntryWithTrace(ex)

Return Nothing

Finally

‘releaseCOMobject is our method that checks if an SAPBouiObject is Nothing or not, and if it’s not Nothing,

‘uses System.Runtime.InteropServices.Marshal.ReleaseComObject to release it from memory, and then sets it to nothing.

‘This prevents memory leaks in the program from unreleased COM objects.

NewSharedMethods.releaseCOMobject(oMatrix)

NewSharedMethods.releaseCOMobject(oForm)

End Try

End Function

Now, why would you want to do this? Well, we are constantly doing checks on the user’s Add/Update to verify certain information within the form to see if it’s correct (using our own validation methods). This method will help us simplify this. Instead of having to go through the UI API multiple times and looping through the rows and columns to find the data we’re looking for, instead we can do it just once, and then we can use the VB.NET DataTable to do some interesting things.

Specifically, we can use the DataTable.Select method to query for the specific rows and data that we want to find. Below is an example validateForm method that I wrote for a Bill of Materials form to validate that if there is a “labor” line and an “overhead” line, that the labor is not greater than the overhead:

Private Function validateForm(ByRef pVal As SAPbouiCOM.ItemEvent, ByRef BubbleEvent As Boolean) As Boolean

Try

‘Pull the matrix into a DataTable for querying

Me.m_dtMatrix = NewSharedMethods.buildMatrixTable(Me.AddOnApp, pVal, CONSTANTS.BOM_MATRIX, CONSTANTS.BOM_MATRIX_ITEM_CODE_COL)

‘Make sure that there’s not more than one WIPLABOR line item on the form

‘Note the brackets that are used here that are necessary in case the column name includes spaces or starts with a number. The brackets

‘denote to the Select statement that the contents within the brackets are in fact a column name, rather than a value/variable to compare.

Dim oWIPLABORrows() As DataRow = Me.m_dtMatrix.Select(“[” & CONSTANTS.BOM_MATRIX_ITEM_CODE_COL & “]” & “=’WIPLABOR’”)

If oWIPLABORrows IsNot Nothing AndAlso oWIPLABORrows.Length > 1 Then

Me.AddOnApp.showMessageBoxWithOverride(“Error, there is more than one WIPLABOR line. Only one is allowed, please correct.”, BubbleEvent)

If BubbleEvent Then

Email.sendWarningEmail(Me.m_ClassName & “.” & System.Reflection.MethodInfo.GetCurrentMethod.Name,

“BoM was overridden to allow more than one WIPLABOR row.”, False)

Else

Return False

End If

End If

‘Make sure that there’s not more than one WIP O/H line item on the form

Dim oWIPOHrows() As DataRow = Me.m_dtMatrix.Select(“[” & CONSTANTS.BOM_MATRIX_ITEM_CODE_COL & “]” & “=’WIP O/H’”)

If oWIPOHrows IsNot Nothing AndAlso oWIPOHrows.Length > 1 Then

Me.AddOnApp.showMessageBoxWithOverride(“Error, there is more than one WIP O/H line. Only one is allowed, please correct.”, BubbleEvent)

If BubbleEvent Then

Email.sendWarningEmail(Me.m_ClassName & “.” & System.Reflection.MethodInfo.GetCurrentMethod.Name,

“BoM was overridden to allow more than one WIP O/H row.”, False)

Else

Return False

End If

End If

‘Prevent the WIPLABOR from being greater than the WIP O/H

If oWIPLABORrows IsNot Nothing AndAlso oWIPOHrows IsNot Nothing Then

‘Get the strings from the total price fields – note that we are always only using the FIRST found row of these values.

‘As per Todd, if there exists more than one row and they overrode it, we will only use the value of the first row for this check.

Dim sLabor As String = oWIPLABORrows(0).Field(Of String)(CONSTANTS.BOM_MATRIX_TOTAL_PRICE_COL)

Dim sOH As String = oWIPOHrows(0).Field(Of String)(CONSTANTS.BOM_MATRIX_TOTAL_PRICE_COL)

‘Try to convert the strings to decimals

sLabor = sLabor.Replace(“$”, “”).Trim

sOH = sOH.Replace(“$”, “”).Trim

Dim dLabor As Decimal = 0.0

Dim dOH As Decimal = 0.0

‘Compare the decimals. If the Labor is greater than the O/H, report and abort

If Decimal.TryParse(sLabor, dLabor) AndAlso Decimal.TryParse(sOH, dOH) Then

If dLabor > dOH Then

Me.AddOnApp.showMessageBoxWithOverride(“Labor charge of ” & dLabor.ToString & ” is greater than the overhead charge of ” & dOH.ToString & “. ” & _

“This is not allowed. Please correct and try again.”, BubbleEvent)

If BubbleEvent Then

Email.sendWarningEmail(Me.m_ClassName & “.” & System.Reflection.MethodInfo.GetCurrentMethod.Name,

“BoM was overridden to allow WIPLABOR > WIP O/H.”, False)

Else

Return False

End If ‘BubbleEvent Then

End If ‘dLabor > dOH Then

End If ‘Decimal.TryParse(sLabor, dLabor) AndAlso Decimal.TryParse(sOH, dOH) Then

End If ‘oWIPLABORrows IsNot Nothing AndAlso oWIPOHrows IsNot Nothing Then

‘If we got here, then everything checks out, return true

Return True

Catch ex As Exception

AsapSharedClasses.ErrorLog.AddEntryWithTrace(ex)

Return False

End Try

End Function

The CONSTANTS you see in the code are our direct references to the UIDs of UI API columns and other UI API objects. By using the buildMatrixTable method right at the start, as you can see, this validation method doesn’t require any looping. That means less overall calls to SAP to check the UI (just one big call at the start), then the rest of the checks/etc. can be done entirely in memory.

I feel that this method will benefit us greatly in the future, not just in this instance, but in future instances when we need to “rip” data out of a matrix that hasn’t yet been committed to the SAP database, but that we would like to go through and process to follow business rules.

New NetWeaver Information at SAP.com

Very Helpfull

 

 

User Rating: Be the first one !