-2

Trying to solve for a loop that reads the account numbers in column 'E' on the "Info sheet" starting from 'E2' and takes that number and inputs it in the first row containing an empty white cell on the "Proof" sheet ('E4') under the account number section. Once the number is placed there, the "long name" (found in the table on the 200th row) associated with the account number in the cell 'E4' appears in the first empty white cell ('B4') under the account name section. Then, the loop continues and reads the next cell ('E3') on the "Input sheet", and if that account number belongs to the same name, place that number in the next white cell ('G4') on the "Proof" sheet. If the account number is not associated with the account name in cell 'B4', put it in the next line containing an empty white cell 'E12' and assign the appropriate name for that number in cell under account name in cell 'B12' and continue down the list in column 'E' on the Info sheet and repeat the process until all the account numbers on the first sheet are complete and all the appropriate account numbers are on the row that has the appropriate 'long name' for those account numbers.

How can I put all the accounts linked to the account name on the same row in the specific white cells without posting them twice on the same row?

This is the code I have:

Sub loopything()


Dim infoSheet As Worksheet, proofSheet As Worksheet, refRange As         Range, lastRow As Long, r As Long
Dim acct As String, foundAcct As Range, nextRow As Long
Set infoSheet = ThisWorkbook.Sheets("Info Sheet")
Set proofSheet = ThisWorkbook.Sheets("Proof")

With proofSheet
nextRow = 4 ' waiting to adjust to normal table format
End With

With proofSheet

Set refRange = .Range("A200:L79000")

End with 

With InfoSheet

lastRow = 30 ' .cells(.rows.count, "E").end(xlup).row

For r = 2 To lastRow

acct = .Cells(r, "E")
Set foundAcct = refRange.Find(what:=acct)
longname = foundAcct.Offset(0, 1)


proofSheet.Cells(nextRow, "E") = acct
proofSheet.Cells(nextRow, "B") = longname
nextRow = nextRow + 8   ' would be nicer to just add one row (see  first note)

Next r

End With

End Sub

Take a look at the snippets for reference.

Info Input Sheet Real Info Input Sheet

Proof Sheet Real Proof Sheet

The code is currently doing this:

Practice Input Sheet Example with Code in VBA

Practice Proof Sheet Example with code in VBA

See how in the practice examples, which is supposed to mimic the real sheets, the name appears on multiple rows with their respective account numbers when they should be appearing on the same row under the same name with all the account numbers on one row.

ZygD
  • 22,092
  • 39
  • 79
  • 102
Mamamia93
  • 25
  • 6
  • [No attempt was made](http://idownvotedbecau.se/noattempt/). Please always include what you have tried. Note that this is not a free coding service. And you need to ask a question (see [ask] and [Why is “Can someone help me?” not an actual question?](https://meta.stackoverflow.com/a/284237/3219613)). – Pᴇʜ Jan 21 '20 at 07:25
  • My apologies. I did not know that I needed to provide proof of attempt. I did look through the whole web, and I was not able to find anything that resolves this dilemma, nor do I know how to put such a loop together. I will try to find something to demonstrate my attempt to figure out a solution. – Mamamia93 Jan 22 '20 at 02:36
  • At least you should shorten down your question to a specific part. I try to explain the issue: What you for now did is explaining your whole project, which is a way too broad to ask here. Try to break it into small parts and only ask exactly about the part you have issues with. And it is absolutely necessary to ask something, because you didn't. • Think about which steps you need to solve, actually a program will do more or less exactly the same steps like if you do it by hand. So start doing/thinking it by hand to find out your steps. Then ask about one step. More likely to get a answer then. – Pᴇʜ Jan 22 '20 at 06:56
  • I edited my post to a shorter and clearer post with a question on the step I need help with. I also added code that I found and manipulated to what I need, but still do not have it do exactly what I need. I hope this is a better post. – Mamamia93 Jan 22 '20 at 15:20
  • In your original document (Input sheet) - in which columns do you have "Account Name" / "Long Name" and "Amount" / "Agent Number" ? Is it **F and G** or **H and I**? 2 pictures show different results. – ZygD Jan 22 '20 at 16:26
  • Also, in the description you mention `G4`, but in the screenshot I see `H4` - which one is correct? – ZygD Jan 22 '20 at 16:35
  • I updated the snapshots for better clarity. Please let me know if that clarified your question @ZygD. Also, the goal is to get the code into the real sheets (the first set of snapshots). The second set of snapshots is the practice sheets for this experiment. The first cell for account numbers begin in E4 and is merged with F4. The second cell for the account numbers is H4 and I4 merged together. The practice sheets are there just to show you what the code resulted in. The main focus is the first set of snapshots. – Mamamia93 Jan 22 '20 at 18:18

2 Answers2

0

Try this. I did not use find method, because you are likely to do many searches on the same dataset. So I loaded it into an array which will be searched instead of a range object (it is faster).

One thing to have in mind - before running it, you need to DELETE all the account numbers in Proof sheet.

Sub loopything()

  Dim wsInfoSheet As Worksheet
  Dim wsProofSheet As Worksheet
  Dim lngLastRow As Long
  Dim r As Long
  Dim sAcct As String
  Dim lngNextRow As Long
  Dim sLongName As String

  Dim arrRef() As Variant
  Dim arrNames() As String
  Dim i As Long
  Dim lngRowInNames As Long
  Dim lngFoundName As Long

  Set wsInfoSheet = ThisWorkbook.Sheets("Info Sheet")
  Set wsProofSheet = ThisWorkbook.Sheets("Proof")

  ' Will be used in the Proof sheet
  lngNextRow = 4 ' waiting to adjust to normal table format

  arrRef = wsProofSheet.Range("A200:L79000").Value
  ReDim arrNames(1 To UBound(arrRef, 1) + 1, 1 To 2)

  With wsInfoSheet

    lngLastRow = 30 ' .cells(.rows.count, "E").end(xlup).row

    lngRowInNames = 1
    For r = 2 To lngLastRow
      sAcct = .Cells(r, "E")
      'lookup for sAcct in arrRef
      For i = 1 To UBound(arrRef, 1)
        If arrRef(i, 1) = sAcct Then
          sLongName = arrRef(i, 2) '(row i, column 2 from arrRef)
          arrNames(lngRowInNames, 1) = sLongName
          arrNames(lngRowInNames, 2) = lngNextRow
          lngRowInNames = lngRowInNames + 1
          Exit For
        End If
      Next
      'lookup for sLongName in arrNames
      For i = 1 To UBound(arrNames, 1)
        If arrNames(i, 1) = sLongName Then
          lngFoundName = i
          Exit For
        End If
      Next

      'if the name is new
      If arrNames(lngFoundName + 1, 1) = "" Then
        wsProofSheet.Cells(lngNextRow, "E") = sAcct
        wsProofSheet.Cells(lngNextRow, "B") = sLongName
        lngNextRow = lngNextRow + 8   ' would be nicer to just add one row (see  first note)
      'if the name already exists
      Else
        wsProofSheet.Cells(arrNames(lngFoundName, 2), wsProofSheet.Cells(arrNames(lngFoundName, 2), wsProofSheet.Columns.Count).End(xlToLeft).Column + 3) = sAcct
      End If

    Next 'r

  End With

End Sub
ZygD
  • 22,092
  • 39
  • 79
  • 102
  • I was able to fix it, but what line in the code are you looking for the "long name" associated with the account number? The range containing the account numbers and the long name along with the account name is located between A200 and L79000. It is not pulling the long name but rather the account name. The account name is in column B (B200: B7900) and the long name is in column L (L200: L79000). The account number to link to the long name is in column A (A200:A79000) all of which are on the Proof sheet. Other than that, the code seems to be working. – Mamamia93 Jan 22 '20 at 19:23
  • Nevermind. I was able to fix it. The issue was 'sLongName = arrRef(i, 2) '(row i, column 2 from arrRef)'. Instead of 2 I put 12 where the information I needed was sitting. Thank you so much! the code works perfectly! I am going to run a couple of more tests and I will let you know how it turns out. – Mamamia93 Jan 22 '20 at 19:35
  • How can I trigger the code to run when I input data on the Input sheet? I already have a Worksheet_Change sub for something else on the input sheet. I placed the code you created in the proof sheet. Any tips? @ZygD – Mamamia93 Jan 22 '20 at 20:56
  • First, you may edit my code in this site - paste the version which works for you. Then, I may be able to edit it again, so that you don't need to delete all the account numbers before running the code. Then, if you really want, you could put a call to this sub into `Worksheet_Change` event. [Here](https://stackoverflow.com/questions/29046139#29055996) you can find an example where some code runs only when specific cells are changed in the sheet. The key line is `If Not Intersect(Target, Me.Range("G1")) Is Nothing Then` - it makes code run when G1 is changed. – ZygD Jan 22 '20 at 21:27
  • So, looking at the post, do I input this code on the proof sheet or the info input sheet? Currently, the code is on the former sheet because there is already a macro with 'Worksheet_Change'. So, based on a change within the entire row on the info input sheet your code should run. Is there a way to call based on range and not a specific cell? As you know, there are multiple cells that will change. – Mamamia93 Jan 22 '20 at 21:39
  • `Worksheet_Change` is automatically run when any cell in the sheet is changed. If you change many cells, you still perform it one-by-one, so the code still runs after every change. This line makes it more controllable, but still, it works for every change for every cell in scope. You can make `Range("A1:A2")`, but it will work for every cell individually. This is why I do not like big recalculations coming from VBA after a single change. You may get errors from VBA, because some values may be missing (not yet inputed) while you code is already running, because one cell was changed. – ZygD Jan 23 '20 at 05:31
  • Hello @ZygD, after amending your code, I am so grateful for your help in providing a functioning code. I am going to post the code that I am using along with another macro inside a `Worksheet_Change` event in order for you to see what I am using. – Mamamia93 Jan 23 '20 at 17:40
  • It's probably wiser to create a new question – ZygD Jan 23 '20 at 17:45
  • I posted the code for you to take a look at what I am using from what you amended. – Mamamia93 Jan 23 '20 at 17:53
0

So, this is currently the code that I am using. I embedded the code inside a change event when a cell within a range changes. But, I was interested in knowing if there is a way that the code can ensure that if the account number is already in a cell it should not post the same number again in the next cell on the same row. Meaning, every time there is a change in the range, the macro runs anew and places the numbers repetitively. I assume I need to put a reset somewhere in the code but I do not know how or where.

Sub worksheet_Change(ByVal target As Range)

If Not Application.Intersect(target, Range("D2:D30")) Is Nothing Then
Application.EnableEvents = False
Dim wsInfoSheet As Worksheet
Dim wsProofSheet As Worksheet
Dim lngLastRow As Long
Dim r As Long
Dim sAcct As String
Dim lngNextRow As Long
Dim sLongName As String

Dim arrRef() As Variant
Dim arrNames() As String
Dim i As Long
Dim lngRowInNames As Long
Dim lngFoundName As Long

Set wsInfoSheet = ThisWorkbook.Sheets("Info Input")
Set wsProofSheet = ThisWorkbook.Sheets("Proof")

'Will be used in the Proof sheet
lngNextRow = 4 ' waiting to adjust to normal table format

arrRef = wsProofSheet.Range("A199:L79000").Value
ReDim arrNames(1 To UBound(arrRef, 1) + 1, 1 To 2)

With wsInfoSheet

lngLastRow = .Cells(.Rows.Count, "E").End(xlUp).Row

lngRowInNames = 1
For r = 2 To lngLastRow
  sAcct = .Cells(r, "E")
  'lookup for sAcct in arrRef
  For i = 1 To UBound(arrRef, 1)
    If arrRef(i, 1) = sAcct Then
      sLongName = arrRef(i, 12) '(row i, column 2 from arrRef)
      arrNames(lngRowInNames, 1) = sLongName
      arrNames(lngRowInNames, 2) = lngNextRow
      lngRowInNames = lngRowInNames + 1
      Exit For
    End If
  Next
  'lookup for sLongName in arrNames
  For i = 1 To UBound(arrNames, 1)
    If arrNames(i, 1) = sLongName Then
      lngFoundName = i
      Exit For
    End If
  Next

  'if the name is new
  If arrNames(lngFoundName + 1, 1) = "" Then
    wsProofSheet.Cells(lngNextRow, "E") = sAcct
    wsProofSheet.Cells(lngNextRow, "B") = sLongName
    lngNextRow = lngNextRow + 8   ' would be nicer to just add one row (see  first note)
  'if the name already exists
  Else
    wsProofSheet.Cells(arrNames(lngFoundName, 2), wsProofSheet.Cells(arrNames(lngFoundName, 2), wsProofSheet.Columns.Count).End(xlToLeft).Column + 3) = sAcct
  End If

Next 'r

End With
Application.EnableEvents = True
End If

Dim iCell As Range
If Not Application.Intersect(target, Range("A2:A30")) Is Nothing Then
Application.EnableEvents = False
For Each iCell In Range("A2:A30")
    If iCell.Address = target.Address Then
        Range("C" & iCell.Row).ClearContents
        Range("D" & iCell.Row).ClearContents
        Range("I" & iCell.Row).ClearContents
    End If
Next iCell

End If
Application.EnableEvents = True
End Sub
Mamamia93
  • 25
  • 6
  • This may become deleted before I can take a look. It is worth posting another question. – ZygD Jan 23 '20 at 18:08
  • Ok @ZygD. I will post a new question. – Mamamia93 Jan 23 '20 at 18:09
  • @ZygD I created another question [Link](https://stackoverflow.com/questions/59884884/need-to-prevent-loop-from-restarting-within-a-worksheet-change-event) – Mamamia93 Jan 23 '20 at 18:35
  • Regarding your second part (A2:A30), you can remove all the `For Each` block and replace it with this one line: `Intersect(Target.EntireRow, Range("C:D,I:I")).ClearContents` – ZygD Jan 24 '20 at 12:36