Как заставить 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 ответов:
Лучше всего использовать
.Find()
. Это вернет arange
если найдено или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
(которое также будет aDouble
) вместо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)
С уважением
Жиль