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