ЗаписьЖурналаРегистрации |
Я |
10.11.09 — 13:34
Добрый день, ребята кто подскажет что я делаю не так. Из 8 ки по ОЛЕ соединяюсь с 7.7. в 7 ой базе создаю объект. Далее хочу в журнал 7ой базы записать событие создания объякта. Пишу База77.ЗаписьЖурналаРегистрации(«Создан новый объект»,»Refs»,»RefNew»,справочник77,2); справочник77 = База77.CreateObject(«Справочник.Номенклатура»);
1 — 10.11.09 — 13:35
не взлетит.
2 — 10.11.09 — 13:47
ща турбо надув дам и взлетит!
3 — 10.11.09 — 13:52
взлетит, если пнуть с подвывертом )
4 — 10.11.09 — 13:58
EvalExpr и ExecuteBatch еще никто не отменял )))
5 — 10.11.09 — 14:17
Щас протестю
6 — 10.11.09 — 15:10
База77.EvalExpr(«НайденныйОбъект=СоздатьОбъект(«»Справочник.Договоры»»);»)
{(1)}: Ошибка при вызове метода контекста (EvalExpr): Произошла исключительная ситуация (1С:Предприятие): 1 НайденныйОбъект<<?>>=СоздатьОбъект(«Справочник.Договоры»);
Переменная не определена (НайденныйОбъект)
не подскажете почему ругается, синтаксис правильный же
7 — 10.11.09 — 15:12
(6) CreateObject?
8 — 10.11.09 — 15:13
(7) смотри (0) надо взять ссылку на элемент 7 ки и подставить в процедуру регистрации события
9 — 10.11.09 — 15:13
(6) неправильно идею понял
10 — 10.11.09 — 15:14
(9) ммм, да? не подскажешь твою идею?
11 — 10.11.09 — 15:14
(8) ЗначениеИзСтрокиВнутр(ЗначениеВстрокуВнутр())
+ двойные кавычки учесть
12 — 10.11.09 — 15:15
(10) а может напрямую в mlg писать или режим разделенный?
13 — 10.11.09 — 15:16
(11) ну да, тема так можно передать объект. Но я вот выполнил запись в журнал без передачи объекта,и чет в журнал нече не добавилось.
14 — 10.11.09 — 15:16
(12) не напрямую не нужно писать
15 — 10.11.09 — 15:17
(14) жаль. такая идея пропадает
16 — 10.11.09 — 15:22
База77.ExecuteBatch(«ЗаписьЖурналаРегистрации(«»Создан новый объект»»,»»Refs»»,»»RefNew»»,ЗначениеИзСтрокиВнутр(«+База77.ЗначениеВстрокуВнутр(справочник77.ТекущийЭлемент())+»),2);»)
17 — 10.11.09 — 15:23
База77.ExecuteBatch(«ЗаписьЖурналаРегистрации(«»Создан новый объект»»,»»Refs»»,»»RefNew»»,ЗначениеИзСтрокиВнутр(«»»+СтрЗаменить(База77.ЗначениеВстрокуВнутр(справочник77.ТекущийЭлемент(),»»»»,»»»»»»))+»»»),2);»);
или так ))
18 — 10.11.09 — 15:24
ТекущийЭлемент() по оле вроде не летает?
19 — 10.11.09 — 15:29
Кто сказал?
20 — 10.11.09 — 15:29
(18) летает
21 — 10.11.09 — 15:29
напрямую нет, но обернутый летает
22 — 10.11.09 — 15:31
интересно а почему без объекта не записывается событие. в отладке показывает выполнение метода ExecuteBatch истина, а в списке журнала нече не появляется. Все фильтры выставлены по все да и период нормальный..
23 — 10.11.09 — 15:37
(15) эта идея давно реализована, у меня в том числе )
IF_THEN
24 — 10.11.09 — 15:38
в общем просто журнал регистраций настроен так что регистрируе пока только вход и выход))) p.s. на демке тестю
dk спасибо за инфо
В платформе 1С сообщения об ошибках бывают достаточно запутаны, и без должных навыков разобраться в причинах достаточно сложно. Вот и сообщение об ошибке при вызове контекста может ввести в ступор начинающего разработчика. Однако в подавляющем большинстве случаев мы видим подобное сообщение, если разработчик допустил ошибку в своем коде. Причем речь зачастую идет не об орфографических ошибках, а о логических.
Исправляем ситуацию
Чтобы избавиться от этого неприятного сообщения об ошибке при вызове метода контекста, следует понимать, что контекстом называют методы платформы 1С. Значит в определенной строке кода воспользовались методом с неверными параметрами или вызвали его не от того владельца. Всегда внимательно и полностью читайте сообщения об ошибках – часто в них содержится указание на строку и метод, вызвавший ошибку. Это поможет сэкономить время на отладку и поиск проблемного места в коде.
Рассмотрим действия разработчика на примере со специально допущенной ошибкой. Мы запускаем на исполнение нижеприведенный кусок кода с запросом, в котором забыли дописать условие отбора. Компилятор 1С пропускает такую процедуру, так как орфографических ошибок в написании команд мы не допустили. Однако в режиме предприятия нас ждет такое сообщение об ошибке:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.ВерсияДанных КАК ВерсияДанных,
| Номенклатура.ПометкаУдаления КАК ПометкаУдаления,
| Номенклатура.Родитель КАК Родитель,
| Номенклатура.ЭтоГруппа КАК ЭтоГруппа,
| Номенклатура.Код КАК Код,
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Артикул КАК Артикул,
| Номенклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
| Номенклатура.ТипНоменклатуры КАК ТипНоменклатуры,
| Номенклатура.Предопределенный КАК Предопределенный,
| Номенклатура.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| ";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
КонецЦикла;
Приведенный текст ошибки программисту 1С скажет, что в модуле формы обработки «ЧтениеЗаписьXML на 152 строчке кода не может выполниться запрос. Причина в том, что на 17 строчке запроса нет чего-то, что ждал компилятор. Таким образом, чтобы убрать подобное сообщение, необходимо выяснить, что там должно быть и написать недостающий код.
Увидев вышеприведенный кусок кода, разработчик заметит, что в запросе есть служебное слово «ГДЕ», дающее сигнал 1С, что дальше будет условие. Но мы забыли дописать его и, естественно, система с помощью сообщения об ошибке спрашивает нас – «а где условие?». Чтобы исправить эту ситуацию необходимо либо убрать оператор «ГДЕ» из запроса, либо добавить условие.
Но ошибки могут быть не только в текстах запросов. Допустим, мы хотим выбрать всю номенклатуру и узнать, входит ли она в определенную группу. Проверка происходит с помощью метода «ПринадлежитЭлементу» и его параметра, который должен быть типа СправочникСсылка. Мы опять допускаем ошибку и вместо ссылки в параметр метода помещаем строку, содержащую имя переменной.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.ВерсияДанных КАК ВерсияДанных,
| Номенклатура.ПометкаУдаления КАК ПометкаУдаления,
| Номенклатура.Родитель КАК Родитель,
| Номенклатура.ЭтоГруппа КАК ЭтоГруппа,
| Номенклатура.Код КАК Код,
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Артикул КАК Артикул,
| Номенклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
| Номенклатура.ТипНоменклатуры КАК ТипНоменклатуры,
| Номенклатура.Предопределенный КАК Предопределенный,
| Номенклатура.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа ";
НужнаяГруппаЭлементов = Справочники.Номенклатура.НайтиПоНаименованию("Мебель");
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Сообщить(ВыборкаДетальныеЗаписи.Ссылка.ПринадлежитЭлементу("НужнаяГруппаЭлементов"));
КонецЦикла;
1С выдает настолько же информативное сообщение, из которого мы понимаем, что на 158 строке у 1 параметра неправильный тип. Но что же делать, если мы не знаем, какой тип должен быть? В этом нам поможет Синтакс-помощник, встроенный в платформу 1С.
В конфигураторе находим строку и метод, на который указывало сообщение об ошибке, и нажимаем на него правой кнопкой мыши. Выбираем пункт «Поиск в синтакс-помощнике» и платформа самостоятельно ищет справочную информацию по выделенному методу. В справке мы видим не только подробное описание параметров и самого метода, но и пример. Сверив пример с нашим кодом, приходит понимание, что кавычки не нужны и без них все работает.
Чаще всего причиной подобных ошибок выступают следующие факторы:
- Невнимательность;
- Отсутствие опыта или знаний;
- Несогласованность действий разработчиков друг с другом;
- Изменения в методах контекста в новых версиях платформы.
Но ошибки при разработке ПО случаются постоянно, поскольку иногда ошибаются даже специалисты с многолетним опытом. Самое главное – уметь исправлять их и учиться на них. Постепенно вы будете видеть сообщения об ошибках все реже и научитесь замечать подобные «опечатки» еще до запуска 1С.
-
Всем привет!
Подскажите, пожалуйста, как решить проблему? У меня БП8.2 актуальный конфиг.
Дело в том, что я пользуюсь процедурой ВыгрузитьЖурналРегистрацииОтбор = Новый Структура("Метаданные", Метаданные.РегламентныеЗадания.Обмен_Логистика8_БИБ82); Задание = РегламентныеЗадания.ПолучитьРегламентныеЗадания(Отбор)[0]; ДатаНач = Задание.ПоследнееЗадание.Начало; ЗаписьЖурналаРегистрации("Обмен.Логистика.Загрузка",УровеньЖурналаРегистрации.Информация, , ,ДатаНач); ДатаКон = Задание.ПоследнееЗадание.Конец; ЗаписьЖурналаРегистрации("Обмен.Логистика.Загрузка",УровеньЖурналаРегистрации.Информация, , ,ДатаКон); Фильтр = Новый Структура("ДатаНачала, ДатаОкончания", ДатаНач, ДатаКон); Журнал = Новый ТаблицаЗначений; ВыгрузитьЖурналРегистрации(Журнал, Фильтр);
Когда вручную запускаю, то все ОК. Когда фоновое задание проходит этот код, то вылезает ошибка:
Ошибка при загрузке файла обмена: ****Logistic8-BIB82-Data_0000000765.xml. {Обработка.ДТ_Обмен_Логистика8_БИБ82.МодульОбъекта(288)}: Ошибка при вызове метода контекста (ВыгрузитьЖурналРегистрации): Недопустимое значение параметра (параметр номер ‘2’)Это как раз второй аргумент процедуры.
Не могу понять в чем дело. В журнал вывожу запись о том что помещается в Фильтр — все ОК — там две даты. Но ошибка все равно есть. Да, фоновое задание пробовал запускать от своего имени. -
Оказалось сам дурак (не удивительно как всегда). Когда запускал через обработку, то фоновое задание бралось предыдущее, а само фоновое задание видит себя, при этом ДатаОкончания не определена еще. И она не заполнялась.
-
Offline
nomad_irk
Гуру в 1С- Регистрация:
- 20 окт 2008
- Сообщения:
- 8.697
- Симпатии:
- 889
- Баллы:
- 204
ну как бы логично
дату окончания более определенно задайте и будет вам Щастье…..
Поделиться этой страницей
рубрики: Язык программирования 1С | Дата: 25 апреля, 2017
В прошлый раз мы рассмотрели простейший способ явной организации транзакций средствами встроенного языка 1С. На практике транзакции гораздо чаще используются совместно с конструкцией Попытка — Исключение. Это позволяет в случае ошибки продолжить выполнение кода, а также выдать адекватное сообщение об ошибке пользователю и записать информацию в журнал регистрации или в файл логов для последующего анализа администратором системы.
Если мы обратимся к технической документации или к диску ИТС, то увидим, что фирма 1С рекомендует следующий способ организации транзакции в попытке
Попытка
//1. Начало транзакции.
НачатьТранзакцию();
//2. Блок операций, выполняющихся в транзакции.
//3. Если все операции успешны, фиксируем транзакцию.
ЗафиксироватьТранзакцию();
Исключение
//4. Если при выполнении кода возникли ошибки, отменяем транзакцию.
ОтменитьТранзакцию();
//5. При необходимости запись в журнал регистрации.
//6. При необходимости вывод сообщения пользователю.
КонецПопытки;
Собственно каких-то особых пояснений код не требует. Если в процессе попытки выполнения транзакционного кода возникает ошибка, мы сразу проваливаемся в блок исключение, т.е. до метода ЗафиксироватьТранзакцию() мы просто не доходим. Ну а в исключении соответственно отменяем транзакцию и если это необходимо выводим сообщение об ошибке и записываем информацию в журнал регистрации. Фиксировать ошибки в журнале регистрации крайне желательно, особенно для тех операций, которые выполняются без участия пользователя (например, регламентные задания). Это позволит в дальнейшем проанализировать ошибку. Вместо записи в журнал регистрации можно организовать отправку сообщений администратору по электронной почте.
Теперь вооружившись новыми знаниями попробуем видоизменить код, рассмотренный в статье про простейшие транзакции. Напомню, что мы рассматривали запись в справочник Товары и в регистр сведений Цена по следующей схеме:
&НаСервереБезКонтекста
Процедура ВыполнитьТранзакциюНаСервере()
НачатьТранзакцию();
//записываем новый товар
Товар = Справочники.Товары.СоздатьЭлемент();
Товар.Наименование = "Дырокол";
Товар.Записать();
//записываем цену
НаборЗаписей = РегистрыСведений.Цена.СоздатьНаборЗаписей();
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ТекущаяДата();
НоваяЗапись.Товар = Товар.Ссылка;
НоваяЗапись.Сумма = 100;
НаборЗаписей.Записать();
ЗафиксироватьТранзакцию();
КонецПроцедуры
А теперь поместим транзакцию в блок Попытка Исключение. Скорее всего ошибки могут возникнуть только в момент записи в справочник или в регистр сведений, поэтому предварительную подготовку вынесем за пределы транзакции.
&НаСервереБезКонтекста
Процедура ВыполнитьТранзакциюНаСервере()
//создаем новый товар
Товар = Справочники.Товары.СоздатьЭлемент();
Товар.Наименование = "Дырокол";
//Создаем запись с ценой
НаборЗаписей = РегистрыСведений.Цена.СоздатьНаборЗаписей();
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ТекущаяДата();
НоваяЗапись.Сумма = 100;
//Выполняем транзакцию в попытке
Попытка
НачатьТранзакцию();
Товар.Записать();
НоваяЗапись.Товар = Товар.Ссылка;
НаборЗаписей.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Произошла ошибка при записи товара и его цены";
Сообщение.Сообщить();
ЗаписьЖурналаРегистрации("Произошла ошибка при записи товара и его цены");
КонецПопытки;
КонецПроцедуры
Как НЕ НАДО делать
У тех кто только начинает работать с транзакциями зачастую возникает желание сделать вот таким образом
НачатьТранзакцию();
Попытка
НачатьТранзакцию();
//Блок операций
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
КонецПопытки;
Попытка
НачатьТранзакцию();
//Блок операций
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
КонецПопытки;
ЗафиксироватьТранзакцию();
Или в цикле
НачатьТранзакцию();
Для каждого Данные Из МассивДанных Цикл
Попытка
НачатьТранзакцию();
Данные.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
КонецПопытки;
КонецЦикла;
ЗафиксироватьТранзакцию();
На первый взгляд мы сделали все в соответствии с рекомендациями фирмы 1С. Но дело в том, что платформа 1С не поддерживает вложенные транзакции. То есть чисто технически так писать можно. Но при этом все вложенные транзакции не образуют новые, а относятся к той же самой транзакции верхнего уровня. Таким образом, если в одной из вложенных транзакций произойдет ошибка, следующую вложенную транзакцию нельзя будет зафиксировать. Система выдаст сообщение вида: «В данной транзакции уже происходили ошибки!». Продемонстрируем это на примере. Допустим мы решили записать два товара, каждый в своей транзакции. И сделаем эти транзакции вложенными в третью. Далее искусственно вызовем ошибку в первой транзакции с помощью метода ВызватьИсключение:
&НаСервереБезКонтекста
Процедура ВыполнитьТранзакциюНаСервере()
НачатьТранзакцию();
Попытка
НачатьТранзакцию();
Товар = Справочники.Товары.СоздатьЭлемент();
Товар.Наименование = "Стол";
Товар.Записать();
ВызватьИсключение "Ошибка записи товара.";
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ОписаниеОшибки();
Сообщение.Сообщить();
КонецПопытки;
Попытка
НачатьТранзакцию();
Товар = Справочники.Товары.СоздатьЭлемент();
Товар.Наименование = "Стул";
Товар.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ОписаниеОшибки();
Сообщение.Сообщить();
КонецПопытки;
ЗафиксироватьТранзакцию();
КонецПроцедуры
В результате выполнения этой процедуры увидим в окне сообщений следующее:
{ВнешняяОбработка.ТранзакцииВПопытке.Форма.Форма.Форма(20)}: Ошибка записи товара.
{ВнешняяОбработка.ТранзакцииВПопытке.Форма.Форма.Форма(40)}: Ошибка при вызове метода контекста (Записать): В данной транзакции уже происходили ошибки!
Таким образом, организация вложенных транзакций в 1С абсолютно бессмысленна.
Возможные варианты
Теперь вернемся к варианту, где мы записывали товар и цену для него. Если у нас при выполнении транзакции произойдет ошибка, то будет трудно понять в какой момент она произошла — при записи товара или при записи цены, поскольку и то и другое происходит в рамках одной попытки. Чтобы определить место возникновения ошибки, нам надо каждую операцию записи заключить в свою собственную попытку и при этом избежать вложенных транзакций. Для этого введем булеву переменную Отказ и в зависимости от ее значения в конце всех операций будем фиксировать или отменять транзакцию.
&НаСервереБезКонтекста
Процедура ВыполнитьТранзакциюНаСервере()
// Начинаем транзакцию
Отказ = Ложь;
НачатьТранзакцию();
// Пытаемся записать товар
Попытка
Товар = Справочники.Товары.СоздатьЭлемент();
Товар.Наименование = "Дырокол";
Товар.Записать();
Исключение
Отказ = Истина;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Ошибка при записи товара";
Сообщение.Сообщить();
КонецПопытки;
// Пытаемся записать цену
Попытка
НаборЗаписей = РегистрыСведений.Цена.СоздатьНаборЗаписей();
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ТекущаяДата();
НоваяЗапись.Товар = Товар.Ссылка;
НоваяЗапись.Сумма = 100;
НаборЗаписей.Записать();
Исключение
Отказ = Истина;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Ошибка при записи цены";
Сообщение.Сообщить();
КонецПопытки;
// Фиксируем или отменяем транзакцию
Если НЕ Отказ Тогда
ЗафиксироватьТранзакцию();
Иначе
ОтменитьТранзакцию();
КонецЕсли;
КонецПроцедуры
Аналогичным образом можно поступить и когда мы перебираем и записываем какие-либо данные в цикле. В этом случае мы сможем получить перечень всех данных с ошибками, если такие будут.