При разработке алгоритмов проведения документов в 1С:Предприятии 8.2 и 8.3 программисты часто сталкиваются с ситуацией, когда при отладке в коллекции движений поле НомерСтроки остается равным нулю. Попытка установить это значение вручную приводит к ошибке выполнения, а система при записи набора может выдавать невнятные сообщения о конфликте в строке №2. Разберем подробно, как устроены механизмы работы с номерами строк и почему возникают подобные проблемы.
Первое, что нам необходимо усвоить: поле НомерСтроки в регистрах сведений является автоматическим системным полем. Проанализируем специфику его поведения:
ОбработкаПроведения), значения в этом поле всегда будут равны 0.Движение.НомерСтроки = 1) система выдает ошибку: «Поле не предназначено для записи».Рассмотрим ситуацию: если вы видите ошибку в духе «запись с номером строки 2 не может быть сохранена», это почти всегда означает, что проблема не в самом номере, а в дублировании ключевых полей (измерений).
Посмотрим на пример кода, который часто становится причиной подобных затруднений. Проанализируем типичный фрагмент формирования движений:
Для Каждого ТекСтрокаСотрудники Из Сотрудники Цикл
Движение = Движения.АИС_ПодписантыОрганизаций.Добавить;
Движение.Период = Дата;
Движение.Организация = Организация; // Убедитесь, что здесь нет опечаток
Движение.Действительна = Истина;
Движение.Сотрудник = ТекСтрокаСотрудники.Сотрудник;
Движение.Приоритет = ТекСтрокаСотрудники.Приоритет;
// Пытаться записывать НомерСтроки здесь нельзя!
КонецЦикла;
В данном коде, если в табличной части Сотрудники окажутся две строки с одинаковым сотрудником (при условии, что Сотрудник — единственное измерение), система не сможет записать такой набор. Поскольку НомерСтроки не является ключом уникальности в регистре сведений, платформа «споткнется» на попытке добавить вторую запись с идентичными измерениями.
Выясним причину, по которой ошибки могут возникать при использовании запросов к виртуальным таблицам (например, СрезПоследних) внутри ОбработкиПроведения. Рассмотрим опасный сценарий:
СрезПоследних считывает данные, включая те, что уже записаны этим же документом ранее.Чтобы избежать этой ситуации, всегда используйте метод Очистить() перед началом формирования новых записей и взводите флаг записи:
Движения.АИС_ПодписантыОрганизаций.Записывать = Истина;
Движения.АИС_ПодписантыОрганизаций.Очистить();
// Далее следует текст запроса и цикл заполнения
Также важно в запросах к регистру сведений добавлять условие исключения текущего регистратора, чтобы не «читать самих себя»:
Запрос.Текст = "ВЫБРАТЬ ... ГДЕ Регистратор <> &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Разберем по шагам, как гарантированно избежать ошибок с номерами строк и дублями:
Шаг 1. Проверьте структуру регистра. Убедитесь, что все поля, которые вы считаете уникальными, действительно являются измерениями, а не ресурсами или реквизитами. Если Сотрудник — это ресурс, то в регистре может быть только одна запись на одну организацию в одну секунду (для периодических регистров).
Шаг 2. Используйте таблицы значений для подготовки данных. Вместо прямого добавления строк в движения, можно сначала сформировать ТаблицуЗначений, свернуть ее по измерениям (метод Свернуть()) для исключения дублей, а затем загрузить в регистр:
ТЗ_Движений = Движения.АИС_ПодписантыОрганизаций.ВыгрузитьКолонки();
// Заполняем ТЗ данными в цикле...
ТЗ_Движений.Свернуть("Организация, Сотрудник", "Приоритет"); // Удаляем дубли по ключам
Движения.АИС_ПодписантыОрганизаций.Загрузить(ТЗ_Движений);
Шаг 3. Контролируйте флаг записи. Если вы используете стандартный механизм проведения, достаточно установить Движения.ИмяРегистра.Записывать = Истина;. Если же вы вызываете Движения.ИмяРегистра.Записать(); принудительно внутри кода, помните, что повторная запись в конце процедуры (автоматическая) может привести к ошибкам блокировок, если не соблюдена осторожность.
Шаг 4. Внимание при копировании. Если вы создали документ путем копирования существующего, обязательно проверьте свойства самого объекта метаданных. Иногда «наследство» в виде установленных флагов в свойствах «Движения» (например, режим «Записывать выбранные») может конфликтовать с вашим программным кодом.
Проанализировав ситуацию, мы видим, что «ошибка в номере строки» — это лишь симптом, указывающий на логическое дублирование записей. Следуя правилам очистки движений, исключения текущего документа из запросов и контроля уникальности измерений, вы обеспечите стабильную работу механизмов проведения.