1

I have some data in column A like this

ColA
Z
A

Z
A

Z
A
A
B
B
B

Z
B
B

Z
C
C
C
D
D

I want to print in column B

  • "0" if cell in A = "Z"

  • empty when cell in A is empty

  • When a group begins for example with letter A, then all next A's should be marked with 1.

  • When a next group begins, i.e. with letter B, then mark all following B's with 2,

  • When begins a new group i.e with letter C, mark with value 1 again and so on.

  • the values in column A are not letters in alphabetical sequence. Is only an example. I only know the value of "Z", the groups could have any string

This is, alternate assigning values 1 and 2 for each new group. I hope make sense.

This is my current code

Sub t1()
Dim dict As Object

Set dict = CreateObject("Scripting.Dictionary")

For i = 1 To 24
    If Cells(i, "A") = "Z" Then
        Cells(i, "B") = "0"
    ElseIf Cells(i, "A") <> "Z" And Cells(i, "A") <> "" Then
        counter = counter + 1
        dict.Add Key:=Cells(i, "A"), Item:=1
        
        If Not dict.Exists(Cells(i, "A")) Then
            If counter Mod 2 = 1 Then
                Cells(i, "B") = "1"
            Else
                Cells(i, "B") = "2"
            End If
        End If
    End If
Next
End Sub

My curent output in column B and my expected output in Column Cells

ColA ColB    ColC
Z      0     0
A      1     1
           
Z      0     0
A      2     1
           
Z      0     0
A      1     1
A      2     1
B      1     2
B      2     2
B      1     2
           
Z      0     0
B      2     2
B      1     2
           
Z      0     0
C      2     1
C      1     1
C      2     1
D      1     2
D      2     2

Maybe someone could help me. Thanks

Ger Cas
  • 2,188
  • 2
  • 18
  • 45
  • Why is the value of B after Z1 2? – Dy.Lee Jul 25 '20 at 03:16
  • Actually all values are "Z", the Z1 was a typo. I fixed it. – Ger Cas Jul 25 '20 at 03:51
  • Quick question. Why is the value of "B", 2 in row 14 and 15? Should it not be "1". Is it a typo? If not, then d you mean that if the letters get repeated then it should retain it's original value? If yes then I will have to amend the formula that I gave you below... – Siddharth Rout Jul 25 '20 at 13:15

3 Answers3

3

Hello, no. Imagine Z and empty values don't exist. Then we have this input A,A,A,B,C,C,C,C,D,D,A,E,E,E,B,A. I only want the alternation between 1 and 2 for each new group. Doesn't matter if A has appeared before, should be taken as new group. With this input the, output should be 1,1,1,2,1,1,1,1,2,2,1,2,2,2,1,2 – Ger Cas 9 hours ago

Try this crazy formula (I am sure this can be made simpler). Put this in cell B2 as shown in the screenshot below

=IF(ISBLANK(A2),"",IF(A2="Z",0,IF(A2=A1,B1,IF(OR(A1="Z",ISBLANK(A1)),IF(ISERROR(INDEX($A$1:$A1,AGGREGATE(14,6,ROW($1:1)/($A$1:$A1=A2),1))),IFERROR((A1+1),1),IF(OR(INDEX($A$1:$A1,AGGREGATE(14,6,ROW($1:1)/($A$1:$A1=A2),1)+1)="Z",INDEX($A$1:$A1,AGGREGATE(14,6,ROW($1:1)/($A$1:$A1=A2),1)+1)=""),INDEX(B:B,MATCH(A2,$A$1:$A1,0),1),1)),IF(B1=1,2,IF(B1=2,1,""))))))

Let's say you data looks like this

enter image description here

Explanation

Following a sequence of checks in the below order

  1. ISBLANK(A2): Check if the cell is empty. If it is empty then keep output blank.
  2. A2="Z": Check if the cell has "Z". Output 0.
  3. A2<>A1: Check if the value changes in column A. If it doesn't then pick up value from top. If it changes then see next check
  4. Then we use INDEX with AGGREGATE() to do a reverse match to find the occurence of the value and if a match is found then pull the respective value from Column B
Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
  • Great solution and this can be easily used in VBA too. By the way, the results in row 15 and 16 should be 2 according to the logic of the OP. – YasserKhalil Jul 25 '20 at 11:52
  • I assumed that it is a typo. If not then it can be easily fixed. Posted a query under the question :) – Siddharth Rout Jul 25 '20 at 13:16
  • Edited original post trying to explain better the logic. Thanks – Ger Cas Jul 25 '20 at 15:31
  • @GerCas: Ok quick question. If you had `Z,C,C,A,D,D` instead of `Z,C,C,C,D,D` in the above scenario then what would `0,1,1,1,2,2` change to? The reason why I ask is because `C` becomes `1` as per your logic but `A` already has a value of `1` from above so the output in my opinion should be `0 (For Z), 1(For C), 1(For C), 1(For A), 2(For D), 2(For D),` If this is correct, then I have the formula ready for you – Siddharth Rout Jul 26 '20 at 08:38
  • Hello, if A already appeared and has value 1, but appears again below as in your example, should be taken as a new group. The alternation between 1 and 2 happens when there is a change of groups. I hope make sense – Ger Cas Jul 26 '20 at 12:03
  • So, even when A had value 1 before, if appears again after the C's should be for Z,C,C,A,D,D = 0,1,1,2,1,1 – Ger Cas Jul 26 '20 at 12:09
  • @GerCas: Why is D one? should it not be 3? 0,1,1,2,3,3 for `Z,C,C,A,D,D` – Siddharth Rout Jul 26 '20 at 21:15
  • Hello, no. Imagine Z and empty values don't exist. Then we have this input A,A,A,B,C,C,C,C,D,D,A,E,E,E,B,A. I only want the alternation between 1 and 2 for each new group. Doesn't matter if A has appeared before, should be taken as new group. With this input the, output should be 1,1,1,2,1,1,1,1,2,2,1,2,2,2,1,2 – Ger Cas Jul 26 '20 at 21:39
  • @GerCas: Check the post now. Does it work as per your specifications? :) – Siddharth Rout Jul 28 '20 at 06:01
  • @SiddharthRout Excellent. Is an anaconda formula hehe, but it seems to work and print correct output. I think this was a headache for you. Thanks dor take of your time to help. – Ger Cas Jul 28 '20 at 16:07
  • 1
    @GerCas: No it was not a heahache. I was simply not able to give it time. lot of work on professional front. I am sure the formula can be optimized... – Siddharth Rout Jul 28 '20 at 16:37
2

Try this code

Sub Test()
    Dim r As Range, c As Range, s As String, n As Long, x As Long, y As Long
    With ThisWorkbook.Worksheets("Sheet1")
        .Columns(2).ClearContents
        For Each r In .Columns(1).SpecialCells(2).Areas
            n = 0: x = 0
            For Each c In r
                If c.Value = "Z" Then
                    c.Offset(, 1).Value = 0
                Else
                    If c.Value <> s And c.Address = r(2).Address Then y = 0
                    If c.Value <> c.Offset(-1).Value And c.Address = r(2).Address And s <> "" Then
                        If c.Value = s Then c.Offset(, 1).Value = y: GoTo Skipper
                    End If
                    If c.Value <> c.Offset(-1).Value Then
                        n = n + 1: c.Offset(, 1).Value = n + y
                    Else
                        c.Offset(, 1).Value = c.Offset(-1, 1).Value
                    End If
                End If
Skipper:
                x = x + 1
                If r.Cells.Count = x Then s = c.Value: y = c.Offset(, 1).Value
            Next c
        Next r
    End With
End Sub

Here's snapshot enter image description here

YasserKhalil
  • 9,138
  • 7
  • 36
  • 95
  • The code ran well on my side. Can you debug.print the addresses of c and r(2)? – YasserKhalil Jul 25 '20 at 07:35
  • Use F8 to follow the lines of the code and at the line of error, type in the immediate window `?c.address` and `?r(2).address` to see what's wrong. – YasserKhalil Jul 25 '20 at 07:48
  • Maybe other members test the code and tell us if the code works or not. That's weird. – YasserKhalil Jul 25 '20 at 11:50
  • I don't know what's wrong exactly with you. I suppose sheet name is "Sheet1" and the data starts at A1 ..If the problem is still there, upload the workbook you are working on to have a look. – YasserKhalil Jul 26 '20 at 07:01
  • Hi, I tested in another machine and it works. Thank you. The only issue is that if you continue adding more letters in column A, the output doesn´t alternate between 1 and 2, but continues incrementing to 3, 4, 5, etc. – Ger Cas Jul 27 '20 at 00:54
0

Try,

Sub test()
    Dim vDB, vR()
    Dim Dict As Object
    Dim i As Long, r As Long
    Dim cnt As Integer
    
    vDB = Range("a1", Range("a" & Rows.Count).End(xlUp))
    Set Dict = CreateObject("Scripting.Dictionary")
    r = UBound(vDB, 1)
    
    ReDim vR(1 To r, 1 To 1)
    For i = 1 To r
        If vDB(i, 1) = "" Then
            cnt = 0
            Set Dict = CreateObject("Scripting.Dictionary") '
        Else
            If vDB(i, 1) Like "Z*" Then
                vR(i, 1) = 0
            Else
                If Dict.Exists(vDB(i, 1)) Then
                    vR(i, 1) = Dict(vDB(i, 1))
                Else
                    cnt = cnt + 1
                    Dict.Add vDB(i, 1), cnt
                    vR(i, 1) = Dict(vDB(i, 1))
                End If
            End If
        End If
    Next i
    Range("b1").Resize(r) = vR
End Sub

Result image

enter image description here

Dy.Lee
  • 7,527
  • 1
  • 12
  • 14
  • Thanks for the help. Your output is correct from row 1 to row 14 and from row 17 to 23. Row 15:16 should have value 2. – Ger Cas Jul 25 '20 at 03:56
  • @GerCas as for the row 19 to 21 which has the value C, it is supposed as for your logic to be 3 not 1 as in the output you posted!! And D in row 22 and 23 to be 4 – YasserKhalil Jul 25 '20 at 04:18
  • @YasserKhalil in the output I show in my post the values for groups of consecutive letters change between 1 and 2, not from 1, 2, 3,4.... For Z would be 0, for groups alternate between 1 and 2. I hope make sense – Ger Cas Jul 25 '20 at 04:23