1

I have an Excel 2013 worksheet where each column has a header row, and then the word "DIRECT" in some or all of the cells. No other data exists in the columns, just "DIRECT" or blanks. No columns are blank, they all have "DIRECT" at least once.

I'm looking for a macro that does the following:

  • Adds a new top row
  • Ignores the original header row, but gets a count of the cells with "DIRECT" in them
  • Puts that number in the corresponding new top cell for each column
  • Does the above actions for each column in the worksheet
  • Works regardless of the last column or row with data (I have to run this on several different-sized worksheets)

I recorded a macro that gets close, but it has two problems:

  1. It adds the COUNTA data out to the last row of the workbook, which isn't needed (the populated columns will be a couple hundred, not thousands)
  2. It references a specific cell range, so could cut off data for sheets with more rows
Sub AddColumnCountsRecorded()
'
' AddColumnCounts Macro
'

'
    Rows("1:1").Select
    Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
    Range("J1").Select
    ActiveCell.FormulaR1C1 = "=COUNTA(R[2]C:R[15]C)"
    Range("J1").Select
    Selection.Copy
    Range(Selection, Selection.End(xlToRight)).Select
    ActiveSheet.Paste
End Sub

If it helps:

  • Column "A" can determine the last row where data could be (that's the "username" column", so no blanks there) - although this last row will also change from sheet to sheet.

  • Row 2 (the header row) can determine the last column where data could be - it has no blank columns; in each column, at least one cell will have the word "DIRECT".

Any advice on editing the existing macro or concocting a new one from scratch would be greatly appreciated!

Thanks!

UPDATE:

Much thanks to Scott, here's what I ended up with - this adds the non-blank cell count to the active worksheet and stops at the last row with data in it. I just call it directly, without the 2nd section of code proposed below:

Sub AddColumnCountsRecorded()

    With ActiveSheet

        .Rows("1:1").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove

        Dim lRow As Long, lCol As Long
        lRow = .Range("A" & .Rows.Count).End(xlUp).Row
        lCol = .Cells(2, .Columns.Count).End(xlToLeft).Column

        .Range(.Cells(1, 2), .Cells(1, lCol)).FormulaR1C1 = "=COUNTA(R[2]C:R[" & lRow & "]C)"

    End With

End Sub
Community
  • 1
  • 1
3Jake
  • 51
  • 1
  • 2
  • 11
  • Read into [how to avoid using `.Select`](http://stackoverflow.com/questions/10714251/how-to-avoid-using-select-in-excel-vba-macros), it'll help tighten and speed up your macro. – BruceWayne Jul 11 '16 at 18:58

1 Answers1

1

Give this a shot. I made a separate sub that you can pass the worksheet reference too.

Sub AddColumnCountsRecorded(ws As Worksheet)

    With ws

        .Rows("1:1").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove

        Dim lRow As Long, lCol As Long
        lRow = .Range("A" & .Rows.Count).End(xlUp).Row
        lCol = .Cells(2, .Columns.Count).End(xlToLeft).Column

        .Range(.Cells(1, 2), .Cells(1, lCol)).FormulaR1C1 = "=COUNTA(R[2]C:R[" & lRow & "]C)"

    End With

End Sub

Call it like this:

Sub ColumnCount()

    AddColumnCountsRecorded Worksheets("Sheet1")

End Sub
Scott Holtzman
  • 27,099
  • 5
  • 37
  • 72
  • Thanks for the help Scott; I gave this a shot but it only added counts to the first and second columns? I'm awfully green when it comes to macros, so maybe it's me - here’s what I'm doing: - I pasted the “Sub AddColumnCountsRecorded(ws As Worksheet)” code block into a new module in the "MS VBA for Applications" window - I pasted the “Sub ColumnCount()” into a 2nd new module - I changed “Sheet1” to the name of the sheet I was working on - From the sheet, I went Developer Tab > Macros > and ran the macro named “ColumnCount” Is there anything I should be doing differently? – 3Jake Jul 11 '16 at 21:24
  • @3Jake - no. I messed up the syntax on `lCol`. Try the code with the edit I just made. – Scott Holtzman Jul 11 '16 at 21:26
  • Perfect! One follow-up question, is there a way to make this run on whatever sheet is active, instead of having to reference "Sheet1" / the name of the sheet I'm looking at? – 3Jake Jul 11 '16 at 21:32
  • Change `ws` to `ActiveSheet` in the `AddColumnCountsRecorded` Sub and remove the argument. – Scott Holtzman Jul 11 '16 at 22:04
  • Thanks Scott - sorry, but I'm not totally clear on your recommendation. Like this? `Sub AddColumnCountsRecorded(ActiveSheet As Worksheet)` and then remove `With ws`? In the "ColumnCount" sub, does `AddColumnCountsRecorded Worksheets("Sheet1")` need to change to incorporate the active sheet as well? – 3Jake Jul 12 '16 at 18:04
  • @3Jake .... Change the `With ws` to `With ActiveSheet` in the `AddColumnCountsRecorded`. Also Change `AddColumnCountsRecorded(ws As Worksheet)` to `AddColumnCountsRecorded()` and just call that sub directly from whatever sheet you want to run it from. Or, and perhaps this is easier, you can call the sub this way as well (leaving it untouched): `AddColumnCountsRecorded ActiveSheet` – Scott Holtzman Jul 12 '16 at 18:07
  • 1
    That's the ticket! Thanks again Scott, I feel like I learned a thing or two about macros here as well - you're the bomb! I'll update my original comment to show what I ended up with. – 3Jake Jul 13 '16 at 14:08