#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. Чтобы избежать лишней строки, просто удалите
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
и вы снова получите эту ошибку..