Страницы: 1 2 След.
RSS
VBA....Ошибается?
 
Здравствуйте!  
При написании программ на vba столкнулся со странной проблемой:  
VBA ошибается при работе с оператором if...  
Прогонял программу по f8, видел что значения переменных были правильными, но оператор if врал...  
Помогло в некоторых случаях введение дополнительных переменных.  
Пример:  
....  
a=5  
b=3  
if a>b then c=5  
else  
c=10  
end if  
Ежели оператор if ошибся, можно попытаться заменить вот так:  
.....  
a=5  
b=3  
d=a  
if d>b then c=5  
else  
c=10  
end if  
конечно ошибется if не в таком простом случае, а если к переменной "a" до того было много обращений...  
Или вот еще пример:  
Public Sub dimcreate(x1, y1, x2, y2, x3, y3)  
Dim Acad As Object  
 Set Acad = GetObject(, "Autocad.Application")  
 If Err <> 0 Then  
   MsgBox "Autocad не запущен", vbExclamation  
   Exit Sub  
 End If  
При многократном обращении к этой процедуре, оператор if врет( Ошибок нет, а он пишет как будто есть...  
PS: Может быть существуют какие-то подводные камни, которые я не нашел в учебнике по vba?)
 
> конечно ошибется if не в таком простом случае, а если к переменной "a" до того было много обращений...  
 
Обращение обращению рознь. Если переменная использовалась только "для чтения" - не поверю. Если же она изменялась - к ней, скажем, что-то прибавили, а потом СТОЛЬКО ЖЕ отняли - то вполне может быть. Погрешности вычислений!  
Простейший пример из моего окна Immediate  
 
?0.3-0.1-0.2=0  
False  
?0.3-0.1-0.2  
-2,77555756156289E-17
 
А так во втором случае?  
 
Err.Clear  
Set Acad = GetObject(, "Autocad.Application")  
If Err <> 0 Then
 
Пока это Ваши ошибки, а не VBA :-)  
Код первого примера – нерабочий, так как содержит синтаксическую ошибку.  
Эта ошибка легко обнаружится, если выбрать Debug – Compile  
 
' Неправильно  
Sub Test1_NotOk()  
 Dim a, b, c  
 a = 5  
 b = 3  
 If a > b Then c = 5   ' <-- эта строка завершенная  
 Else ' <-- это уже ошибка (Else without If), потому что не относится ни к какому If  
   c = 10  
 End If  
 MsgBox "c=" & c  
End Sub  
 
Правильно так:  
 
' Правильно  
Sub Test1_Ok1()  
 Dim a, b, c  
 a = 5  
 b = 3  
 If a > b Then  
   c = 5  
 Else  
   c = 10  
 End If  
 MsgBox "c=" & c  
End Sub  
 
или так:  
 
' Тоже правильно  
Sub Test1_Ok2()  
 Dim a, b, c  
 a = 5  
 b = 3  
 If a > b Then c = 5 Else c = 10  
 MsgBox "c=" & c  
End Sub  
 
Во втором примере перед Set Acad = … нужна строка: Err.Clear как рекомендует Hugo
 
{quote}{login=ZVI}{date=27.11.2010 12:51}{thema=}{post}Пока это Ваши ошибки, а не VBA :-)  
Код первого примера – нерабочий, так как содержит синтаксическую ошибку.  
Эта ошибка легко обнаружится, если выбрать Debug – Compile  
 
' Неправильно  
Sub Test1_NotOk()  
 Dim a, b, c  
 a = 5  
 b = 3  
 If a > b Then c = 5   ' <-- эта строка завершенная  
 Else ' <-- это уже ошибка (Else without If), потому что не относится ни к какому If  
   c = 10  
 End If  
 MsgBox "c=" & c  
End Sub  
 
Правильно так:  
 
' Правильно  
Sub Test1_Ok1()  
 Dim a, b, c  
 a = 5  
 b = 3  
 If a > b Then  
   c = 5  
 Else  
   c = 10  
 End If  
 MsgBox "c=" & c  
End Sub  
 
или так:  
 
' Тоже правильно  
Sub Test1_Ok2()  
 Dim a, b, c  
 a = 5  
 b = 3  
 If a > b Then c = 5 Else c = 10  
 MsgBox "c=" & c  
End Sub  
 
Во втором примере перед Set Acad = … нужна строка: Err.Clear как рекомендует Hugo{/post}{/quote}
 
Прошу прощения за некорректный предыдущий пост, не знаю как тут можно удалять посты..  
 
2Казанский  
Ну в принципе я думал про погрешности вычислений :-) Речь идет даже не об ошибках в сотых или десятых, ошибки идут в целых числах и даже на дестятки целых...могу попытаться выбрать основные куски из своей проги, чтобы было видно где я или vba ошибся) В принципе я много уже думал именно в этом направлении...думаю если бы получше выбирал тип переменных можно было бы и избежать...собственно потому и пришел за советом)  
2Hugo - спасибо за совет! попробую с Err.Clear....хотя тоже странно,потому что ошибок вроде как и не было...  
2ZVI - синтаксис оператора if  я понимаю) пример то привел не из своей программы, а просто для пояснения проблемы.  
 
А не может быть такого что переменные в vba надо периодически как-то стирать (по аналогии с err.clear приведенного выше? если да то как...  
PS: не выложил сразу свою прогу, потому что думаю врядли кому то захочется копаться в длинном коде...
 
Собственно прикрепил файл, в котором сохранил только ту процедуру, в которой происходит ошибка...в 2-х вариантах, с заменой переменных и без...  
Суть процедуры, что она строит 4-х угольники(трапеции) по трем сторонам, NN1,NN2,NN3 и углу alpha в autocad. Плюс она же образмеривает. Собственно if здесь используется для определения типа трапеции (думаю по "эскизикам" в коде типа /||||||||\ понятно о чем идет речь. А тип нужно найти для того, чтобы правильно проставить в autocad размеры трапеций (опять же это делается программно)  
Заранее спасибо за советы!
 
В Вашем примере есть ссылки на отсутствующий лист, вызов отсутствующих процедур, использование неопределенных констант. Процедура приведена с параметрами, а примера вызова процедуры нет, поэтому не понятно, с какими параметрами сбоит.    
Запустите в своем пример Debug - Compile и отладчик ругнется на первую же ошибку.  
 
Приведите лучше краткий пример, типа тех, что я приводил выше, который можно запустить и увидеть ошибочный результат.  
 
Вероятной ошибкой может быть задание угла в градусах, а не в радианах.  
Тип Currency использует всего 4 знака после запятой, используйте лучше тип Double
 
2ZVI  
Там все ссылки на отсутствующие листы не имеют отношения к оператору if; а все отсутствующие процедуры занимаются непосредственно черчением в autocad, и к тому же не имеют отношения к оператору if.  
Я специально вырезал все лишнее, чтобы проще было понять.  
Модули oshibka и zamena - это одно и то же, в первом случае без ввода ненужных переменных, во втором - с вводом. Переменные так и называются, neponyatno и neponyatno1 (см. пример в первом посте)  
Я использовал и currancy и double, результат от этого не менялся...угол приходит именно в радианах...  
К тому же я прогонял по f8 до строчки где были операторы if, в них все числа были правильные, а оператор "нагло врал".  
Пример:  
видим по f8:    
a=5  
b=3  
c=4  
if a+b>c then  
d=1  
else  
d=2  
end if  
И наша программа идет по else и присваивает d значение 2...  
 
Могу прислать всю прогу (ошибка-то происходит когда эта процедура запускается эдак раз 10-15), только она весит 871 кб...и там куча куча всего...  
Кстати NN1,NN2,NN3 и alpha имеют как раз тип double.
 
Желательно приводить пример полностью с объявлениями переменных, так как ошибка может крыться именно в этом.Вот Ваш пример, он работает корректно: d=1  
   
Sub Test2()  
 a = 5  
 b = 3  
 c = 4  
 If a + b > c Then  
   d = 1  
 Else  
   d = 2  
 End If  
 MsgBox "d=" & d  
End Sub  
 
Покажите на этом примере ситуацию, когда возникает проблема
 
Для однозначности - то же самое, но с объявлением переменных внутри процедуры  
 
Sub Test2()  
 Dim a, b, c, d  
 a = 5  
 b = 3  
 c = 4  
 If a + b > c Then  
   d = 1  
 Else  
   d = 2  
 End If  
 MsgBox "d=" & d  
End Sub
 
{quote}{login=dec0rator}{date=27.11.2010 02:32}{thema=}{post}...Могу прислать всю прогу (ошибка-то происходит когда эта процедура запускается эдак раз 10-15), только она весит 871 кб...и там куча куча всего...{/post}{/quote}Всю не нужно, локализуйте проблему и приведите краткий код именно с проблеммой.  
С учетом "эдак раз 10-15" можно предположить, что переменные при перезапуске не инициализируются, т.е объявлены на уровне модуля, а не внутри процедур(ы).  
 
Или передаются в процедуру как ссылки ByRef (если не указано, то это - по умолчанию), а не ByVal (работа с копией). Переменная, переданная как ссылка из одной процедуры в другую, может быть изменена в этой другой, тем самым изменяя её и в первой.  
Более подробно про ByRef, ByVal здесь: http://www.planetaexcel.ru/forum.php?thread_id=3575
 
вряд ди сбоит vba.. ни разу не встречался..  
 
с err - классический пример начинающих. err это не код, возвращаемый подпрограммой, а значение, устанавлимое системой при возникновении ошибки.  
 
нет ошибки - err не меняется, т.е может остаться и ненулевым, если до этого была ошибка в другом месте.
Живи и дай жить..
 
2ZVI  
Я локализовал, сделал вроде бы все наглядно...заодно выяснил что ошибается именно в данном случае...но ошибку не могу найти  
2 слэн - учту, буду знать на будущее)  
думаю что в выложенном примере тоже классическая ошибка..
 
Кстати, в форму нужно вводить значения так, чтобы:  
b>c  
a>d  
Т.е. чтобы получалась фигура вроде той что на рисунке  
Еще нужно забить любую чушь в строку маркировка окна. Все остальные строки можно не трогать
 
{quote}{login=dec0rator}{date=27.11.2010 12:31}{thema=}{post}Кстати, в форму нужно вводить значения так, чтобы:  
b>c  
a>d  
Т.е. чтобы получалась фигура вроде той что на рисунке  
Еще нужно забить любую чушь в строку маркировка окна. Все остальные строки можно не трогать{/post}{/quote}Роман, нет у меня автокада-2010 (вообще никакого нет), Вы можете привестьи пример без него, на чистом VBA?
 
Если нет автокада (как и у меня тоже), можно из References убить ссылку на библиотеку, тогд код работает.  
Но вот в чём ошибка - не понял. Вроде надписи в мессиджах правильные...  
Вы не можете точнее описать, где именно ошибка?
 
2ZVI  
Я итак вырезал все ссылки на автокад) не смотрите что кнопка называется "в autocad"...или проблема в том что я подключил библиотеки автокада?  
Введите, например a=1000,b=1000,c=500,d=400, нажмите "в autocad"  
пойдут msgbox ы, которые полностью дублируют условия выбора...
 
2Hugo  
Программа должна во всех случаях выбирать первое условие, а она выбирает 2-е...в том и ошибка...
 
В первом условии есть  tip3.marka.Value <> ""  
Следовательно, нужно что-то вписать в поле маркировка окна текстбокса tip3.marka, чтобы условие выполнилось как True.  
После этого идет какой-то расчет с сообщениями - проверьте и уточните, что должно быть в tip3.marka
 
NN1 - текстовое значение!
 
Ну да, туда и вывело:  
NN1 = tip3.d.Value
 
хм...  
Dim NN1, NN2, NN3 As Double
 
Заработало, хватает  
NN1 = Val(tip3.d.Value)  
Хотя надо бы и переменные правильно "продимить"...
 
Неправильно: Dim NN1, NN2, NN3 As Double  
Должно быть: Dim NN1 As Double, NN2 As Double, NN3 As Double
 
1) Добавить в  Sub tip3_autocad_Click()  объявление переменных:  
 
' Примечание: # означает As Double, $ = As String  
Dim s1#, s2#, s3#, s4#, x1#, x2#, x3#, x4#, y1#, y2#, y3#, y4#, angle1#, nazvanie$  
 
Полезно в начале модуля писать строку:  
Option Explicit  
Тогда отладчик поможет найти все необъявленные переменные  
 
2) Как уже рекомендовалось, перед тем, как выкладывать пример, проверяйте корректность кода с помощью Debug – Compile  
 
В Вашем примере отладчик при этом найдет ссылки на несуществующие объекты:  
tip1 - в строке tip1.obsada_ver.Enabled = True  
Vubor  - в строке Vubor.Show  
 
3) Вместо Function Pi() лучше объявить константу в начале модуля  
Const Pi# = 3.14159265358979  
Это ускоряет код  
 
Соответственно функция radian() будет выглядеть так:  
Function radian(angle) As Double  
 radian = angle * Pi / 180  
End Function
 
2ZVI, Hugo - спасибо огромное за помощь!  
Собственно ошибка была как раз здесь:  
"Неправильно: Dim NN1, NN2, NN3 As Double  
Должно быть: Dim NN1 As Double, NN2 As Double, NN3 As Double"  
Я проглядел что NN1 то текстом приходит( увидел "правильную" цифру и на этом успокоился...  
На будущее учту советы по поводу описания ВСЕХ переменных! И еще очень полезная информация про ByRef, ByVal.  
PS: В дальнейшем хочу поглубже изучить программирование...что посоветуете, продолжать изучать VB/VBA или учить с нуля C++? сорри за отход от темы
 
{quote}{login=dec0rator}{date=28.11.2010 01:13}{thema=}{post}...что посоветуете, продолжать изучать VB/VBA или учить с нуля C++? сорри за отход от темы{/post}{/quote}А слабо среди фанатов "Спартака" спросить что лучше ЦСКА или "Динамо"? ;)
 
{quote}{login=dec0rator}{date=28.11.2010 01:13}{thema=}{post}что посоветуете, продолжать изучать VB/VBA или учить с нуля C++? сорри за отход от темы{/post}{/quote}  
На чём собираетесь программировать, то и изучайте.
 
{quote}{login=Юрий М}{date=28.11.2010 03:12}{thema=Re: }{post}На чём собираетесь программировать, то и изучайте.{/post}{/quote}  
Ок, буду думать на чем буду программировать :-) и читать google =)
Страницы: 1 2 След.
Читают тему
Наверх