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