Страницы: 1
RSS
Неккоректное сравнение чисел в макросе (VBA)
 
Добрый день. Никак не получается понять, почему неправильно сравнивает значение в макросе.
Суть таблицы: Пользователь вводит данные только в ячейки помеченные желтым (все остальные заблокированы). Далее нажимает на кнопку сверху (длинная зеленая) и запускается макрос проверки логических ошибок.
Интересует проверка равенства ячеек H52 и суммы K52:M52. В макросе оставил только эту проверку.
Я так подозреваю, что проблема в вещественных числах, ибо в других таблицах есть подобная проверка, но там вводятся целые числа, и повторить ошибку не удалось. Все данные вводятся пользователем и никакие операции над ними не производятся.
И конкретно ошибка:
ввожу 0,7 и сравниваю с суммой 0,6+0,1 - ошибки нет
ввожу 0,7 и сравниваю с суммой 0,65+0,05 - ошибка есть
ввожу 0,246 и сравниваю с суммой 0,123+0,123 - ошибки нет
Таким образом можно вводить разные числа (заведомо равные) - макрос может сравнить правильно, а может и неправильно
Куда можно копать?
p.s. пробовал исскуственно умножать на 1 значения, чтобы vba точно определял это как числа (прочитал в кодной из тем тут на форуме) - результата не дало
Изменено: Крекер - 26.12.2017 09:36:55
 
В Excel'е и VBA используется стандарт для дробных чисел, который дает погрешность. Один из способов убрать погрешность - округляйте числа перед сравнением. Например в Вашем случае, если смотреть файл, то округляйте до 3-х цифр после запятой.
Пример, сравнения:
Код
cdbl(format(0.65+0.05, "0.000"))=cdbl(format(0.7, "0.000"))
Изменено: Karataev - 26.12.2017 09:39:02
 
Спасибо большое. Работает
 
В продолжении темы появилась другая проблема. Проверка сравнений происходит в цикле по нескольким строчкам. Пользователь не всегда вводит числа в каждую строчку. Соответственно формула  cdbl(format(x, "0.000")) выдает ошибку на пустых строках : runtime error 13 type mismatch
Можно ли этого как-то избежать, не проставляя нули?  
 
Перед преобразование делайте проверку на наличие данных
Код
 For j = 52 To 53
    If Not (IsEmpty(Cells(j, 11)) And IsEmpty(Cells(j, 8))) Then
        If (CDbl(Format(Cells(j, 11) + Cells(j, 12) + Cells(52, 13), "0.000")) <> CDbl(Format(Cells(j, 8), "0.000"))) Then
            '...........
        End If
    End If
 Next j
Согласие есть продукт при полном непротивлении сторон
 
Крекер, на пустых ячейках такой ошибки быть не должно, т.к. там числовое значение 0 по умолчанию хранится. А вот на нулевых строках или строках с символом ', или пробелами такая ошибка будет возникать, т.к. они содержат текст, неконвертируемый в число.
Добавьте строку On Error Resume Next перед строкой, ошибку в которой надо игнорировать, или сделайте обработку каждого случая.
Изменено: Irregular Expression - 09.01.2018 19:44:54
 
ну Dabl дважды его CDbl(Format(CDbl(
но я б для  онругления всеж Round использовал. Зачем гонять из формата в формат, и сравнивать текст. Это хорошо что в вашем случае просто на неравенство проверка, а завтра только > или < потребуется, что делать с текстом?  Да и числа сравнивать компу чуть проще.
Изменено: БМВ - 09.01.2018 19:50:36
По вопросам из тем форума, личку не читаю.
 
Спасибо, попробовал через
Код
If (Round(Cells(j, k - 10), 2) < Round(Cells(j, k) + Cells(j, k + 10), 2)) Then
(из другой проверки в таблицы, где тоже была ошибка), вроде все корректно сравнивает
 
Крекер, только имейте ввиду, что Round округляет по-особому, когда дробная часть заканчивается на 5. Округление может быть в меньшую, а может быть в большую сторону. Точно не помню принципа, кажется связано с четностью - округляется так, чтобы было четное число. Посмотрите в интернете про такое округление.
Страницы: 1
Читают тему
Наверх