Forum Discussion
RobbSalzmann
3 years agoValued Contributor II
The sorting posted so far relies on standard lexical ordering which produces an order that can be a bit strange for a business user:
This code will help sort things in a human, alphanumeric order:
Public Class MainClass
  Public Function Main(si As SessionInfo, globals As BRGlobals, api As Object, args As ExtenderArgs) As Object
    Try
      Dim mbrLst As New MemberList()
      Dim mbrDisplayOptions As MemberDisplayOptions = New MemberDisplayOptions() _
         With{ .IncludeAllProperties = True, .IncludeMemberInfoForProperties = True}
      Dim lstMembers As LIst(Of MemberInfo) = 
         BRApi.Finance.Metadata.GetMembersUsingFilter(si, "CorpAccounts", "A#[GAAP Account Structure].Base", True, Nothing, mbrDisplayOptions)
      lstMembers.Sort(New AlphaNumericMemberInfoComparer())
      mbrLst.AddMemberInfosToList(lstMembers)
      Return mbrLst
    Catch ex As Exception
      Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
    End Try
  End Function   
End Class
Public Class AlphaNumericMemberInfoComparer
   Implements IComparer(Of MemberInfo)
    Public Function Compare(x As MemberInfo, y As MemberInfo) As Integer Implements IComparer(Of MemberInfo).Compare
        If x.Member.Name = y.Member.Name Then Return 0
        Dim xParts() As String = Regex.Split(x.Member.Name, "(\d+)")
        Dim yParts() As String = Regex.Split(y.Member.Name, "(\d+)")
        For i As Integer = 0 To Math.Min(xParts.Length, yParts.Length) - 1
            If xParts(i) <> yParts(i) Then
                Return PartCompare(xParts(i), yParts(i))
            End If
        Next
        Return xParts.Length.CompareTo(yParts.Length)
    End Function
    Private Shared Function PartCompare(x As String, y As String) As Integer
        Dim a, b As Integer
        Dim isNumericX As Boolean = Integer.TryParse(x, a)
        Dim isNumericY As Boolean = Integer.TryParse(y, b)
        If isNumericX And isNumericY Then
            Return a.CompareTo(b)
        End If
        Return String.Compare(x, y, StringComparison.OrdinalIgnoreCase)
    End Function
End ClassAlternate Sorting Result:
JackLacava
OneStream Employee
2 years agoThat's neat. It could be further generalized by accepting a parameterized switch (SortOrder=<human/lcg>) and another one to switch between ordering by name or description (SortBy=<name/desc>).
- RobbSalzmann2 years agoValued Contributor II
Or, if you want something quick and LINQ-y, these will work to sort lists of MemberInfo:
''VB.net Public Sub AlphaNumericSort(ByRef members as List(Of MemberInfo) Dim sortedMembers As List(Of MemberInfo) = members _ .OrderBy(Function(memberInfo) _ If(Regex.Match(memberInfo.Member.Name, "\d+").Success, _ 'Evaluation, starts with a number? Integer.Parse(Regex.Match(memberInfo.Member.Name, "\d+").Value), _ 'True Part Integer.MaxValue)) _ 'False Part, put after all that start with a number .ToList() End Sub // C#: public void AlphaNumericSort(ref List members) { List sortedMembers = members .OrderBy ( memberInfo => Regex.Match(memberInfo.Member.Name, @"\d+").Success ? //Evaluation, starts with a number? int.Parse(Regex.Match(memberInfo.Member.Name, @"\d+").Value) : //True int.MaxValue //False, put after all that start with a number ).ToList(); }Used like this:
Public Class MainClass Public Function Main(si As SessionInfo, globals As BRGlobals, api As Object, args As ExtenderArgs) As Object Try Dim mbrLst As New MemberList() Dim mbrDisplayOptions As MemberDisplayOptions = New MemberDisplayOptions() _ With{ .IncludeAllProperties = True, .IncludeMemberInfoForProperties = True} Dim lstMembers As List(Of MemberInfo) = BRApi.Finance.Metadata.GetMembersUsingFilter(si, "CorpAccounts", "A#[GAAP Account Structure].Base", True, Nothing, mbrDisplayOptions) '' Sort the members: AlphaNumericSort(lstMembers) mbrLst.AddMemberInfosToList(lstMembers) Return mbrLst Catch ex As Exception Throw ErrorHandler.LogWrite(si, New XFException(si, ex)) End Try End Function Public Sub AlphaNumericSort(ByRef members as List(Of MemberInfo) Dim sortedMembers As List(Of MemberInfo) = members _ .OrderBy(Function(memberInfo) _ If(Regex.Match(memberInfo.Member.Name, "\d+").Success, _ 'Evaluation, starts with a number? Integer.Parse(Regex.Match(memberInfo.Member.Name, "\d+").Value), _ 'True Part Integer.MaxValue)) _ 'False Part, put after all that start with a number .ToList() End Sub End Class- IB9 months agoNew Contributor
Hi Robb,
Thank You for posting the sort code. I tried using the function but it gives me an error that the source is empty. I dont think that is the case. Any advice would be greatly appreciated.
Thank You,
Indu
 
 
Related Content
- 7 months ago