2015-08-25 2 views
1

Мой код до сих пор, как это:Excel-Vba - Double/Дата/время согласования и толерантность

Sub FindMatchingValue() 
    Dim i As Integer, TimeValueToFind As Date 
    TimeValueToFind = "04:00:00" 
    Sheets("Vessels").Range("F07").ClearContents 
    For i = 1 To 25 ' 
     If CDate(Sheets("Vessels").Cells(i, 1).Value) = TimeValueToFind Then 
      MsgBox ("Found value on row " & i) 

      Sheets("Vessels").Range("F07").Value = Cells(i, 1).Offset(1, 1).Resize(1).Value 
      Exit Sub 
     End If 
    Next i 
    MsgBox ("Value not found in the range!") 
End Sub 

Этот код проверяет Столбец A в течение времени, введенного в формате хх: хх: хх И где ввод и где время написано, устанавливаются как формат «Время». Изначально редактирование CDate не было добавлено. И это заставило код всегда возвращать false, потому что, поскольку он был поставлен, я пытался «сравнить яблоки с апельсинами».

Однако добавление CDate добавляет ошибку несоответствия. Точно так же изменения, как быть двойной также не работают:

Sub FindMatchingValue() 
    Dim i As Integer, TimeValueToFind As Date 
    TimeValueToFind = "04:00:00" 
    Sheets("Vessels").Range("F07").ClearContents 
    For i = 1 To 25 ' 
     If Sheets("Vessels").Cells(i, 1).Value = CDbl(TimeValueToFind) Then ' < This was the line changed 
      MsgBox ("Found value on row " & i) 

      Sheets("Vessels").Range("F07").Value = Cells(i, 1).Offset(1, 1).Resize(1).Value 
      Exit Sub 
     End If 
    Next i 
    MsgBox ("Value not found in the range!") 
End Sub 

Однако это одна другая причина, так как магазины Excel значение, как плавающая точка, каждое значение по-прежнему отличается. «Хорошо известно, что выражение a == b, скорее всего, вернет False, когда a и b оба удваиваются, хотя вы можете подумать, что они одинаковы. Это связано с конечной точностью, с которой хранятся числа с плавающей запятой. "

Путь вокруг этого заключается в установке допуска. If abs(a-b)<tolerance Then Однако я не особо уверен в том, какую терпимость использовать и как ее можно включить, не запуская первый цикл.
Интересно, может ли кто-нибудь пролить свет на это и направить меня, какие дополнения мне нужно сделать, и какие допуски будут приемлемыми? Я думаю, что вопрос по существу двоякий. Заранее спасибо!

+0

hm ... первый работает для меня. При сравнении «CDate (sheetvalue) =« 04:00:00 »« Я получаю истинное значение – rst

+0

Возможно, стоит отметить, что объект «Range» имеет свойство «.Value2», которое не использует типы даты или валюты, поэтому вернет Вариант/Двойное значение. –

+0

Вы пытались использовать 'TimeValue()' вместо этого? –

ответ

0

Вы правы, что неточность чисел с плавающей запятой является причиной вашей проблемы. Помните, что базовые данные в типе данных даты по-прежнему являются двойными, отформатированными как дата.

Вопрос «... какие допуски приемлемы?» действительно зависит от вас. Учитывая, что ваше тестовое значение равно «hh: mm: ss», тогда может быть достаточно второго.

Существует много способов достичь этого. Если данные в формате «чч: мм: сс», то это будет работать

If CDate(Sheets("Vessels").Cells(i,1).Text) = TimeValueToFind Then 

Это зависит от формата, нанесенного на лист в том, чтобы с такой же точностью, как ваш тест значения

+0

Также значение всегда по часам, в частности, это всегда 00:00:00, любая идея, как написать терпимость? – Savagefool

+0

Насколько близки времена для _you_ считать их равными? –

1

Использование TimeValue() или TimeSerial() как так:

Sub SO() 

Dim x As Date 
Dim y As Date 
Dim z As Date 


x = TimeValue("04:00:00") 
y = TimeSerial(4, 0, 0) 
z = CDate(Range("A1").value) '// A1 has "04:00:00" entered 

Debug.Print x = y '// True 
Debug.Print y = z '// True 
Debug.Print x = z '// True 

End Sub 

Подставляя это в контексте вашего кода:

Sub FindMatchingValue() 
    Dim i As Integer, TimeValueToFind As Date 
    TimeValueToFind = TimeValue("04:00:00") 
    Sheets("Vessels").Range("F07").ClearContents 
    For i = 1 To 25 ' 
     If CDate(Sheets("Vessels").Cells(i, 1).value) = TimeValueToFind Then 
      MsgBox ("Found value on row " & i) 
      Sheets("Vessels").Range("F07").value = Cells(i, 1).Offset(1, 1).Resize(1).value 
      Exit Sub 
     End If 
    Next i 
    MsgBox ("Value not found in the range!") 
End Sub 
+0

Все еще возвращает false для меня, оператор If никогда не запускает – Savagefool

+0

, если вы измените его на «CDate (листы (« сосуды »). Ячейки (i, 1) .Value2)'? –

+0

Такая же проблема, по-прежнему говорит: «Значение не найдено в диапазоне!» – Savagefool

0

Для тех, кто заинтересован, вот ответ:

Sub FindMatchingValue() 
    Dim i As Integer, TimeValueToFind As Date, Delta As Double, Tolerance As Double 
    TimeValueToFind = Sheets("Vessels").Range("F06") 
    Tolerance = 0.001 
    Sheets("Vessels").Range("F07").ClearContents 
    For i = 2 To 25 ' 
     Delta = Sheets("Vessels").Cells(i, 1).Value - CDbl(TimeValueToFind) 
     If Abs(Delta) <= Tolerance Then 

      MsgBox ("Found value on row " & i) 

      Sheets("Vessels").Range("F07").Value = Cells(i, 1).Offset(0, 1).Resize(1).Value 
      Exit Sub 
     End If 
    Next i 
    MsgBox ("Value not found in the range!") 
End Sub 

Так в любое время в коробке F06, набранного в, теперь он находит. Была использована комбинация допуска, а также преобразование в двойное. i = 1-25 был изменен на 2-25, потому что у меня был текстовый заголовок, и это создавало ошибку несоответствия.

+0

Как вы достигли допуска 86,4 секунды? –

+0

Не уверен, я получил часть ответа от кого-то еще. Это работает. И поскольку моя не вторая вещь, время округляется до часа, поэтому точность не должна быть идеальной. 000.1 более чем достаточно, infact это, вероятно, слишком точно, но это хорошо, чтобы быть уверенным. – Savagefool

Смежные вопросы