-1

In the next sample structure BOM:

updated screenshot

we find articles, and further down we find their structure with its content, other articles which in their turn may or may not have their content and so on.

I'm trying to create a recursive routine to determine whether or not they exist further down and determine their level:

Public eof As Long

Sub RecursiveSearch()
    Dim i As Long
    Dim ws As Worksheet
    Dim art_to_search As String
    Dim str_art As Integer
    Dim l As Integer ' Declare l as a local variable
    
    Set ws = ThisWorkbook.Worksheets("Sheet1") ' Replace "Sheet1" with the actual sheet name
    eof = Cells.Find("*", [A1], , , xlByRows, xlPrevious).Row 'Recalc end of file
    'l is the level
    l = 1
    i = 1
    ' Loop through each row in the data range
    For i = i To eof

    art_to_search = Cells(i, 2).Value
    str_art = Len(art_to_search)

    If str_art = 15 Then
        Debug.Print i & " " & art_to_search
        Call ArticleExists(art_to_search, i + 1, eof, l)
        End If
    Next i
End Sub

Sub ArticleExists(ByVal article As String, ByVal startRow As Long, ByVal lastRow As Long, ByRef l As Integer)
    Dim a As Long
    ' Loop through each row below the start row
    For a = startRow To lastRow
        If Trim(article) = Trim(Range("A" & a).Value) Then
            l = l + 1
            Range("D" & a) = l
            Call ArticleExists(Cells(a, 2).Offset(2, 0), a + 2, lastRow, l)
            Exit Sub
        End If
    Next a
End Sub

It works, but the counting of levels is not correct. Could you give me some help to improve my understanding of recursion on this problem?

wiwi_99
  • 3
  • 3
  • 1
    Can you clarify how the 'level' should be determined? For the article you highlight what is the correct level? And there are other articles in your image that appear lower down in the data ... what is the correct level for those? – JohnM Aug 24 '23 at 08:58
  • As stated above, it would be good to better define what a `correct level` means. The best approach I think would be to explain the highlighted item analysis and **why so, based on what logic**. Now, looking to `l` variable way of using it looks strange. I mean, it is continuously updated by `ArticleExists`, so the following searched article level will starts from the total existing `l` value. It looks (without knowing what a correct leveling means) that you must make `l = 0` before each call `Call ArticleExists(art_to_search, i + 1, eof, l)`... – FaneDuru Aug 24 '23 at 09:40
  • [Why should I not upload images of code/*data*/errors when asking a question?](https://meta.stackoverflow.com/questions/285551/why-should-i-not-upload-images-of-code-data-errors-when-asking-a-question) and also please include your desired results from your posted data. – Ron Rosenfeld Aug 24 '23 at 09:55
  • Sorry for the lack of information on "correct levels". The variable "l" being the level, in the example given, we start from article 47-10-014-04062, which is level 1. Within its structure, we come across article 47-10-026-10011, so this will be level 2. Within article 47-10-026-10011, we come across article 91-584-130-0540, and we increase the level by +1, so level 3, and so on. – wiwi_99 Aug 24 '23 at 11:41
  • @RonRosenfeld updated the screenshot on the initial post. Thank ypu all. – wiwi_99 Aug 24 '23 at 11:53
  • Then, what to be the meaning of yellow highlighted cells? Instead of confusing us... Then, only showing numbers (in the updated picture, which is not what has been required - something editable to be tested...), without showing the respective occurrences based on what to count them, is not too eloquent. You should not use your real existing data, you should use data to be eloquent looking to them... – FaneDuru Aug 24 '23 at 11:53
  • @FaneDuru, because l = 1, represents the level 1 = 47-10-014-04062, where it starts. The 47-10-026-10011 is inside, and we found it below with it own structure, so it will represent level 2. And so on. And the yellow highlighted cell, was just for me to ensure the articles are the same. Thank you for your time – wiwi_99 Aug 24 '23 at 12:02
  • Can you explain what do you think to be of any help in the picture you show? Since, we cannot see the incriminated BOM components of different levels... – FaneDuru Aug 24 '23 at 12:12
  • @FaneDuru, The variable "l" being the level, in the example given, we start from article 47-10-014-04062, which is level 1. Within its structure, we come across article 47-10-026-10011, so this will be level 2. Within article 47-10-026-10011, we come across article 91-584-130-0540, and we increase the level by +1, so level 3, and so on. The updated screenshot show us in the "correct level" what expected The levels are incremented + 1 with the recurse sub, what is not acomplished yet with i have wrote (see no correct level column) – wiwi_99 Aug 24 '23 at 12:17
  • So, do you see in the picture the level 3 for "47-10-014-04062" article? I don't... Your picture starts showing the levels from the "47-10-026-10011" article. Then, "91-584-130-0540" article comes with 7 instead of 3 levels/occurrences, but since we cannot see these occurrences, you could only tell us about it, why the need of such a picture? But, maybe somebody else better understands your way of explaining... – FaneDuru Aug 24 '23 at 12:28
  • @FaneDure, maybe you are right, it is me who have didn't explained well. I have updated the picture with the picture of the structure provided by ike (thank you!). Kind regards, and thank you – wiwi_99 Aug 24 '23 at 13:40

1 Answers1

0

You can use this code.

It retrieves per Article from column A the subset of articles by using CurrentRegion - and then iterates over each sub-article the same way.

Option Explicit

Public Sub readHierarchy()
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets(1) '---> adjust this
readLevel ws.UsedRange.Rows(1), 1
End Sub

Private Function readLevel(rgRow As Range, iLevel As Long)
    rgRow.Cells(1, 4) = iLevel
    
    Dim rgSubLevels As Range
    Set rgSubLevels = rgRow.CurrentRegion.Offset(2)
    If rgSubLevels.Rows.Count >= 3 Then
        Set rgSubLevels = rgSubLevels.Resize(rgSubLevels.Rows.Count - 2)
    Else
        Exit Function
    End If
    
    Dim rgNext As Range
    For Each rgRow In rgSubLevels.Rows
        Set rgNext = findArticle(rgRow, rgRow.Cells(1, 2))
        If Not rgNext Is Nothing Then
            readLevel rgNext.Rows(1), iLevel + 1
        End If
    Next

End Function

Public Function findArticle(rgStart As Range, Article As String) As Range

Dim ws As Worksheet: Set ws = rgStart.Parent

Dim rgFound As Range

Set findArticle = ws.UsedRange.Columns(1).Find(What:=Article, After:=rgStart.Cells(1, 1), LookIn:=xlValues, _
        LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
        MatchCase:=False, SearchFormat:=False)
End Function

enter image description here

Ike
  • 9,580
  • 4
  • 13
  • 29
  • Exactly that structure who corresponds to mine. Thank you a lot, but seems that i have a VBA Error 1004 - Application-Defined or Object-Defined Error at this line: Set rgSubLevels = rgSubLevels.Resize(rgSubLevels.Rows.Count - 2) – wiwi_99 Aug 24 '23 at 13:34
  • is there an article w/o sub-articles in your list? I updated the code to check for that. – Ike Aug 24 '23 at 14:11
  • Great - as you are new to SO: don't forget to mark it as an answer so others can see your question is solved. – Ike Aug 25 '23 at 06:36