0

I am not too sure how I should solve this issue, but there are two methods that make sense to me..

Some of the sheets in my workbook do not have headers, so I use the below code to insert a blank row and assign a header to column A - I know column A will always be employee number.

Sub insertRow()

    Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet
    Dim wkbk1 As Workbook

    Set wkbk1 = Workbooks("testWorkbook.xlsm")

    'Set sheets to be used in each workbook
    Set ws1 = wkbk1.Sheets("mySheet")
    Set ws2 = wkbk1.Sheets("hisSheet")
    Set ws3 = wkbk1.Sheets("herSheet")

    wkbk1.Activate

    ws1.Range("A1").EntireRow.Insert
    ws1.Range("A1").Value = "Employee Number"

    ws2.Range("A1").EntireRow.Insert
    ws2.Range("A1").Value = "Employee Number"

    ws3.Range("A1").EntireRow.Insert
    ws3.Range("A1").Value = "Employee Number"

End Sub

The below code deletes columns based on the header name.

Sub ManipulateSheets()

    Dim a As Long, w As Long
    Dim keepCols As Variant
    Dim wkbk1 As Workbook

    Set wkbk1 = Workbooks("testWorkbook.xlsm")

    keepCols = Array("Employee Number", "Status")

    wkbk1.Activate

    With wkbk1

        For w = 1 To .Worksheets.count

            With Worksheets(w)

                For a = .Columns.count To 1 Step -1

                    If UBound(Filter(keepCols, .Cells(1, a), True, vbTextCompare)) < 0 Then _
                            .Columns(a).EntireColumn.Delete

                Next a

            End With

        Next w

    End With

End Sub

The issue is this:

The 3 sheets that I insert a row in and set the column header for column A to Employee Number, still has empty headers for the remainder of the row.. So when I run the code above to delete the columns, nothing happens on these 3 sheets as there is no data to compare to in the header.

So the two options I thought would work are:

  1. Find the lastColumn and insert text into the cells between column A and the lastColumn

  2. Find the lastColumn and include a criteria in the if statement that looks for blank cells as well as non-matching headers

I got the code to find the lastColumn here:

Excel VBA- Finding the last column with data

Sub findColumn()

    Dim rLastCell As Range
    Dim i As Long
    Dim MyVar As Variant
    Dim ws1 As Worksheet
    Dim wkbk1 As Workbook
    i = 2

    Set wkbk1 = Workbooks("testWorkbook.xlsm")

    Set ws2 = wkbk1.Sheets("ws1")

    Set rLastCell = ws2.Cells.Find(What:="*", After:=ws2.Cells(1, 1), LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False)

End Sub

I'm thinking of a Do While Loop along the lines of the below:

Do While (MyVar1 >= 2 And MyVar1 < rLastCell.Column)



Loop
Eitel Dagnin
  • 959
  • 4
  • 24
  • 61
  • Are you trying to delete empty columns in the range as well? – QHarr May 09 '18 at 10:58
  • @QHarr No, not empty columns. I need to delete all columns that do not contain the headers "Employee Number" or "Status". But these 3 worksheets do not contain headers, so no columns are deleted even though there should be a few columns deleted. – Eitel Dagnin May 09 '18 at 11:01
  • If there is no header how would the correct columns to delete be determined in those sheets? – QHarr May 09 '18 at 11:02
  • @QHarr So that's the issue. That's why I was thinking of some code that would determine the lastColumn that has data, then scan row 1 until lastColumn and if a cell is empty in row 1, I insert some text and when I run the code to delete the columns, it would have text to compare to. – Eitel Dagnin May 09 '18 at 11:07
  • How would you determine which columns to add the text to if the header positions are not fixed? Conversely, if they are fixed you could modify your array to the column numbers to keep. – QHarr May 09 '18 at 11:34
  • @QHarr perhaps something like this: Find the last column that has data in it; Identify the column (lets assume column E) - at this point, we know from column A - E there is data in those columns; Set a loop from cell B1 - cell E1 to check if the cells are blank or not (I say cell B1 because I know cell A1 will contain "Employee Number"); if the cell is blank, insert the text "blank"; When I execute the macro that check column headers, it would therefore be able to check that from column B - E needs to be deleted because it has text and doesn't match the required text in the array. – Eitel Dagnin May 09 '18 at 11:51
  • My code below would do the same thing. See the For Each rng In Intersect(.Rows(1), .UsedRange) and combine with the <>0 test. – QHarr May 09 '18 at 11:52

1 Answers1

1

You could change the condition to

IsError(Application.Match(rng.Value, keepCols, 0)) 

That picks up all non-matching items.

Note:

For Each rng In Intersect(.Rows(1), .UsedRange)

The above is going to loop through the used range of row 1 in the selected sheet.

Looping multiple sheets might be something like:

Option Explicit

Sub test()

    Dim keepCols()
    keepCols = Array("Employee Number", "Status")

    Dim unionRng As Range, rng As Range, ws As Worksheet

    For Each ws In ThisWorkbook.Worksheets
        With ws
            If Application.WorksheetFunction.CountA(.Rows(1)) > 0 Then
                For Each rng In Intersect(.Rows(1), .UsedRange)
                    If IsError(Application.Match(rng.Value, keepCols, 0)) Then
                        If Not unionRng Is Nothing Then
                            Set unionRng = Union(unionRng, rng)
                        Else
                            Set unionRng = rng
                        End If
                    End If
                Next rng
                If Not unionRng Is Nothing Then 
                    Debug.Print unionRng.EntireColumn.Address 'unionRng.EntireColumn.Delete '.  ''<== Swop when ready to delete
                    Set unionRng = Nothing
                End If
            End If
        End With
    Next ws
End Sub
QHarr
  • 83,427
  • 12
  • 54
  • 101
  • 1
    Ahhh you see, I knew you knew what I was trying to do! Thank you very much :) – Eitel Dagnin May 09 '18 at 12:02
  • I seem to be having an issue. I changed the code a little to not be specific to one sheet but rather loop through them all and I seem to be getting an error with that.. I updated my question with that error.. – Eitel Dagnin May 09 '18 at 12:34
  • Is it thrown when the sheet has nothing in the first row at all? See bottom version of answer. – QHarr May 09 '18 at 12:44
  • I used your code exactly, I get the error: Method 'union' of 'object'_Global' failed at this line Set unionRng = Union(unionRng, rng). However, when you posted your original answer, the code worked perfectly. – Eitel Dagnin May 09 '18 at 13:07
  • Not sure what else to say without seeing your data layout as the above should work. This line in the bottom version Application.WorksheetFunction.CountA(.Rows(1)) > 0 ensures that union is not attempted if there is no data in row 1. – QHarr May 09 '18 at 13:12
  • Was additional problem sorted? – QHarr May 10 '18 at 19:29
  • 1
    Yes it was, thank you very much! :) I had to leave early so I did not get to contact you again. – Eitel Dagnin May 11 '18 at 07:55