Как заполнить табличную часть документа из другого документа в 1С:Бухгалтерия 3.0?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет
← На главную

В процессе разработки в конфигурации 1С:Бухгалтерия 3.0 часто возникает задача автоматизации ввода данных. Типичный сценарий: необходимо перенести данные из табличной части документа ПоступлениеТоваровУслуг (ПТУ) в документ ОтчетПроизводстваЗаСмену (ОПЗС), например, на вкладку «Услуги». При этом важно не просто скопировать строки, но и правильно сопоставить аналитику, такую как номенклатура и счета учета.

В этой статье мы подробно разберем, как реализовать механизм заполнения через внешнюю обработку и расширение конфигурации, проанализируем типичные ошибки клиент-серверного взаимодействия и научимся правильно строить запросы к данным документов.

Разбор архитектурной ошибки: Клиент против Сервера

Прежде чем приступать к коду, проанализируем одну из самых распространенных ошибок начинающих разработчиков, упомянутую в обсуждении. При попытке вызвать форму выбора документа из кода расширения часто возникает ошибка: Процедура или функция с указанным именем не определена (Открытьформу).

Выясним причину: в платформе «1С:Предприятие 8.3» на управляемых формах существует строгое разделение контекстов. Функция ОткрытьФорму является клиентским методом. Если вы пытаетесь вызвать ее в процедуре с директивой компиляции &НаСервере, система выдаст ошибку. Рассмотрим правильную структуру вызова:


&НаКлиенте
Процедура Расш1_ЗаполнитьИзПоступления(Команда)
    // Открытие формы выбора документа-источника
    ПараметрыВыбора = Новый Структура;
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораДокумента", ЭтотОбъект);
    ОткрытьФорму("Документ.ПоступлениеТоваровУслуг.ФормаВыбора", ПараметрыВыбора, ЭтотОбъект, , , , Оповещение);
КонецПроцедуры

Использование ОписаниеОповещения позволяет программе «дождаться» выбора пользователя и передать выбранную ссылку в следующую процедуру для обработки.

Реализация через внешнюю обработку заполнения (БСП)

Наиболее корректным и безопасным способом решения задачи является создание внешней обработки с видом ЗаполнениеОбъекта. Это позволяет не вносить изменения в конфигурацию и не использовать расширения там, где это не критично. Рассмотрим структуру модуля объекта такой обработки.

Сначала опишем функцию регистрации в системе в соответствии со стандартами Библиотеки стандартных подсистем (БСП):


Функция СведенияОВнешнейОбработке() Экспорт
    РегистрационныеДанные = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("1.0.0.0");
    РегистрационныеДанные.Назначение.Добавить("Документ.ОтчетПроизводстваЗаСмену");
    РегистрационныеДанные.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиЗаполнениеОбъекта();
    
    НовКоманда = РегистрационныеДанные.Команды.Добавить();
    НовКоманда.Представление = "Заполнить из Поступления (услуги)";
    НовКоманда.Идентификатор = "ЗаполнитьИзПоступления";
    НовКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
    
    Возврат РегистрационныеДанные;
КонецФункции

Обратите внимание на тип команды ОткрытиеФормы. Это позволит нам создать собственную форму, где пользователь выберет нужный документ ПоступлениеТоваровУслуг.

Логика получения данных из документа-источника

Теперь проанализируем, как правильно получить данные из табличной части документа. Использование запроса — это наиболее эффективный метод, особенно если требуется фильтрация данных (например, выбор только определенных услуг). Рассмотрим пример функции, которая возвращает массив структур с данными:


&НаСервереБезКонтекста
Функция ПолучитьДанныеИзПоступления(СсылкаНаДокумент)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ПоступлениеУслуги.Номенклатура КАК Субконто1,
        |	ПоступлениеУслуги.Количество КАК Количество,
        |	ПоступлениеУслуги.Цена КАК ПлановаяСтоимость,
        |	ПоступлениеУслуги.Сумма КАК СуммаПлановая,
        |	ПоступлениеУслуги.СчетУчетаЗатрат КАК СчетЗатрат
        |ИЗ
        |	Документ.ПоступлениеТоваровУслуг.Услуги КАК ПоступлениеУслуги
        |ГДЕ
        |	ПоступлениеУслуги.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);
    
    ТаблицаРезультат = Запрос.Выполнить().Выгрузить();
    Возврат ОбщегоНазначения.ТаблицаЗначенийВМассив(ТаблицаРезультат);
КонецФункции

Важный нюанс: обратите внимание на псевдонимы полей в запросе (КАК Субконто1). Это позволяет нам использовать метод ЗаполнитьЗначенияСвойств, чтобы автоматически сопоставить поля из запроса с полями табличной части Услуги в документе ОтчетПроизводстваЗаСмену.

Перенос данных в форму документа

После того как мы получили данные в виде массива, нам нужно перенести их в форму основного документа. Если мы работаем из внешней формы обработки, обращение к документу-владельцу происходит через ВладелецФормы.


&НаКлиенте
Процедура ВыполнитьЗаполнение(Команда)
    Если НЕ ЗначениеЗаполнено(ВыбранныйДокументПТУ) Тогда
        Возврат;
    КонецЕсли;

    ДанныеТЧ = ПолучитьДанныеИзПоступления(ВыбранныйДокументПТУ);
    
    // Получаем доступ к табличной части документа Отчет производства за смену
    ОбъектДокумента = ВладелецФормы.Объект;
    ТЧ_Услуги = ОбъектДокумента.Услуги;
    
    ТЧ_Услуги.Очистить();
    
    Для Каждого СтрокаДанных Из ДанныеТЧ Цикл
        НоваяСтрока = ТЧ_Услуги.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДанных);
        
        // Дополнительная логика: заполнение специфических полей
        НоваяСтрока.НоменклатурнаяГруппа = ОбъектДокумента.НоменклатурнаяГруппа;
    КонецЦикла;
КонецПроцедуры

Проблема заполнения аналитики (Субконто)

Рассмотрим подробнее вопрос заполнения поля Субконто1. В документе ОтчетПроизводстваЗаСмену на вкладке «Услуги» аналитика затрат зависит от выбранного счета. Если используется счет 20.01 («Основное производство»), то Субконто1 обычно соответствует справочнику НоменклатурныеГруппы, а не самой номенклатуре услуги.

Рекомендация: Если ваша цель — видеть в затратах конкретную услугу из поступления, убедитесь, что в плане счетов для выбранного счета затрат настроено соответствующее субконто (например, справочник Номенклатура). В противном случае, при программном заполнении возникнет несоответствие типов, и поле останется пустым.

Если же стоит задача найти конкретную услугу по наименованию (как предлагалось в одном из сообщений форума), используйте метод НайтиПоНаименованию, но помните о рисках: при изменении названия в справочнике код перестанет работать. Правильнее передавать ссылку на номенклатуру напрямую из документа-источника.

Итоги и лучшие практики

Мы проанализировали процесс создания механизма заполнения табличной части и выяснили следующее:

  1. Используйте внешние обработки заполнения для сохранения чистоты конфигурации и удобства обновлений.
  2. Всегда разделяйте логику: получение данных — на сервере через запрос, манипуляции с интерфейсом и открытие форм — на клиенте.
  3. Для связи полей разных документов используйте псевдонимы в запросах и метод ЗаполнитьЗначенияСвойств. Это сокращает объем кода и делает его более читаемым.
  4. При работе с расширениями внимательно следите за контекстом выполнения процедур, чтобы избежать ошибок отсутствия функций.
  5. Всегда проверяйте типы данных в полях Субконто, так как они динамически зависят от выбранного счета учета.

Следуя этим шагам, вы сможете реализовать надежный механизм переноса данных, который упростит работу бухгалтера и минимизирует количество ошибок ручного ввода.

← На главную