Excel VBA Course
Excel VBA Course - From Beginner to Expert

200+ Video Lessons
50+ Hours of Video
200+ Excel Guides

Become a master of VBA and Macros in Excel and learn how to automate all of your tasks in Excel with this online course. (No VBA experience required.)

View Course

Gathering values from a sequence following rules

0

Hello,

I try to extract some values from a header, following specific rules which I tried to detail in the attached file

I started with this code below listed but it's not working at all and as I am a beginner I cannot advance. Can anyone support me?

Sub Options()

Dim i, j, k As Double

   Sheets("Sheet1").Select

          For i = 1 To 5

          x = ""

          For j = 3 To 23

          k = j + 1

          If k < 24 & Left(Cells(1, j).Value, 2) = Left(Cells(1, k).Value, 2) Then

          If (UCase(Cells(i, j).Value) = "X" & UCase(Cells(i, k).Value) = "") Or (UCase(Cells(i, j).Value) = "X" & UCase(Cells(i, k).Value) = "S") Or (UCase(Cells(i, j).Value) = "S" & UCase(Cells(i, k).Value) = "S") Or (UCase(Cells(i, j).Value) = "X" & UCase(Cells(i, k).Value) = "X") Or (Cells(i, j).Value <> "" & Cells(i, k).Value = "") Then x = x & " e " & Cells(1, j).Value

          ElseIf (UCase(Cells(i, j).Value) = "" & UCase(Cells(i, k).Value) = "X") Or (Cells(i, j).Value = "" & Cells(i, k).Value = "S") Then x = x & " t " & Cells(1, k).Value

          End If           

          Next j

          If x <> "" Then Cells(i, 26).Value = x

          Next i

  End Sub

Answer
Discuss

Answers

0
Selected Answer

Sebas

Here's a different approach which delivers an "exception report" i.e. only what's wrong with your data. Not sure if I have understood your rules correctly but...

In the attached revised file, under your table there is a button called "List errors". Clich that and the following macro (with a few guiding comments) will run:

Sub DefineClassColumns()

Dim j As Double, n As Double, Start As Double 'variable for counters and start of class code
Dim XCol As Double, SCol As Double, XRowl As Double, SRow As Double 'variables for class rows and columns
Dim Errors As String

Start = 3
' run through columns
For j = 3 To 23
    ' do things per code value
    XCol = WorksheetFunction.CountIf(Range(Cells(2, j), Cells(6, j)), "=X")
    SCol = WorksheetFunction.CountIf(Range(Cells(2, j), Cells(6, j)), "=S")

    Select Case XCol
        Case Is > 1
        Errors = Errors & vbCr & "Value error: >1 X for class " & Cells(1, j).Value

        Case Is = 1
        If SCol >= 1 Then
        Errors = Errors & vbCr & "Value error: S and X for class " & Cells(1, j).Value
        Else
        End If

        Case Is = 0
        If SCol > 1 Then Errors = Errors & vbCr & "Value error: >1 S for class " & Cells(1, j).Value

    End Select

    'find extent of each code class
    If Left(Cells(1, j).Value, 2) <> Left(Cells(1, j + 1).Value, 2) Then
        'do things per code class
        Errors = Errors & vbCr & "Class " & Left(Cells(1, j).Value, 2) & "- columns " & Start & ":" & j
        For n = 2 To 6
        XRow = WorksheetFunction.CountIf(Range(Cells(n, Start), Cells(n, j)), "=X")
        SRow = WorksheetFunction.CountIf(Range(Cells(n, Start), Cells(n, j)), "=S")

        Select Case XRow
            Case Is > 1
            Errors = Errors & vbCr & "    Class error: >1 X for ID/Code " & Cells(n, 2).Value

            Case Is = 1
            If SRow >= 1 Then Errors = Errors & vbTab & vbCr & "    Class error: S and X for ID/Code " & Cells(n, 2).Value

            Case Is = 0
            If SRow > 1 Then Errors = Errors & vbTab & vbCr & "    Class error: >1 S for ID/Code " & Cells(n, 2).Value

        End Select
          Next n
        'create start for next code class
        Start = j + 1

    End If

Next j

n = MsgBox(Errors, vbOKOnly, "Found...")

End Sub

It checks per column for errors then (when it sees a change in class of code) checks per class row for errors. 

All errors are collected in a string called "errors" which is displayed in a Message Box at the end of the macro. You could copy that string to a cell or the clipboard.

REVISION:

Further to comments below, the ...v0_b.xlsm revised file below reports only row errors and in the cells to the right of the data cells.

I've added variables for Top, Bottom (rows) and Start, Last (columns) of the data cells. That means you can expand it easily. Results are now recorded in the three columns to the right of column 23. I've also rationalised the Conditional Formatting for the data cells (and added a new rule to highlight any errors in the error column). 

Here's the revised code (with comments)

Sub DefineClassColumns()

Dim j As Integer, n As Integer 'variables for counters 
Dim Start As Integer, Last As Integer, Top As Integer, Bottom As Integer ' variables for data and start/end of class code
Dim XRow As Integer, SRow As Integer 'variables for class rows
Dim Errors As String

Start = 3 'set first column of data cells
Last = 23 'set last column of data cells
Top = 2 'set first row of data cells
Bottom = 6 'set last row of data cells

Range(Cells(Top, Last + 1), Cells(Bottom, Last + 3)).ClearContents 'clear results cell values only

' run through columns
For j = Start To Last   ' do things per code value

    For n = Top To Bottom
        Cells(n, j).Value = UCase(Cells(n, j).Value) ' make cell CAPS
        'record S and X entries (regardless of errors)
        If Cells(n, j).Value = "S" Then Cells(n, Last + 1).Value = Cells(n, Last + 1).Value & " " & Cells(Top - 1, j).Value
        If Cells(n, j).Value = "X" Then Cells(n, Last + 2).Value = Cells(n, Last + 2).Value & " " & Cells(Top - 1, j).Value
    Next n

    'find extent of each code class
    If Left(Cells(1, j).Value, 2) <> Left(Cells(1, j + 1).Value, 2) Then
        'do things per code class

        For n = Top To Bottom
        XRow = WorksheetFunction.CountIf(Range(Cells(n, Start), Cells(n, j)), "=X")
        SRow = WorksheetFunction.CountIf(Range(Cells(n, Start), Cells(n, j)), "=S")

        Select Case XRow
            Case Is > 1
            Cells(n, Last + 3).Value = Cells(n, Last + 3).Value & "Class error: >1 X for " & Left(Cells(Top - 1, j).Value, 2) & "**; "

            Case Is = 1
            If SRow >= 1 Then Cells(n, Last + 3).Value = Cells(n, Last + 3).Value & "Class error: S and X for " & Left(Cells(Top - 1, j).Value, 2) & "**; "

            Case Is = 0
            If SRow > 1 Then Cells(n, Last + 3).Value = Cells(n, Last + 3).Value & "Class error: >1 S for " & Left(Cells(Top - 1, j).Value, 2) & "**; "

        End Select
          Next n
        'create start for next code class
        Start = j + 1

    End If

Next j

MsgBox "Done!"

End Sub

Hope this helps.

Discuss

Discussion

Oops! Just noticed that my macro doesn't allow for lowercase entries (so it misses the error for c;ass RS19). Don't have the time to fix that now but will await you comment
John_Ru (rep: 6142) Sep 17, '21 at 4:13 am
Hello John_Ru,
Thanks a lot for your answer. The result is great.
I can see it summarizes for each class and returns:
1. Class Type - indicating the columns concerned
2. Class Error - indicating the markings in error(>1S, >X) per ID. I confirm that should check Upper&Lower case markings
3. Value Error - This check per column is not expected, I only need the check per row(for each ID)

Is it possible to have this result in a cell instead of Msg Box? 
Many thanks!
sebas14 (rep: 16) Sep 17, '21 at 1:09 pm
Thanks for selecting my Answer, Sebas.

The result can be written to a cell e.g. for B20, replace the line "n=MsgBox..." with
Cells(20, 2).Value = Errors


Don't have more time today but forn upper- and lowercase, it's easier if I convert all lowercase to uppercase- is that okay?
John_Ru (rep: 6142) Sep 17, '21 at 2:06 pm
Hello John_Ru, it is ok to convert lowercase to uppercase
The most important would be to have a dynamic result per line. Eg Cells(n, 20).Value = Errors  ' => should spot only the errors for line "n"
Would this be possible?

Many thanks
sebas14 (rep: 16) Sep 24, '21 at 12:41 pm
Sebas. Thanks for the comment.

I've forgotten about your problem but will see if I get time over the weekend to look at it and your comment above
John_Ru (rep: 6142) Sep 24, '21 at 12:47 pm
Sebas- see my revised Answer and second file.
John_Ru (rep: 6142) Sep 25, '21 at 7:51 am
Hi John_Ru
The revised code is top, provides the expected result
Much appreciate your effort!
sebas14 (rep: 16) Sep 27, '21 at 2:57 am
Thanks. We got there in the end! 
John_Ru (rep: 6142) Sep 27, '21 at 6:18 am
Add to Discussion


Answer the Question

You must create an account to use the forum. Create an Account or Login