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