Вычислить, что формула где-то может вызвать ошибку

Программирование на Visual Basic for Applications
Avtopic
Постоялец
Постоялец
 
Сообщения: 442
Зарегистрирован: 30.09.2005 (Пт) 17:15
Откуда: Tbilisi

Вычислить, что формула где-то может вызвать ошибку

Сообщение Avtopic » 25.03.2007 (Вс) 16:04

Здравствуйте!

Даю возможность пользователю вписать формулу в текстовом виде, и предварительно проверив на синтаксические ошибки, запоминаю эти формулы в базу.

формула (к примеру):
(a*b) / (1+c/100) + (a*b) / (d*0.3)

или
(a*b) / (1+c/100) + (a*b) / (d*0.3))

первый вариант содержит потенциальную ошибку, если c =-100 или d =0 произойдет деление на ноль.

второй вариант содержит еще и лишнюю “)”.

Кто не будь, может посоветовать, существует теория проверки потенциальных ошибок, или анализа формулы, чтобы заранее вычислить вероятность ошибки? К примеру, такой, какой использует JET при передаче ему SQL строки на синтаксис строки.

Канешно, все завысит от сложности формул, но мне интересен самый простой вариант использование только операторов + - * / ( ) и 4 переменных только a, b, c, d.
Что из этих операторов и переменных сотворит пользователь заранее не известно.
В принципе, для этих операторов и переменных, мне кажется, потенциальные ошибки сводятся только на “деление на ноль” или “переполнение”.

саму формулу (синтаксис) и явное деление, проверяю, следя за ошибками, используя как раз JET:
Код: Выделить всё
Set r = db.OpenRecordset (" SELECT ” &  Моя_формула  &” FROM " & _
    " (SELECT 0 as a, 0 as b, 0 " as c, 0 as d FROM какая-то_непустая_таблица)  ")

и затем K = r.Fields(0)
но потенциальные ошибки не знаю, как проверить.


Спасибо!

KL
Microsoft MVP
 
Сообщения: 483
Зарегистрирован: 30.10.2005 (Вс) 0:31
Откуда: Madrid

Re: Вычислить, что формула где-то может вызвать ошибку

Сообщение KL » 25.03.2007 (Вс) 19:38

Avtopic писал(а):В принципе, для этих операторов и переменных, мне кажется, потенциальные ошибки сводятся только на “деление на ноль” или “переполнение”.
Неуверен, что понял суть задачи. За отсутствием указания на приложение, предполагаю, что речь об Excel.

Переполнение, как я понимаю, это лишь частный случай неправильного типа данных.

Как насчет того, что любая из переменных может иметь текстовое значение (напр. "23" или "2007-03-25" или ЛОЖЬ или ИСТИНА автоматически сконвертируются в нужный тип и ошибки не дадут, а "АБВ23" даст ошибку) или они могут изначально значение ошибки?

Я уже не говорю об ошибках в порядке дней и месяцев в датах, разделителях десятичных и разрядов и т.д. Что уж говорить про функции (неправильное написание, более 7 вставленных функций, более 30 параметров в функции, не активированная надстройка, отсутствие кода UDF или невключенные макросы и т.д.)

А как насчет длинны формулы:
- в различных версиях Excel длина формулы в ячейке ограничена поразному (в Excel 2003 - 1024 знака)
- для формул массива, при вводе через VBA, существует ограничение в 255 знаков (http://www.dailydoseofexcel.com/archive ... as-in-vba/)

Предположим, что в данном случае вышеуказанные проблемы не актуальны. Потенциально, по моему, любая формула может выдать ошибку, даже если это просто ошибка синтаксиса . Не лучше ли отлавливать ошибку в момент подстановки значений переменных? Например:

Код: Выделить всё
Sub test1()
    Dim Formula As String
    Formula = "=A23/B1"
    If Left(Formula, 1) = "=" Then Formula = Mid(Formula, 2, Len(Formula))
    If IsError(Evaluate(Formula)) Then MsgBox "Error in formula"
End Sub


Хотя и тут не все гладко - ошибка в формуле возвращающей массив таким способом не определится и возможно придется делать что-то такое:

Код: Выделить всё
Sub test2()
    Dim Formula As String
    Formula = "=A23/B1:B10"
    If Left(Formula, 1) = "=" Then Formula = Mid(Formula, 2, Len(Formula))
    Select Case True
    Case IsError(Evaluate(Formula))
        MsgBox "Error in formula"
    Case Evaluate("OR(ISERROR(" & Formula & "))")
        MsgBox "Error in formula"
    End Select
End Sub


Все это лишь сумбурные идеи :-)
Привет,
KL

Avtopic
Постоялец
Постоялец
 
Сообщения: 442
Зарегистрирован: 30.09.2005 (Пт) 17:15
Откуда: Tbilisi

Сообщение Avtopic » 26.03.2007 (Пн) 1:25

KL
1. Спасибо за потраченное для меня время.: :))
2. Суть задачи примерно такой:
Существуют бухгалтерский план счетов.

Существуют стандартные бухгалтерские операции.
Интерфейс программы позволяет пользователю по отдельности вывести эти операции в форме , и для каждой операции сделать следующее:
Перетаскиванием, составить список на какие бух. счета должна воздействовать операция в дебиторской часты, на какие в кредиторской. А напротив указать, какой формулой вычислить это воздействие. Этот список с формулами запоминается.

В результате, позже, параллельно проведению операции происходит изменения в соответствующих счетах и “on line” формированные баланса предприятия. В основном для аналитических нужд.

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

Как я писал, синтаксис проверяю с помощью JET, для которого, в конце концов, и пишутся эти формулы. И возможное деление на ноль тоже так проверяю.
Все эти проверки происходят в момент создания формул, так как крайне нежелательно возникновение ошибки в ходе работы.

Исходя из этих маленьких претензии, и написал что, << потенциальные ошибки сводятся только на “деление на ноль” или “переполнение”. >>

a,b,c,d реально это- К –количество, Ц –цена или сумма, Н- ндс, А –акциз.
В принципе, если кто-то напишет в формуле 1/К, это сразу перехватываю и вывожу сообщение что, “это потенциально может стать причиной ошибки и что в бухгалтерии трудно представить себе бух. счет где для вычислении нужно деление на количество“
Но трудности возникают с ндс и акциз.
Короче, мне нужно в формуле найти ту часть, которая находится после знака “/”, и является “отдельно вычисляемой частью” (термин придумал :)) )
На пример, в формуле
a*b+1/c*d*(a+b)+ d+a +a*b+1/ (a+b)+ d+a
под “отдельно вычисляемой частью” подразумеваю c*d*(a+b) которая в результате не должна роднятся нулю, так же (a+b). Т.е. их там две.
Найдя такие части потом сам присобачу к ним iif-и и прочие проверки.
Извиняюсь, что много написал. Надеюсь, понятно передал задачу.

KL
Microsoft MVP
 
Сообщения: 483
Зарегистрирован: 30.10.2005 (Вс) 0:31
Откуда: Madrid

Сообщение KL » 26.03.2007 (Пн) 2:00

Avtopic писал(а):Короче, мне нужно в формуле найти ту часть, которая находится после знака “/”, и является “отдельно вычисляемой частью” (термин придумал :)) )
На пример, в формуле
a*b+1/c*d*(a+b)+ d+a +a*b+1/ (a+b)+ d+a
под “отдельно вычисляемой частью” подразумеваю c*d*(a+b) которая в результате не должна роднятся нулю, так же (a+b). Т.е. их там две.

Похоже, твоя задача должна решаться с пом. regular expressions.
Jurgen Volkering делает нечто подобное в своей надстройке TranslateIt: http://members.chello.nl/jvolk/keepitcool/download.html (код незакрытый, но с Copyright)

Еще про regular expressions:
http://msdn.microsoft.com/library/defau ... 6a7353.asp
Привет,
KL

Avtopic
Постоялец
Постоялец
 
Сообщения: 442
Зарегистрирован: 30.09.2005 (Пт) 17:15
Откуда: Tbilisi

Сообщение Avtopic » 26.03.2007 (Пн) 15:19

Спасибо!
Изображение


Вернуться в VBA

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 83

    TopList