Текст Range.Find() с возвратом каретки Excel VBA

Что я пытаюсь сделать
Найдите столбец, ячейка заголовка которого содержит уникальную строку. Другими словами, я знаю текст ячейки и знаю, что ячейка находится в строке 1, но не знаю, в каком столбце. ПРИМЕЧАНИЕ. Я хочу искать весь текст, а не только его часть. ПРИМЕЧАНИЕ 2. Текст может отличаться, поэтому я не могу жестко закодировать значение в своем коде. Скорее мне нужно использовать переменную, в которой хранится значение.

Проблема
Если в тексте заголовка нет возврата каретки, простой newCol = Range("1:1").Find(headerText).Column работает нормально. Однако, если есть возврат каретки, это не работает. Выдает ошибку "Переменная объекта или переменная блока не установлена". Вот моя точная строка заголовка:

Incomplete Email
(more text)

Что я уже пробовал
Я также пробовал использовать WorksheetFunction.Match(headerText, Range("1:1"), 0), но возникла та же проблема.

Дополнительные примечания и требования
Это часть надстройки, поэтому я не хочу ничего менять в пользовательском листе Excel, если в этом нет необходимости (т. е. я не удалять возврат каретки).

Технически я делаю это в функции:

Public Function getColumn(headerText As Variant)
    getColumn = Range("1:1").Find(headerText).Column
End Function

Спасибо!


person Alex Silverman    schedule 20.04.2016    source источник
comment
Что, если вы попробуете Range("1:1").Find("*" & headerText & "*").Column   -  person BruceWayne    schedule 20.04.2016
comment
Неудачно. Та же проблема   -  person Alex Silverman    schedule 20.04.2016
comment
Как вы объявили newCol? Я поставил Test [alt-enter] Test и запустил newCol = Range("1:1").Find("Test").Column и все заработало.   -  person BruceWayne    schedule 20.04.2016
comment
Вы пробовали Trim и CLEANФункции???   -  person Elbert Villarreal    schedule 20.04.2016
comment
Если вы абсолютно уверены, что он находится в диапазоне (1:1), вы можете попробовать Range("1:1").Find(What:=headerText, LookAt:=xlPart).Column   -  person LocEngineer    schedule 20.04.2016
comment
Элберт и LocEngineer: ни одно из решений не сработало. На обоих концах строки нет пробелов, и строка представляет собой полное значение ячейки, а не только ее часть.   -  person Alex Silverman    schedule 20.04.2016
comment
Брюс: Технически это возвращаемое значение функции. Но я не удивлен, что у вас сработало, так как вы искали строку Test без возврата каретки.   -  person Alex Silverman    schedule 20.04.2016
comment
Глупый вопрос: вы ищете Incomplete Email или Incomplete Email (more text)?   -  person LocEngineer    schedule 20.04.2016
comment
Я ищу все это: Неполное электронное письмо (больше текста), где между неполным письмом и (больше текста) есть возврат каретки.   -  person Alex Silverman    schedule 20.04.2016
comment
В этом случае это просто сработало для меня, используя Find(What:="Incomplete Email" & Chr(10) & "(more text)")   -  person LocEngineer    schedule 20.04.2016
comment
Правильно, так что это работает, потому что вы жестко запрограммировали строку и возврат каретки. Но я не ЗНАЮ, что он будет. Поэтому мне нужно искать ПЕРЕМЕННУЮ, а не ЗНАЧЕНИЕ.   -  person Alex Silverman    schedule 20.04.2016


Ответы (3)


Пожалуйста, попробуйте с кодом ниже

Public Function getColumn(headerText As String)
    str1 = Split(headerText, vbCrLf)
    str2 = UBound(str1)
    b = Range("1:1").Find(str1(0) & Chr(10) & str1(1)).Column
End Function
person Karthick Gunasekaran    schedule 20.04.2016
comment
См. комментарий Брюса Уэйна выше. Это не работает. Имеет некоторый смысл, что это не так, поскольку у меня есть вся строка, поэтому подстановочные знаки * на самом деле мало что делают. - person Alex Silverman; 20.04.2016
comment
Для меня это не идеальное решение, но в качестве резервной копии может подойти. Сначала я определю, есть ли возврат каретки, и я буду использовать этот код. Спасибо! - person Alex Silverman; 20.04.2016

Вот в чем дело: текст с разрывом строки и без него НЕ является одним и тем же текстом, поэтому .Find не работает. Что вы должны сделать, это поиск шаблона. Я только что проверил это, и это работает, при условии, что если нет разрыва строки, должен быть пробел:

Sub test()
Dim rex As RegExp, ran As Range
Dim col As Integer, headerText As String

'read you headerText here

Set rex = New RegExp
rex.Pattern = RegexIt(headerText)

For Each ran In Range("1:1")
    If rex.test(ran.Text) Then
        col = ran.Column
        Exit For
    End If
Next ran

MsgBox col

End Sub

Function RegexIt(what As String) As String

what = Replace(what, "(", "\(")
what = Replace(what, ")", "\)")
what = Replace(what, "[", "\[")
what = Replace(what, "]", "\]")
what = Replace(what, "<", "\<")
what = Replace(what, ">", "\>")
what = Replace(what, " ", "[\n ]?")
what = Replace(what, vbCrLf, "[\n ]?")

End Function

Удачи!

Изменить: требуется ссылка на регулярные выражения Microsoft VBScript 5.5.

Edit2: отредактировано для использования переменных. Объяснение: Замените пробел в значении переменной на необязательный пробел/разрыв строки, экранирующие скобки для сопоставления с образцом.

person LocEngineer    schedule 20.04.2016
comment
Спасибо. К сожалению, как я уже упоминал выше, мне нужно искать переменную, потому что точная строка может отличаться. Можете ли вы использовать RegEx с переменной? - person Alex Silverman; 20.04.2016
comment
При условии, что разрывы могут происходить только между словами значения переменной, да. См. редактирование2. - person LocEngineer; 20.04.2016
comment
Это кажется более интуитивным, но и более неуклюжим, чем решение Картика выше. - person Alex Silverman; 20.04.2016
comment
Это определенно выглядит более неуклюже. Но Катик не будет работать, если НЕТ разрыва строки. Также мой код выше содержал ошибки. Я немного изменил его, а также расширил, когда текст заголовка содержит пробелы, разрывы строк или символы, которые необходимо экранировать для регулярного выражения. Хотя должно быть хорошо. - person LocEngineer; 21.04.2016

Ваш код должен работать, даже если ячейка заголовка содержит возврат каретки:

Sub FindColumnWithTextInRowOne()
    Dim headerText As String, newCol As Long

    headerText = "whatever"
    newCol = Range("1:1").Find(headerText).Column
    MsgBox newCol
End Sub

введите здесь описание изображения


Это связано с тем, что использование вами Find() не требует совпадения со ВСЕМ содержимым ячейки.

РЕДАКТИРОВАНИЕ №1:

Если ячейка заголовка была построена с использованием формулы, следует использовать несколько иной Find():

   Sub FindColumnWithTextInRowOne()
    Dim headerText As String, newCol As Long, r As Range
    headerText = Range("H1").Text
    newCol = Range("1:1").Find(What:=headerText, LookAt:=xlWhole, LookIn:=xlValues).Column
    MsgBox newCol
End Sub

введите здесь описание изображения

person Gary's Student    schedule 20.04.2016
comment
Вы ищете часть текста заголовка, а не весь текст. - person Alex Silverman; 20.04.2016
comment
Попробуйте выполнить поиск Range(H1).Value или где бы вы ни хранили этот текст. Это не должно работать. - person Alex Silverman; 20.04.2016
comment
Не тут-то было, хотя дела обстоят немного иначе. Поскольку я работаю с формой, headerText на самом деле является значением раскрывающегося списка/поля со списком, которое передается функции. Использование LookAt:=xlWhole и Lookin:=xlValues не помогло. - person Alex Silverman; 20.04.2016