VBA to classify items in a report

alfordtp

Board Regular
Joined
Oct 3, 2008
Messages
62
I have a report that is generated automatically in the following format:

1APPLE 1
2APPLE 2
3APPLE 3
CLASS AFRUIT
5BLUE 5
6BLUE 6
7BLUE 7
8BLUE 8
REP12
CLASS BCOLOR
11CIRCLE 11
12CIRCLE 12
CLASS CSHAPE

<tbody>
</tbody>

This goes on for around 10,000 rows. Where it says REP12 is where the report page break is and REP12 is the report number. Random placement.

I want to quickly add the class to column A of the table for each group. For example, the first group would read:

CLASS A1APPLE 1
CLASS A2APPLE 2
CLASS A3APPLE 3

<tbody>
</tbody>


As you can see, the way the report is originally formatted, there are spaces and sometimes other information in between the classes and item numbers.

Any thoughts as to which technique to write this VBA?
 

Excel Facts

Ambidextrous Undo
Undo last command with Ctrl+Z or Alt+Backspace. If you use the Undo icon in the QAT, open the drop-down arrow to undo up to 100 steps.
alfordtp,

Sample raw data:


Excel 2007
ABCDEFG
11APPLE 1
22APPLE 2
33APPLE 3
4
5CLASS AFRUIT
6
75BLUE 5
86BLUE 6
97BLUE 7
108BLUE 8
11
12REP12
13
14CLASS BCOLOR
15
1611CIRCLE 11
1712CIRCLE 12
18
19CLASS CSHAPE
20
Sheet1


After the macro using two arrays in memory:


Excel 2007
ABCDEFG
11APPLE 1CLASS A1APPLE 1
22APPLE 2CLASS A2APPLE 2
33APPLE 3CLASS A3APPLE 3
4CLASS B5BLUE 5
5CLASS AFRUITCLASS B6BLUE 6
6CLASS B7BLUE 7
75BLUE 5CLASS B8BLUE 8
86BLUE 6CLASS C11CIRCLE 11
97BLUE 7CLASS C12CIRCLE 12
108BLUE 8
11
12REP12
13
14CLASS BCOLOR
15
1611CIRCLE 11
1712CIRCLE 12
18
19CLASS CSHAPE
20
Sheet1


Please TEST this FIRST in a COPY of your workbook (always make a backup copy before trying new code, you never know what you might lose).

1. Copy the below code
2. Open your NEW workbook
3. Press the keys ALT + F11 to open the Visual Basic Editor
4. Press the keys ALT + I to activate the Insert menu
5. Press M to insert a Standard Module
6. Where the cursor is flashing, paste the code
7. Press the keys ALT + Q to exit the Editor, and return to Excel
8. To run the macro from Excel press ALT + F8 to display the Run Macro Dialog. Double Click the macro's name to Run it.

Code:
Sub ClassifyItems()
' hiker95, 10/09/2014, ME810818
Dim oa As Variant
Dim a As Variant, o As Variant
Dim i As Long, j As Long
Dim lr1 As Long, lr2 As Long, h As String
Application.ScreenUpdating = False
Columns("E:G").ClearContents
lr1 = Cells(Rows.Count, "B").End(xlUp).Row
oa = Range("A1:B" & lr1)
With Range("A1:A" & lr1)
  .Value = Evaluate("IF(ROW(),SUBSTITUTE(" & .Address & ",""REP12"",""""),"""")")
End With
Range("A1:B" & lr1).SpecialCells(xlCellTypeBlanks).Delete Shift:=xlUp
lr2 = Cells(Rows.Count, "B").End(xlUp).Row
a = Range("A1:B" & lr2).Value
ReDim o(1 To lr2, 1 To 3)
For i = lr2 To 1 Step -1
  If InStr(a(i, 1), "CLASS") Then
    h = a(i, 1)
  Else
    j = j + 1
    o(j, 1) = h
    o(j, 2) = a(i, 1)
    o(j, 3) = a(i, 2)
  End If
Next i
Range("A1:B" & lr1) = oa
Range("E1:G" & lr2) = o
lr2 = Cells(Rows.Count, "E").End(xlUp).Row
Range("H1").Value = lr2
With Range("H2:H" & lr2)
  .FormulaR1C1 = "=R[-1]C-1"
  .Value = .Value
End With
Range("E1:H" & lr2).Sort key1:=Range("H1"), order1:=1
Range("H1:H" & lr2).ClearContents
Columns(5).Resize(, 3).AutoFit
Application.ScreenUpdating = True
End Sub

Before you use the macro with Excel 2007 or newer, save your workbook, Save As, a macro enabled workbook with the file extension .xlsm

Then run the ClassifyItems macro.
 
Upvote 0
For the original sample data in post #1, can you show the complete result you want?
 
Upvote 0
alfordtp,

Sample raw data in the active worksheet:


Excel 2007
ABC
11APPLE 1
22APPLE 2
33APPLE 3
4
5CLASS AFRUIT
6
75BLUE 5
86BLUE 6
97BLUE 7
108BLUE 8
11
12REP12
13
14CLASS BCOLOR
15
1611CIRCLE 11
1712CIRCLE 12
18
19CLASS CSHAPE
20
Sheet1


After the macro using two arrays in memory:


Excel 2007
ABC
1CLASS A1APPLE 1
2CLASS A2APPLE 2
3CLASS A3APPLE 3
4
5CLASS AFRUIT
6
7CLASS B5BLUE 5
8CLASS B6BLUE 6
9CLASS B7BLUE 7
10CLASS B8BLUE 8
11
12REP12
13
14CLASS BCOLOR
15
16CLASS C11CIRCLE 11
17CLASS C12CIRCLE 12
18
19CLASS CSHAPE
20
Sheet1


Please TEST this FIRST in a COPY of your workbook (always make a backup copy before trying new code, you never know what you might lose).

1. Copy the below code
2. Open your NEW workbook
3. Press the keys ALT + F11 to open the Visual Basic Editor
4. Press the keys ALT + I to activate the Insert menu
5. Press M to insert a Standard Module
6. Where the cursor is flashing, paste the code
7. Press the keys ALT + Q to exit the Editor, and return to Excel
8. To run the macro from Excel press ALT + F8 to display the Run Macro Dialog. Double Click the macro's name to Run it.

Code:
Sub ClassifyItemsV2()
' hiker95, 10/10/2014, ME810818
Dim a As Variant, b As Variant
Dim r As Long, lr As Long, h As String
Application.ScreenUpdating = False
lr = Cells(Rows.Count, "C").End(xlUp).Row
b = Range("B1:C" & lr).Value
ReDim a(1 To lr, 1 To 1)
Columns(1).ClearContents
For r = lr To 1 Step -1
  If b(r, 1) = "" Or b(r, 1) = "REP12" Then
    'do nothing
  ElseIf InStr(b(r, 1), "CLASS") Then
    h = b(r, 1)
  ElseIf IsNumeric(b(r, 1)) Then
    a(r, 1) = h
  End If
Next r
Range("A1").Resize(lr, 1).Value = a
Columns(1).AutoFit
Application.ScreenUpdating = True
End Sub

Before you use the macro with Excel 2007 or newer, save your workbook, Save As, a macro enabled workbook with the file extension .xlsm

Then run the ClassifyItemsV2 macro.
 
Upvote 0
This looks like what I need.
In that case you might also like to have a look at this version. It has some slight differences to hiker's code, including ..

1. Mine assumes that column A is already empty per your sample whereas hiker's does not.

2. Mine relies on the last row (as determined by looking at column C) being a "Class" row whereas hiker's does not.

3. Mine does not rely on the Class labels containing the word "CLASS".

4. Mine does not rely on the page break text containing anything in particular (eg "REP12").

5. Mine does not rely on the rows to be labelled containing numerical values in column B.

6. On my machine and testing about 10,000 rows, this code was about one third faster (though with both codes taking less than one tenth of a second, speed shouldn't be a major issue for you :)).

Rich (BB code):
Sub Add_Class()
  Dim a As Variant
  Dim i As Long
  Dim Clss As String
  Dim b As Boolean
  
  a = Range("A1", Range("C" & Rows.Count).End(xlUp)).Value
  i = UBound(a, 1)
  Do
    If b Then
      Do Until a(i, 3) = ""
        a(i, 1) = Clss
        i = i - 1
        If i = 0 Then
          Range("A1").Resize(UBound(a, 1)).Value = a
          GoTo PreExit
        End If
      Loop
    Else
      Clss = a(i, 2)
      i = i - 1
    End If
    Do While a(i, 3) = ""
      i = i - 1
    Loop
    b = Not b
  Loop Until i = 0
  
PreExit:
End Sub
 
Last edited:
Upvote 0

Forum statistics

Threads
1,214,424
Messages
6,119,407
Members
448,894
Latest member
spenstar

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top