Как заставить match () работать с датой в excel vba?


У меня возникли проблемы с тем, чтобы match() работал в excel VBA. Код такой:

x = Application.Match("Sep 2008", Range("F1:F1"), 0)

Значение в ячейке F1 равно 9/1/2008.

Даже если я изменил Sep 2008 на 9/1/2008, он все равно не возвращает никакого значения.

Есть идеи, как это исправить?

6 3

6 ответов:

Лучше всего использовать .Find(). Это вернет a range если найдено или nothing если нет.

Set x = Range("F1:F1").Find(CDate("Sept 2008"), , , xlWhole)

Если вам нужен номер столбца :

x = Range("F1:F1").Find(CDate("Sept 2008"), , , xlWhole).Column

С захватом не найденного

Sub test()

    Dim y As Date, x As Variant, c As Long
    y = CDate("Sep 2008")
    Set x = Range("1:1").Find(y, , , xlWhole)
    If Not x Is Nothing Then
        c = x.Column '<~~found
    Else
        Exit Sub 'not found
    End If

End Sub

Причина, по которой Even if I changed Sep 2008 to 9/1/2008, it still doesn't return any value.

Это потому, что когда в excel есть дата, Excel автоматически преобразует эту дату в числовое значение, то, что вы действительно хотите найти, это:

39692

Это число является числом дней между 9/1/2008 и excel по умолчанию 1/1/1900

Каждая дата в excel хранится со значением, подобным этому. Поэтому самый простой способ справиться с этим-преобразовать то, что вы видите как дату, в то, что excel видит как дату, используя CDate().

Это само по себе даст вам бесполезную ошибку, что vba не может получить свойство.

Это потому, что Lookup_value может быть значением (число, текст или логическое значение) или ссылкой ячейки на число, текст или логическое значение. Не дата, поэтому просто преобразуйте значение даты now в число для поиска соответствующего числа в списке с помощью CLng()

Дайте этому шанс, он также будет намного быстрее, чем использование альтернативы Find:

x = WorksheetFunction.Match(CLng(CDate("Sep 2008")), Range("F1:F1"), 0)

Это должно дать вам ожидаемый результат

К дескриптор, когда совпадение не найдено попробуйте этот Sub:

Sub MatchDate()
Dim myvalue As Double
Dim LastRow As Long

LastRow = Cells(Rows.Count, "F").End(xlUp)

On Error GoTo NotFound
myvalue = WorksheetFunction.Match(CLng(CDate("Sep 2008")), Range("F1:F" & LastRow), 0)
MsgBox (myvalue)
End

NotFound:
MsgBox ("No Match Was Found")
End

End:
End Sub

Таким образом, он работает следующим образом:

Nbr,L, C как целое число

Datedeb как дата

nbr = WorksheetFunction.Match(CLng(CDate(Datedeb)), Range(Cells(L, C), Cells(L + 100, C)), 0)

Итог:

  • Использование WorksheetFunction.Match(CDbl(date), range, 0)

  • В качестве альтернативы используйте свойство Date ячейкиValue2 (которое также будет a Double) вместо Value для ключа поиска.

CLng предложенные в других ответах отбросили бы временную часть date.

Та же проблема существует для типа данных Currency, но вы не можете использовать для него CDbl (смотрите ниже варианты).


Диапазон.Свойство Value2 (Excel) статья предполагает, что типы Date и Currency являются "особыми", поскольку они имеют "внутреннее представление", которое резко контрастирует с отображаемым значением. Действительно:

  • Date внутренне представлен в виде 64-разрядных (8-байтовых) чисел с плавающей запятой IEEE, где целая часть-это дата, а дробная часть-Время
  • Currency также является 8-байтовым, но рассматривается как число с фиксированной точкой с 4 дробными цифрами (целое число, масштабируемое на 10 ' 000)
По-видимому,

Сравнивает эти внутренние значения по причинам производительности. Таким образом, мы должны гарантировать, что они, а не читаемые представления, точно совпадают.

Поскольку Date уже является внутренне плавающей точкой, CDbl(date) фактически не изменяет данные.

Для типа Currency, CDbl действительно изменяет данные, так что это не подлежит сомнению. Так что либо

  • используйте точное представление ключа (до 4 дробных цифр) так или иначе, если вы требовать точного совпадения, или
  • сделайте ячейки в диапазоне фактически формулами с Round) если значение для сравнения взято из другого источника и / или требуется только равенство 2 дробным числам

Я думаю, что могу с уверенностью предположить, что значение в F1 - это дата. В вашем коде "Sep 2008" - это строка. Вы никогда не сможете получить успешное совпадение, пока ваши типы данных несовместимы. Если вы ищете дату, то убедитесь, что первым параметром является дата.

Dim dSearchSDate As Date

dSearchSDate = "01/Sept/2008"

x = Application.Match(dSearchSDate, Range("F1:F1"), 0)
Вот еще один возможный подход.
Sub temp()
Dim x
Dim dSearchSDate As Date

    dSearchSDate = "01/Sept/2008"

    If ThisWorkbook.Worksheets(1).Range("F1:F1").Value = dSearchSDate Then
        Debug.Print "Found it!"
    Else
        Debug.Print "Doh!!"
    End If

End Sub

Я знаю, что этот пост старый, но у меня был тот же вопрос, и я нашел ответ.

Чтобы заставить его работать, вам сначала нужно заставить VBA видеть то же форматирование данных, что и в вашей электронной таблице excel:

YourVar = Format ("YourDate", " mmm-yyyy") YourResult = Приложение.матч(Clng(Cdate(YourVar)), YourRange, 0)

С уважением

Жиль