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