Как программно заполнить новый объект (документ или справочник) на основании выбранных строк в управляемой форме

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Способ 1. Получение данных одной строки через ТекущиеДанные

Если задача подразумевает создание объекта на основе только одной активной (выделенной в данный момент) строки, мы используем свойство расширения таблицы ТекущиеДанные. Важно помнить, что это свойство доступно только на клиенте. Рассмотрим алгоритм действий:

  1. На клиенте получаем данные строки.
  2. Извлекаем ссылку на объект-источник.
  3. Передаем ссылку на сервер для создания нового объекта.

Проанализируем пример кода для клиентской процедуры:


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

Способ 2. Работа с множественным выделением строк

Если пользователю нужно выбрать несколько строк и на основании каждой (или всех вместе) создать объект, свойство ТекущиеДанные не подойдет, так как оно возвращает только одну активную строку. В этом случае мы используем коллекцию ВыделенныеСтроки.

Разберем, как правильно собрать ссылки из выделенных строк:


&НаКлиенте
Процедура СоздатьОбъектыИзСписка(Команда)
    
    ВыделенныеСтроки = Элементы.СписокДокументов.ВыделенныеСтроки;
    МассивСсылок = Новый Массив;
    
    Для Каждого ИдентификаторСтроки Из ВыделенныеСтроки Цикл
        // Получаем данные конкретной строки по её идентификатору
        ДанныеСтроки = Элементы.СписокДокументов.ДанныеСтроки(ИдентификаторСтроки);
        Если ДанныеСтроки <> Неопределено Тогда
            МассивСсылок.Добавить(ДанныеСтроки.Ссылка);
        КонецЕсли;
    КонецЦикла;
    
    Если МассивСсылок.Количество() > 0 Тогда
        СоздатьОбъектыНаСервере(МассивСсылок);
    КонецЕсли;
    
КонецПроцедуры

Способ 3. Эффективное копирование данных и работа с ТЧ

Когда ссылка передана на сервер, нам нужно создать новый объект и заполнить его. Рассмотрим ситуацию, когда нужно перенести не только основные реквизиты («шапку»), но и табличные части (ТЧ).

Использование метода ЗаполнитьЗначенияСвойств

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

Копирование табличных частей

Частая ошибка начинающих разработчиков — попытка перебора строк ТЧ на клиенте. Правильно делать это на сервере, используя методы Выгрузить() и Загрузить(). Это позволяет скопировать всю таблицу одной командой.

Посмотрим на пример серверной реализации:


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

Способ 4. Использование метода Скопировать()

Если новый объект должен быть практически идентичен старому, мы можем применить метод Скопировать(). Он создает полную копию объекта, включая все табличные части.


НовыйОбъект = СсылкаИсточник.Скопировать();
// После копирования можно очистить или изменить конкретные поля
НовыйОбъект.Номер = ""; 
НовыйОбъект.Записать();

Внимание: Будьте осторожны с этим методом, если в объекте есть уникальные идентификаторы или статусы, которые не должны переноситься в новый документ.

Профессиональный подход: Использование ОбработкиЗаполнения

Наиболее правильным с точки зрения архитектуры 1С является использование стандартного механизма заполнения. В модуле объекта (документа или справочника), который вы создаете, нужно прописать логику в процедуре ОбработкаЗаполнения.

В этом случае на клиенте достаточно вызвать создание формы с параметром Основание:


&НаКлиенте
Процедура СоздатьЧерезОснование(Команда)
    ПараметрыЗаполнения = Новый Структура("Основание", Элементы.Список.ТекущиеДанные.Ссылка);
    ОткрытьФорму("Документ.ИмяДокумента.ФормаОбъекта", ПараметрыЗаполнения);
КонецПроцедуры

А в модуле объекта нового документа проанализируем параметр ДанныеЗаполнения:


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

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

← На главную