Исключения в 1С

Конструкция Попытка-Исключение-КонецПопытки

Если в модуле на встроенном языке 1С будет ошибка времени выполнения, например деление на 0, то выполнение модуля будет прервано и на экран будет выведено сообщение об ошибке:

&НаКлиенте
Процедура Команда1(Команда)
	а = 5/0;
КонецПроцедуры

Ошибки времени выполнения (run time) — это ошибки во время выполнения модуля. Еще есть ошибки времени компиляции (compile time) — это ошибки во время компиляции модуля.

Для обработки ошибок времени выполнения можно использовать исключения:

&НаКлиенте
Процедура Команда1(Команда)
	Попытка
		а = 5/0;
	Исключение
		Сообщить("Нельзя делить на 0");
	КонецПопытки;	
КонецПроцедуры

Если в коде после ключевого слова Попытка будет ошибка времени выполнения, то выполнение программы перейдет на первую строку после ключевого слова Исключение. Если ошибок не будет, то код после ключевого слова Исключение даже не будет выполнен.

Конструкцию Попытка-Исключение-КонецПопытки нельзя использовать для обработки ошибок времени компиляции. Такой модуль все равно не будет скомпилирован:

&НаКлиенте
Процедура Команда1(Команда)
	Попытка
		а = 5/0;+ //здесь ошибка
	Исключение
		Сообщить("Нельзя делить на 0");
	КонецПопытки;	
КонецПроцедуры

Вызовы процедур и функций внутри попытки тоже будут обработаны:

&НаКлиенте
Процедура Команда1(Команда)
	Попытка
		ПоделитьНаНоль();
	Исключение
		Сообщить("Нельзя делить на 0");
	КонецПопытки;	
КонецПроцедуры
 
&НаКлиенте
Процедура ПоделитьНаНоль()
	а = 5/0;	
КонецПроцедуры

В 1С используется единый механизм для обработки всех исключений, как исключений платформы, так и исключений конфигураций. То есть при возникновении ошибки времени выполнения платформа начинает искать ближайший оператор Исключение, относящийся к данному блоку кода. Если ошибка произошла на строке, который не был обернут в конструкцию Попытка-Исключение, но после этой строки есть такая конструкция — ошибка не будет обработана этой конструкцией. Если такой оператор найден, то ошибка будет обработана им. Если не найден, то ошибка обрабатывается платформой, выполнение модуля останавливается.

Оператор ВызватьИсключение

Попытки могут быть вложенными:

&НаКлиенте
Процедура Команда1(Команда)
	Попытка
		ПоделитьНаНоль();
	Исключение
		Сообщить("Нельзя делить на 0");
	КонецПопытки;	
КонецПроцедуры
 
&НаКлиенте
Процедура ПоделитьНаНоль()
	Попытка
		а = 5/0;	
	Исключение
		Сообщить("Ошибка в процедуре");	
	КонецПопытки;	
КонецПроцедуры

Если выполнить данный код, то выйдет сообщение «Ошибка в процедуре», то есть код из первого исключения даже не будет выполнен. Чтобы выполнялся код из вышестоящего исключения нужно использовать оператор ВызватьИсключение:

&НаКлиенте
Процедура Команда1(Команда)
	Попытка
		ПоделитьНаНоль();
	Исключение
		Сообщить("Нельзя делить на 0");
	КонецПопытки;	
КонецПроцедуры
 
&НаКлиенте
Процедура ПоделитьНаНоль()
	Попытка
		а = 5/0;	
	Исключение
		ВызватьИсключение;	
	КонецПопытки;	
КонецПроцедуры

В этом случае исключение будет проброшено вверх по стеку и обработано первым блоком Попытка-Исключение.

Можно вызывать исключение из кода оператором ВызватьИсключение. Выполнение кода будет прервано, на экране будет сообщение с текстом исключения:

&НаКлиенте
Процедура Команда1(Команда)
	ВызватьИсключение "Исключение вызванное из кода";	
КонецПроцедуры

Информация об ошибке

В 1С нельзя использовать несколько блоков Исключений для разных типов ошибки. Какая бы ошибка не произошла всегда будет вызываться код после оператора Исключение. Для получения описания ошибки можно использовать метод ОписаниеОшибки():

&НаКлиенте
Процедура Команда1(Команда)
	Попытка
		а = 4/0;	
	Исключение
		Сообщить(ОписаниеОшибки());
	КонецПопытки;	
КонецПроцедуры

Пример с другим типом ошибки:

&НаКлиенте
Процедура Команда1(Команда)
	Попытка
		а = ПредопределенноеЗначение("Справочник.Склады.ОсновнойСклад");
		//при этом такого предопределенного элемента нет
	Исключение
		Сообщить(ОписаниеОшибки());
	КонецПопытки;	
КонецПроцедуры

Но правильней использовать метод ИнформацияОбОшибке(), который вернет объект типа ИнформацияОбОшибке:

&НаКлиенте
Процедура Команда1(Команда)
	Попытка
		а = 4/0;
	Исключение
		Инф = ИнформацияОбОшибке();
		//объект типа ИнформацияОбОшибке передаем 
		//в метод КраткоеПредставлениеОшибки()
		//для вывода сообщения на экран
		Сообщить(КраткоеПредставлениеОшибки(Инф));
	КонецПопытки;	
КонецПроцедуры

Метод КраткоеПредставлениеОшибки() выведет более понятное для обычного пользователя сообщение: «Деление на 0» вместо «{Обработка.Обработка1.Форма.Форма.Форма(5)}: Деление на 0».

Для более полного описания ошибки можно использовать метод ПодробноеПредставлениеОшибки():

&НаКлиенте
Процедура Команда1(Команда)
	Попытка
		а = 4/0;
	Исключение
		Инф = ИнформацияОбОшибке();
		//объект типа ИнформацияОбОшибке передаем 
		//в метод ПодробноеПредставлениеОшибки()
		//для вывода подробного сообщения на экран
		Сообщить(ПодробноеПредставлениеОшибки(Инф));
	КонецПопытки;	
КонецПроцедуры

Но правильней пользователю сообщать кратное представление, а в журнал регистрации записывать подробное представление ошибки:

&НаКлиенте
Процедура Команда1(Команда)
	//ЗаписьЖурналаРегистрации доступно только на сервере
	Команда1НаСервере();	
КонецПроцедуры
 
&НаСервере
Процедура Команда1НаСервере()
	Попытка
		а = 4/0;
	Исключение
		Инф = ИнформацияОбОшибке();
		//сообщим пользователю
		Сообщить(КраткоеПредставлениеОшибки(Инф));
		//и запишем в журнал регистрации
		ПодробнаяОшибка = ПодробноеПредставлениеОшибки(Инф);
		ЗаписьЖурналаРегистрации("Ошибка", 
					  УровеньЖурналаРегистрации.Ошибка,,, 
					  ПодробнаяОшибка);
	КонецПопытки;	
КонецПроцедуры

Приведение к нужному типу

При загрузке числовых данных из файла (например из текстового документа) в 1С часто применяется такой прием для получения числа из строки:

&НаКлиенте
Процедура Команда1(Команда)
	//это строка с числом, допустим она была получена из файла
	ЧислоСтрокой = "123.45";
	Попытка	
		//пробуем перевести ее в число
		ЧислоЧислом = Число(ЧислоСтрокой);
	Исключение
		//если не получилось
		ЧислоЧислом = 0;
	КонецПопытки;
 
	//дальше работаем как с числом
	ЧислоЧислом = ЧислоЧислом + 1;
	Сообщить(ЧислоЧислом);
КонецПроцедуры

С точки зрения производительности это не совсем корректно. Правильно использовать объект ОписаниеТипов:

&НаКлиенте
Процедура Команда1(Команда)
	//это строка с числом, допустим она была получена из файла
	ЧислоСтрокой = "123.45";
 
	//создаем объект типа ОписаниеТипов с типом Число 
	ОписаниеТипа = Новый ОписаниеТипов("Число");
	//приводим строку к числу, если не получится вернет значение по умолчанию
	//для числа это 0
	ЧислоЧислом = ОписаниеТипа.ПривестиЗначение(ЧислоСтрокой);
 
	//дальше работаем как с числом
	ЧислоЧислом = ЧислоЧислом + 1;
	Сообщить(ЧислоЧислом);
КонецПроцедуры

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями: