-3

I am starting to use VBA programing and am stumped on how to extract what I need from non-sequential data. I have tried using excel functions such as "VLookup", "INDEX(Match(", "MAX(If", "MIN(If" but can only find the first or last match and nothing around where the sequence breaks. I don't think it is possible with Excel functions which is why I am trying to figure out how to do this in VBA. Maybe "If, Else, Loop" but not sure.

Criteria: Must have matching "Item desc" and "Supplier".
Output1: Find Year/Week after gap in delivery.
Output2: Find Year/Week prior to gap in delivery.

Below is a sample image of Excel layout of the raw data on sheet1 and the analysis on sheet2.

Image of Excel issue:

JosephA
  • 3
  • 2
  • 2
    Always helps to explain what you already tried, and what problems you had. Also, it would help to explain exactly what "gap in delivery" looks like. – Tim Williams Oct 03 '18 at 16:10
  • Yeah, just a bit too much to guess on here. For instance, on the Analysis tab, do you expect `Item 876A` with `Supplier A` to really show up 11 times? If so, what is the expected logic or output with 11 entries? – C.A.R. Oct 03 '18 at 16:48
  • Tim W. - Gap in delivery occurs when the list of year/weeks are not sequential for a given Item and Supplier. – JosephA Oct 03 '18 at 17:21
  • C.A.R - You are correct, there should only be one line for each Item Desc/ Supplier in the Analysis tab. The goal is to input data from "Raw Data: column A" into the Analysis Column A and B that match Column C and D. Analysis column B should look at the matching data from Raw columns B and C, then select the oldest entry in the most recent sequence. Analysis Column A should look at the matching data from Raw columns B and C, then select the next year/week after the sequence ends. – JosephA Oct 03 '18 at 17:37

1 Answers1

0

This code should do what you want but check if it doesn't make mistakes. I didn't check it too much so it may produce errors. Run it in a copy of workbook.

You should put this into class module and call it 'CItem':

Public pItemDescription As String
Public pSupplier As String
Public pDateDelivery As Collection

https://excelmacromastery.com/vba-class-modules/

That table in 'Analysis' should be empty.

Then this into regular module:

Option Explicit

Sub SortCheck()

    Dim aSht As Worksheet
    Dim bSht As Worksheet

    Dim tempItemDescription As String
    Dim tempSupplier As String
    Dim tempDateDelivery As String


    Dim xItemsAll As Collection
    Dim xItem As CItem
    Dim xI As Variant
    Dim flag As Boolean

    Dim xTemp As Variant
    Dim i As Long
    Dim j As Long
    Dim k As Long
    Dim Row As Long

    Set xItemsAll = New Collection
    Set xItem = New CItem

    Set aSht = Worksheets("Raw Data")
    Set bSht = Worksheets("Analysis")

    Row = 2

    flag = True

    Do
        ' If the cell is empty, stop populating the collection
        If aSht.Cells(Row, 2).Value = "" Then Exit Do

        ' ---
        tempDateDelivery = aSht.Cells(Row, 1).Value
        tempItemDescription = aSht.Cells(Row, 2).Value
        tempSupplier = aSht.Cells(Row, 3).Value

        'If xItemsAll contains some records, check wheter similar records exist
        If xItemsAll.Count > 0 Then

            For Each xI In xItemsAll

                If tempItemDescription = xI.pItemDescription And tempSupplier = xI.pSupplier Then

                    Set xItem = New CItem
                    Set xItem = xI
                    xItem.pDateDelivery.Add tempDateDelivery
                    Set xItem = Nothing
                    flag = False
                    Exit For

                Else

                    flag = True

                End If

            Next xI

        End If

        ' If the first pass or no element in collection yet, create new record

        If flag = True Then

            Set xItem = New CItem

            With xItem
                .pItemDescription = tempItemDescription
                .pSupplier = tempSupplier

                Set .pDateDelivery = New Collection
                .pDateDelivery.Add tempDateDelivery
            End With

            xItemsAll.Add xItem

            Set xItem = Nothing

            flag = False

        End If

        Row = Row + 1

    Loop


    'Sort the collection - Item Description in order
    For i = 1 To xItemsAll.Count - 1
        For j = i + 1 To xItemsAll.Count
            If xItemsAll(i).pItemDescription > xItemsAll(j).pItemDescription Then

                Set xItem = New CItem
                Set xItem = xItemsAll(j)

                xItemsAll.Remove j
                If j <> xItemsAll.Count + 1 Then
                    xItemsAll.Add xItemsAll(i), , j
                Else
                    xItemsAll.Add xItemsAll(i), , , j - 1
                End If

                xItemsAll.Remove i
                If i <> xItemsAll.Count + 1 Then
                    xItemsAll.Add xItem, , i
                Else
                    xItemsAll.Add xItem, , , i - 1
                End If

                Set xItem = Nothing

            End If
        Next j
    Next i

    'Sort the collection - Suplier in order
    For i = 1 To xItemsAll.Count - 1
        For j = i + 1 To xItemsAll.Count
            If xItemsAll(i).pItemDescription = xItemsAll(j).pItemDescription Then
                If xItemsAll(i).pSupplier > xItemsAll(j).pSupplier Then

                    Set xItem = New CItem
                    Set xItem = xItemsAll(j)

                    xItemsAll.Remove j
                    If j <> xItemsAll.Count + 1 Then
                        xItemsAll.Add xItemsAll(i), , j
                    Else
                        xItemsAll.Add xItemsAll(i), , , j - 1
                    End If

                    xItemsAll.Remove i
                    If i <> xItemsAll.Count + 1 Then
                        xItemsAll.Add xItem, , i
                    Else
                        xItemsAll.Add xItem, , , i - 1
                    End If

                    Set xItem = Nothing

                End If
            End If
        Next j
    Next i

    'Sort the collection - Dates in order
    For k = 1 To xItemsAll.Count
        For i = 1 To xItemsAll(k).pDateDelivery.Count - 1
            For j = i + 1 To xItemsAll(k).pDateDelivery.Count
                If xItemsAll(k).pItemDescription = xItemsAll(k).pItemDescription Then
                    If xItemsAll(k).pSupplier = xItemsAll(k).pSupplier Then
                        If xItemsAll(k).pDateDelivery(i) > xItemsAll(k).pDateDelivery(j) Then

                            xTemp = xItemsAll(k).pDateDelivery(j)

                            xItemsAll(k).pDateDelivery.Remove j
                            If j <> xItemsAll(k).pDateDelivery.Count + 1 Then
                                xItemsAll(k).pDateDelivery.Add xItemsAll(k).pDateDelivery(i), , j
                            Else
                                xItemsAll(k).pDateDelivery.Add xItemsAll(k).pDateDelivery(i), , , j - 1
                            End If

                            xItemsAll(k).pDateDelivery.Remove i
                            If i <> xItemsAll(k).pDateDelivery.Count + 1 Then
                                xItemsAll(k).pDateDelivery.Add xTemp, , i
                            Else
                                xItemsAll(k).pDateDelivery.Add xTemp, , , i - 1
                            End If

                        End If
                    End If
                End If
            Next j
        Next i
    Next k


    Row = 2

    For i = 1 To xItemsAll.Count
        For j = 1 To xItemsAll(i).pDateDelivery.Count - 1
            If CLng(Mid(xItemsAll(i).pDateDelivery(j + 1), 5)) <> (CLng(Mid(xItemsAll(i).pDateDelivery(j), 5)) + 1) Then

                bSht.Cells(Row, 1).Value = xItemsAll(i).pDateDelivery(j + 1)

                bSht.Cells(Row, 2).Value = xItemsAll(i).pDateDelivery(j)

                bSht.Cells(Row, 3).Value = xItemsAll(i).pItemDescription

                bSht.Cells(Row, 4).Value = xItemsAll(i).pSupplier

                Row = Row + 1

            End If
        Next j
    Next i

End Sub

For the code to work corectly it has to be 201801, 201805, etc. not 20181, 20185, etc. So if you have it different you would have to modify it with functions or vba.

Shelty
  • 296
  • 2
  • 5
  • Shelty: This worked fantastic! I have tested it several ways and it is quite effective and perfect for my needs. You have taught me some new ways of using VBA that I had not realized were possible. Thank you very much! – JosephA Oct 04 '18 at 17:35