Идентифицировать два разных столбца с помощью одной функции

#excel #vba

#excel #vba

Вопрос:

Вот функция, которая может идентифицировать столбец по его заголовку:

 Function find_Col(header As String) As Range

    Dim aCell As Range, rng As Range
    Dim col As Long, lRow As Long
    Dim colName As String
    Dim y As Workbook
    Dim ws1 As Worksheet

    Set y = Workbooks("Template.xlsm")

    Set ws1 = y.Sheets("Results")

    With ws1

        Set aCell = Cells.Find(what:=header, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False, SearchFormat:=False)

        col = aCell.Column
        colName = Split(.Cells(, col).Address, "$")(1)

        lRow = Range(colName amp; .Rows.count).End(xlUp).Row   1

        Set myCol = Range(colName amp; "2")

        'This is your range
        Set find_Col = Range(myCol.Address amp; ":" amp; colName amp; lRow)

        find_Col.Select

    End With

End Function
  

Затем я вызываю функцию во вложенном:

 Sub myCol_Find()

    find_Col ("Product")

End Sub
  

Вышеописанное работает нормально, но проблема, с которой я сталкиваюсь, заключается в том, что если столбец, который я ищу, практически пустой, исключая заголовок, то моя функция выберет только первые 2 строки под заголовком. Кроме того, вторая проблема, она также выбирает строку сразу после последней строки. Таким образом, если первая строка под заголовком является B3 , а последняя строка — B10 , она выбирает B3:B11 .

В результате этого я подумал, что, возможно, будет работать лучше, если сначала определить столбец с данными в нем (в котором, я знаю, всегда будут данные), затем использовать этот столбец для поиска последней строки данных и, наконец, использовать фактический столбец, который мне нужен для выбора.

Итак, я сначала провел тест, изменив эту строку:

     lRow = Range(colName amp; .Rows.count).End(xlUp).Row   1
  

К этому:

     lRow = Range("A" amp; .Rows.count).End(xlUp).Row   1
  

И это выделило все ячейки в моем столбце поиска на основе общего количества строк, найденных в столбце A.

Затем я подумал, что вместо того, чтобы специально называть столбец, я применю ту же логику «поиска» столбца, чтобы найти «Столбец A». Итак, у меня есть это:

 Function find_Col(header As String) As Range

    Dim aCell As Range, rng As Range, def_Header As Range
    Dim col As Long, lRow As Long, defCol As Long
    Dim colName As String, defColName As String
    Dim y As Workbook
    Dim ws1 As Worksheet

    Set y = Workbooks("Template.xlsm")

    Set ws1 = y.Sheets("Results")

    With ws1

        Set def_Header = Cells.Find(what:="ID", LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False, SearchFormat:=False)

        defCol = def_Header.Column
        defColName = Split(.Cells(, def_Col).Address, "$")(1)

        Set aCell = Cells.Find(what:=header, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False, SearchFormat:=False)

        col = aCell.Column
        colName = Split(.Cells(, col).Address, "$")(1)

'        lRow = Range(colName amp; .Rows.count).End(xlUp).Row   1

        lRow = Range(defColName amp; .Rows.count).End(xlUp).Row   1

        Set myCol = Range(colName amp; "2")

        'This is your range
        Set find_Col = Range(myCol.Address amp; ":" amp; colName amp; lRow)

        find_Col.Select

    End With

End Function
  

Добавлен дополнительный код:

 Dim def_Header As Range
Dim defCol As Long
Dim defColName As String

Set def_Header = Cells.Find(what:="KW_ID", LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False, SearchFormat:=False)

defCol = def_Header.Column
defColName = Split(.Cells(, defCol).Address, "$")(1)
  

И изменил это:

 lRow = Range("A" amp; .Rows.count).End(xlUp).Row   1
  

К этому:

 lRow = Range(defColName amp; .Rows.count).End(xlUp).Row   1
  

Теперь я получаю сообщение об ошибке в строке:

 defCol = def_Header.Column
  

Ошибка:

Объектная переменная с не заданной блочной переменной

Я не совсем понимаю, в чем проблема, поскольку ранее при определении этой ошибки она мне не выдавала aCell .

Итак, в настоящее время я сталкиваюсь с двумя проблемами:

  1. Выделение — это выделение одной дополнительной ячейки по сравнению с необходимой
  2. Я не знаю, почему я получаю вышеуказанную ошибку

Комментарии:

1. Чтобы избежать лишней строки, просто удалите 1 Вы ничего не охватываете внутри своего With блока (т. Е. вы должны добавлять префикс Range и т.д. с .

2. БОЖЕ. ;/ Вот, я чувствую себя дураком. Продолжайте пропускать эти простые проблемы. Спасибо @TimWilliams 🙂

3. def_Header будет Nothing , если заголовок не найден, поэтому вам нужно проверить это.

4. Аааа! Название заголовка не было обновлено правильно. Спасибо за помощь @TimWilliams 🙂

5. В качестве бонуса вы можете просто использовать find_Col("Product").Select в своем основном коде. Таким образом, вы можете избежать использования .Select в вашей функции, которое может иметь непредвиденные последствия в будущем. На самом деле, вы можете использовать любое из свойств диапазона и методов в строке вызова функции, потому что возвращаемая функция представляет собой диапазон.

Ответ №1:

Это должно сработать:

РЕДАКТИРОВАТЬ: обновлено для рассмотрения случаев, когда заголовок найден, но данных нет

 Function find_Col(header As String) As Range

    Dim aCell As Range, bCell As Range, rng As Range

    With Workbooks("Template.xlsm").Sheets("Results")

        Set aCell = .Cells.Find(what:=header, LookIn:=xlValues, lookat:=xlWhole, _
                                 MatchCase:=False, SearchFormat:=False)

        If Not aCell Is Nothing Then
            Set aCell = aCell.Offset(1, 0)
            Set bCell = .Cells(.Rows.Count, aCell.Column).End(xlUp)
            If bCell.Row > aCell.Row Then
                Set rng = .Range(aCell, bCell)  'column has some content
            Else
                Set rng = aCell 'or nothing?     'column has no content...
            End If
        End If      
    End With

    Set find_col = rng
End Function
  

Комментарии:

1. Отлично работает. Спасибо 🙂

2. @EitelDagnin: Вам все равно придется сделать одну дополнительную проверку.. If Not find_Col("Product") Is nothing Then Это потому, что если заголовок не найден, то Set find_col = rng будет равно Set find_col = Nothing и вы снова получите эту ошибку..