Consulting

Page 1 of 2 1 2 LastLast
Results 1 to 20 of 29

Thread: Help with Sorting by first name

  1. #1
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location

    Help with Sorting by first name

    Please see that attached Link
    [vba]
    https://docs.google.com/file/d/0B1BS...it?usp=sharing
    [/vba]

    The Names are in C2, C13, C24, and C35, Im showing 4 but i have 50 employees that need to be sorted by first name.

    If possible can someone help with a VBA to Sort those Tables By First name?

    Name C2 has B2:J11
    C13 has B13:J22
    C24 has B24:J33
    C35 has B35:J44

    there are 50 of theses.

    Thank you!!

    Basically something like this...

    Start:
    [vba]
    https://docs.google.com/file/d/0B1BS...it?usp=sharing
    [/vba]

    end result:
    [vba]
    https://docs.google.com/file/d/0B1BS...it?usp=sharing
    [/vba]
    Last edited by menor59; 03-06-2013 at 01:18 PM.

  2. #2
    Knowledge Base Approver VBAX Guru GTO's Avatar
    Joined
    Sep 2008
    Posts
    3,368
    Location
    Greetings menor59

    Firstly, let me welcome you to the site! I've been a member for several years now, and am sure you will enjoy the help you can get here as much as I do.

    I would mention that you will get faster responses if we don't have to go to some other storage site to download an attachment. Frankly, a lot of these are blocked at plenty of worksites, including mine. Anyways, I was able to get the attachment, so here's a stab at maybe what you are looking to do?

    I did not try sorting the tables in place, as copying (sorted) seemed easier.

    In a Standard Module:
    [vba]Option Explicit

    Sub example()
    Dim DIC As Object ' Scripting.Dictionary
    Dim rngLRN As Range
    Dim arrNames As Variant
    Dim arrRows As Variant
    Dim arrOutput As Variant
    Dim lLastRecordNameRow As Long
    Dim lCurRow As Long
    Dim n As Long

    '// Temp "safety" in case <Cancel> //
    On Error Resume Next
    Set rngLRN = Application.InputBox( _
    Prompt:="Select the cell with the name of the last record...", _
    Title:=vbNullString, _
    Type:=8)
    On Error GoTo 0

    If rngLRN Is Nothing Then Exit Sub

    lLastRecordNameRow = rngLRN.Row

    '// Something to hopefully ensure the tables are equally spaced/have same no. of rows.//
    If Sheet1.Range("C" & lLastRecordNameRow).Offset(9).Row Mod 11 = 0 Then

    Set DIC = CreateObject("Scripting.Dictionary")

    '// I am assuming no duplicate names, and including the last name. Since our sort//
    '// will compare left to right, Bob Smith would end up before Bob Wills. //
    For lCurRow = Sheet1.Range("C" & lLastRecordNameRow).Row To 2 Step -11
    DIC.Item(UCase(Trim(Sheet1.Cells(lCurRow, 3).Value))) = lCurRow
    Next

    '// Plunk .Items (the row number) and .Keys(the name) into two parrallel arrays //
    '// (presuming Late-Bound), and then loop these into a single two-column array. /
    arrNames = DIC.Keys
    arrRows = DIC.Items
    ReDim arrOutput(0 To UBound(arrNames), 0 To 1)

    For n = 0 To UBound(arrOutput, 1)
    arrOutput(n, 0) = arrNames(n)
    arrOutput(n, 1) = arrRows(n)
    Next

    '// Sort our array. //
    BubbleSort arrOutput

    lCurRow = 2
    '// Now running through our sorted array, we can use the original row numbers to//
    '// know which cell (resized to the table) to copy to another sheet. //
    For n = LBound(arrOutput, 1) To UBound(arrOutput, 1)
    Sheet1.Range("B" & arrOutput(n, 1)).Resize(10, 9).Copy Sheet2.Cells(lCurRow, "B")
    lCurRow = lCurRow + 11
    Next
    End If
    End Sub

    ' Contrived from an example BubbleSort at:
    ' http://www.xtremevbtalk.com/showpost...90&postcount=2
    Function BubbleSort(ByRef vntIOArray)
    Dim lOuter As Long, lInner As Long, lLBnd As Long, lUBnd As Long, Tmp(0 To 1) As Variant

    lLBnd = LBound(vntIOArray, 1)
    lUBnd = UBound(vntIOArray, 1)

    For lOuter = lLBnd To lUBnd - 1
    For lInner = lLBnd To lUBnd - lOuter - 1
    If vntIOArray(lInner, 0) > vntIOArray(lInner + 1, 0) Then
    Tmp(0) = vntIOArray(lInner, 0)
    Tmp(1) = vntIOArray(lInner, 1)

    vntIOArray(lInner, 0) = vntIOArray(lInner + 1, 0)
    vntIOArray(lInner, 1) = vntIOArray(lInner + 1, 1)

    vntIOArray(lInner + 1, 0) = Tmp(0)
    vntIOArray(lInner + 1, 1) = Tmp(1)
    End If
    Next lInner
    Next lOuter
    End Function[/vba]

    If you look at the attached, you can see the difference between the sheet's CodeName and Worksheet name.

    Hope thatg helps,

    Mark
    Attached Files Attached Files

  3. #3
    VBAX Contributor
    Joined
    Oct 2012
    Location
    Brisbane, Queensland, Australia
    Posts
    163
    Location
    Assuming that the data is in Sheet1, the following code will make a copy of that sheet as Sheet1 (2) with the data sorted as required. (It should handle all of your employees)

    [VBA]Sub sort()
    Dim strnames As String
    Dim varnames As Variant
    Dim varnamesandrows()
    Dim rnganchor As Range
    Dim rngtarget As Range
    Dim lngOffset As Long
    Set rnganchor = Worksheets(1).Range("C1")
    Dim i As Long, j As Long, k As Long, n As Long
    i = 0
    strnames = ""
    Do While rnganchor.Offset(11 * i + 1, 0) <> ""
    strnames = strnames & "|" & rnganchor.Offset(11 * i + 1, 0)
    i = i + 1
    Loop
    strnames = Mid(strnames, 2)
    varnames = Split(strnames, "|")
    j = Val(Format(UBound(varnames)))
    ReDim varnamesandrows(j, 1)
    For i = LBound(varnames) To UBound(varnames)
    varnamesandrows(i, 0) = varnames(i)
    varnamesandrows(i, 1) = 11 * i + 1
    Next i
    Call BubbleSort(varnamesandrows)
    Sheets("Sheet1").Copy Before:=Sheets(2)
    Set rngtarget = Worksheets("Sheet1 (2)").Range("C1")
    For i = LBound(varnames) To UBound(varnames)
    rngtarget.Offset(11 * i + 1, 0).Value = varnamesandrows(i, 0)
    n = varnamesandrows(i, 1)
    For j = 1 To 7
    For k = 1 To 6
    rngtarget.Offset(11 * i + 1 + j, k).Value = rnganchor.Offset(n + j, k).Value
    Next k
    Next j
    Next i
    End Sub
    Sub BubbleSort(arr)
    Dim strTemp1 As String
    Dim strTemp2 As String
    Dim i As Long
    Dim j As Long
    Dim lngMin As Long
    Dim lngMax As Long
    lngMin = LBound(arr)
    lngMax = UBound(arr)
    For i = lngMin To lngMax - 1
    For j = i + 1 To lngMax
    If arr(i, 0) > arr(j, 0) Then
    strTemp1 = arr(i, 0)
    strTemp2 = arr(i, 1)
    arr(i, 0) = arr(j, 0)
    arr(i, 1) = arr(j, 1)
    arr(j, 0) = strTemp1
    arr(j, 1) = strTemp2
    End If
    Next j
    Next i
    End Sub[/VBA]

  4. #4
    Distinguished Lord of VBAX VBAX Grand Master Bob Phillips's Avatar
    Joined
    Apr 2005
    Posts
    25,453
    Location
    Doug, can you add VBA tags around your code? There is a green VBA button above the reply textbox that adds them automatically.
    ____________________________________________
    Nihil simul inventum est et perfectum

    Abusus non tollit usum

    Last night I dreamed of a small consolation enjoyed only by the blind: Nobody knows the trouble I've not seen!
    James Thurber

  5. #5
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    Read below...Im sorry

  6. #6
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    IM Sorry all Typo:
    what i originally stated...

    The Names are in C2, C13, C24, and C35, Im showing 4 but i have 50 employees that need to be sorted by first name.

    If possible can someone help with a VBA to Sort those Tables By First name?

    Name C2 has B2:J11
    C13 has B13:J22
    C24 has B24:J33
    C35 has B35:J44

    there are 50 of theses.

    Thank you!!

    Basically something like this...

    Should read:

    The Names are in C12, C23, C24, and C35, Im showing 4 but i have 50 employees that need to be sorted by first name.

    If possible can someone help with a VBA to Sort those Tables By First name?

    Name C12 has B12:J21
    C23 has B23:J32
    C34 has B34:J43
    C45 has B45:J54

    there are 50 of theses.

    Thank you!!

    Basically something like this...

    can you please modify your code above?

  7. #7
    VBAX Contributor
    Joined
    Oct 2012
    Location
    Brisbane, Queensland, Australia
    Posts
    163
    Location
    In my code, replace

    [VBA]Set rnganchor = Worksheets(1).Range("C1")
    [/VBA]

    with

    [VBA]Set rnganchor = Worksheets(1).Range("C11")
    [/VBA]

    and replace

    [VBA] Set rngtarget = Worksheets("Sheet1 (2)").Range("C1")
    [/VBA]

    with

    [VBA] Set rngtarget = Worksheets("Sheet1 (2)").Range("C11")
    [/VBA]

  8. #8
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    Doug,

    So i added your Code to mine...

    My Code...which is in Sheet1 (Blank)
    Sub Copy_Sheet()
    If Range("A2").Value >= Range("A1").Value Then
    MsgBox "This Date you Selected has passed...Please Click Undo, and delete the Tab Below Labeled " & Sheets(1).Range("X12").Text
    Else
    End If
    
    Dim wSht As Worksheet
    Dim shtName As String
    shtName = Sheets(1).Range("X12")
    For Each wSht In Worksheets
        If wSht.Name = shtName Then
            MsgBox "Sheet already exists...Use the Button " & _
                "on the TAB titled BLANK!" & _
                " **Remember to select a New Date!"
            Exit Sub
        End If
    Next wSht
    Sheets(1).Copy Before:=Sheets(1)
    Sheets(1).Name = shtName
    Sheets(shtName).Move After:=Sheets(Sheets.Count)
    End Sub
    Your Code:
    Sub sort()
        Dim strnames As String
        Dim varnames As Variant
        Dim varnamesandrows()
        Dim rnganchor As Range
        Dim rngtarget As Range
        Dim lngOffset As Long
        Set rnganchor = Worksheets(1).Range("C12")
        Dim i As Long, j As Long, k As Long, n As Long
        i = 0
        strnames = ""
        Do While rnganchor.Offset(11 * i + 1, 0) <> ""
            strnames = strnames & "|" & rnganchor.Offset(11 * i + 1, 0)
            i = i + 1
        Loop
        strnames = Mid(strnames, 2)
        varnames = Split(strnames, "|")
        j = Val(Format(UBound(varnames)))
        ReDim varnamesandrows(j, 1)
        For i = LBound(varnames) To UBound(varnames)
            varnamesandrows(i, 0) = varnames(i)
            varnamesandrows(i, 1) = 11 * i + 1
        Next i
        Call BubbleSort(varnamesandrows)
        Sheets("Sheet1").Copy Before:=Sheets(2)
        Set rngtarget = Worksheets("Sheet1 (2)").Range("C12")
        For i = LBound(varnames) To UBound(varnames)
            rngtarget.Offset(11 * i + 1, 0).Value = varnamesandrows(i, 0)
            n = varnamesandrows(i, 1)
            For j = 1 To 7
                For k = 1 To 6
                    rngtarget.Offset(11 * i + 1 + j, k).Value = rnganchor.Offset(n + j, k).Value
                Next k
            Next j
        Next i
    End Sub
    Sub BubbleSort(arr)
        Dim strTemp1 As String
        Dim strTemp2 As String
        Dim i As Long
        Dim j As Long
        Dim lngMin As Long
        Dim lngMax As Long
        lngMin = LBound(arr)
        lngMax = UBound(arr)
        For i = lngMin To lngMax - 1
            For j = i + 1 To lngMax
                If arr(i, 0) > arr(j, 0) Then
                    strTemp1 = arr(i, 0)
                    strTemp2 = arr(i, 1)
                    arr(i, 0) = arr(j, 0)
                    arr(i, 1) = arr(j, 1)
                    arr(j, 0) = strTemp1
                    arr(j, 1) = strTemp2
                End If
            Next j
        Next i
    End Sub
    soooo...

    what my code does is this...

    when the workbook is opened theres a worksheet called "Blank".
    on that work sheet theres pull down (data validation) in C2 (which is referenced to X12 in format MMM dd, yyyy) that has every 1st Sunday in the year...when my code above is activated based on the date in the pull down window, my code above creates a new worksheet based on the value in X12 (the MMM dd, YYYY) value in X12. can you make your code work with mine....make sense sir...ohhh and thank you!!!

    when putting your code in with mine it errors out with

    Compile error:
    Member already exists in an object module from which this object module derives....

    Is it possible for you to try your code by doing the following...

    Create a workbook, name one worksheet Blank
    delete sheet2 and 3
    Put My code in ALT-F11 of the Blank worksheet...

    In cell X12 put the date of Mar 10, 2013 in that format...

    run my code.....

    it should have created a new work sheet entitled Mar 10, 2013 keeping the Blank intact (thats basically the template)

    Now delete the work sheet entitles Mar 10, 2013 and put your code after mine...and run the codes...
    Last edited by menor59; 03-09-2013 at 06:31 PM.

  9. #9
    VBAX Contributor
    Joined
    Oct 2012
    Location
    Brisbane, Queensland, Australia
    Posts
    163
    Location
    Put all of the code in a standard module (Insert>Module in the VBE) rather than in Sheet 1.

  10. #10
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    will my code continue to work as before??

  11. #11
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    ok its breaking here....

    Sheets("Sheet1").Copy Before:=Sheets(2)
    did you see my code before??? above?

  12. #12
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    Doug can you PM me your email address so i can send it you you?

  13. #13
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    Doug can you PM me your email address if your ok with it?

  14. #14
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    OK Doug,

    the code works but i just noticed its moving the names in Column C

    rephrase...

    it needs to use the Names are in C12, C23, C24, and C35, etc etc...for sorting....

    and needs to arrange the chart also following the name...ie...


    so when sorting based on names in C12, C23, C34, C45 etc. etc....

    it must include the range around it....

    C12 has the name to sort...then select and move B12:J21
    C23 has the name to sort...then select and move B23:J32
    C34 has the name to sort...then select and move B34:J43
    C45 has the name to sort...then select and move B45:J54
    etc.etc..

    the B's - J's is a chart with the C's having names...


    so lets say the following....

    C12 = Darth Vader something in D14 B12:J21
    C23 = harry potter something in F27 B23:J32
    c34 = Cory feldman something in I40 B34:J43
    c45 = luke skywalker something in H46 B45:J54

    running the module would do the following...

    c12 = Cory feldman something in I18 B12:J21
    c23 = Darth Vader something in D25 B23:J32
    c34 = Harry Potter something in F38 B34:J43
    C45 = Luke Skywalker something in H46 B45:J54

    Picture each name has a Boarder around it... the B12:J21, B23:J32 , b34:j43 , and B45:j54 and the names are in each border at c12, c23, c34, c45.... based on the name is needs to sort and move the border and whats inside the border along with the name....

    does that help??
    Last edited by menor59; 03-09-2013 at 09:44 PM.

  15. #15
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    Here is a Before:

    https://docs.google.com/file/d/0B1BS...it?usp=sharing


    Heres an after:

    https://docs.google.com/file/d/0B1BS...it?usp=sharing

    ive also modified you code slightly...

    please notice that han solo and his table moved in order of the other 3

    Sub sort()
        Dim strnames As String
        Dim varnames As Variant
        Dim varnamesandrows()
        Dim rnganchor As Range
        Dim rngtarget As Range
        Dim lngOffset As Long
        Set rnganchor = ActiveSheet.Range("C11")
        Dim i As Long, j As Long, k As Long, n As Long
        i = 0
        strnames = ""
        Do While rnganchor.Offset(11 * i + 1, 0) <> ""
            strnames = strnames & "|" & rnganchor.Offset(11 * i + 1, 0)
            i = i + 1
        Loop
        strnames = Mid(strnames, 2)
        varnames = Split(strnames, "|")
        j = Val(Format(UBound(varnames)))
        ReDim varnamesandrows(j, 1)
        For i = LBound(varnames) To UBound(varnames)
            varnamesandrows(i, 0) = varnames(i)
            varnamesandrows(i, 1) = 11 * i + 1
        Next i
        Call BubbleSort(varnamesandrows)
            Set rngtarget = ActiveSheet.Range("C11")
        For i = LBound(varnames) To UBound(varnames)
            rngtarget.Offset(11 * i + 1, 0).Value = varnamesandrows(i, 0)
            n = varnamesandrows(i, 1)
            For j = 1 To 7
                For k = 1 To 6
                    rngtarget.Offset(11 * i + 1 + j, k).Value = rnganchor.Offset(n + j, k).Value
                Next k
            Next j
        Next i
    End Sub
    Sub BubbleSort(arr)
        Dim strTemp1 As String
        Dim strTemp2 As String
        Dim i As Long
        Dim j As Long
        Dim lngMin As Long
        Dim lngMax As Long
        lngMin = LBound(arr)
        lngMax = UBound(arr)
        For i = lngMin To lngMax - 1
            For j = i + 1 To lngMax
                If arr(i, 0) > arr(j, 0) Then
                    strTemp1 = arr(i, 0)
                    strTemp2 = arr(i, 1)
                    arr(i, 0) = arr(j, 0)
                    arr(i, 1) = arr(j, 1)
                    arr(j, 0) = strTemp1
                    arr(j, 1) = strTemp2
                End If
            Next j
        Next i
    End Sub

  16. #16
    VBAX Contributor
    Joined
    Oct 2012
    Location
    Brisbane, Queensland, Australia
    Posts
    163
    Location
    Use the following:

    [VBA]Sub sort()
    Dim strnames As String
    Dim varnames As Variant
    Dim varnamesandrows()
    Dim rng1 As Range
    Dim rng2 As Range
    Dim lngOffset As Long
    Dim newSheet As Worksheet
    Dim origSheet As Worksheet
    Set origSheet = ActiveSheet
    Set rng1 = origSheet.Range("C11")
    Dim i As Long, j As Long, k As Long, n As Long
    i = 0
    strnames = ""
    Do While rng1.Offset(11 * i + 1, 0) <> ""
    strnames = strnames & "|" & rng1.Offset(11 * i + 1, 0)
    i = i + 1
    Loop
    strnames = Mid(strnames, 2)
    varnames = Split(strnames, "|")
    j = Val(Format(UBound(varnames)))
    ReDim varnamesandrows(j, 1)
    For i = LBound(varnames) To UBound(varnames)
    varnamesandrows(i, 0) = varnames(i)
    varnamesandrows(i, 1) = 11 * i + 1
    Next i
    Call BubbleSort(varnamesandrows)
    Set newSheet = Sheets.Add
    origSheet.UsedRange.Copy
    newSheet.Paste
    Set rng2 = newSheet.Range("C11")
    For i = LBound(varnames) To UBound(varnames)
    rng1.Offset(11 * i + 1, 0).Value = varnamesandrows(i, 0)
    n = varnamesandrows(i, 1)
    For j = 0 To 8
    For k = 1 To 6
    rng1.Offset(11 * i + 1 + j, k).Value = rng2.Offset(n + j, k).Value
    Next k
    Next j
    Next i
    Application.DisplayAlerts = False
    newSheet.Delete
    Application.DisplayAlerts = True
    End Sub
    Sub BubbleSort(arr)
    Dim strTemp1 As String
    Dim strTemp2 As String
    Dim i As Long
    Dim j As Long
    Dim lngMin As Long
    Dim lngMax As Long
    lngMin = LBound(arr)
    lngMax = UBound(arr)
    For i = lngMin To lngMax - 1
    For j = i + 1 To lngMax
    If arr(i, 0) > arr(j, 0) Then
    strTemp1 = arr(i, 0)
    strTemp2 = arr(i, 1)
    arr(i, 0) = arr(j, 0)
    arr(i, 1) = arr(j, 1)
    arr(j, 0) = strTemp1
    arr(j, 1) = strTemp2
    End If
    Next j
    Next i
    End Sub
    [/VBA]

  17. #17
    VBAX Regular
    Joined
    Mar 2013
    Posts
    45
    Location
    Almost..

    So uI created one entry and populated the cells with numbers...the green area...when i ran the macro it put the names correctly...but from the new name down...it also populated the same numbers i inputed into the user....see the enclosed sample...
    https://docs.google.com/file/d/0B1BS...it?usp=sharing

  18. #18
    Knowledge Base Approver VBAX Wizard
    Joined
    Apr 2012
    Posts
    5,645
    Why don't you upload your file here ?
    This forum has been designed to provide this facility and is much more robust than the site you posted it.

    You can keep it simple using:

    [VBA]Sub M_snb()
    With CreateObject("System.Collections.ArrayList")
    For j = 12 To 45 Step 11
    .Add Sheet1.Cells(j, 3).Value
    Next
    .sort
    sn = .toarray
    End With

    For j = 0 To UBound(sn)
    Sheet1.Cells(12 + 11 * j, 30).Resize(10, 9) = Sheet1.Columns(3).Find(sn(j), , xlValues, 1).Offset(, -1).Resize(10, 9).Value
    Next
    End Sub[/VBA]
    Last edited by snb; 03-10-2013 at 03:55 AM.

  19. #19
    VBAX Contributor
    Joined
    Oct 2012
    Location
    Brisbane, Queensland, Australia
    Posts
    163
    Location
    Attached is an After file created by running the code in the workbook on the Before file that you posted at:

    https://docs.google.com/file/d/0B1BS...it?usp=sharing


    As in the file that you posted at:


    https://docs.google.com/file/d/0B1BS...it?usp=sharing

    you have reinstated the formula to sum the Total Hours, I have done the same in the Before file that this was created from and as a result have changed the

    [VBA]
    For j = 0 to 8
    [/VBA]

    to

    [VBA]
    For j = 0 to 7
    [/VBA]

    Otherwise, the code is the same as that in my most recent post.
    Attached Files Attached Files

  20. #20
    Knowledge Base Approver VBAX Wizard
    Joined
    Apr 2012
    Posts
    5,645
    Or use the builtin sorting facility for named ranges:

    [vba]Sub M_snb_001()
    For j = 12 To 45 Step 11
    Sheet1.Cells(j, 3).Offset(, -1).Resize(10, 9).Name = Replace(Sheet1.Cells(j, 3).Value, " ", "_")
    Next

    For j = 1 To Application.Names.Count
    Sheet1.Cells(12 + 11 * (j - 1), 30).Resize(10, 9) = Application.Names(j).RefersToRange.Value
    Next
    End Sub[/vba]

    and if you want to preserve the formatting:
    [VBA]Sub M_snb_002()
    For j = 12 To 45 Step 11
    Sheet1.Cells(j, 3).Offset(, -1).Resize(10, 9).Name = Replace(Sheet1.Cells(j, 3).Value, " ", "_")
    Next

    For j = 1 To Application.Names.Count
    Application.Names(j).RefersToRange.Copy Sheet1.Cells(12 + 11 * (j - 1), 30)
    Next
    End Sub[/VBA]
    Last edited by snb; 03-10-2013 at 04:41 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •