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

Программист IT и автоматизация бизнеса
← На главную

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

Разбор основных инструментов: ТекущаяСтрока и ТекущиеДанные

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

Проанализируем ситуацию: нам нужно получить целую табличную часть (например, «Товары»), которой нет и не может быть в плоском списке документов. Значит, нам нужно взять ТекущаяСтрока (ссылку), передать её на сервер и там уже «достать» нужные данные.

Решение через запрос на сервере (оптимальный способ)

Рассмотрим наиболее производительный вариант. Вместо того чтобы считывать весь объект документа (что нагружает память), мы воспользуемся запросом к базе данных. Это позволит нам получить только те колонки табличной части, которые нам действительно нужны.

Предположим, у нас есть кнопка «Добавить» и таблица на форме с именем Товары. Разберем по шагам реализацию обработчика:


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

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

В данном примере мы использовали функцию ЗаполнитьЗначенияСвойств. Это очень удобный метод: если имена полей в результате запроса совпадают с именами колонок вашей таблицы на форме, 1С автоматически подставит значения. Это избавляет от необходимости писать НоваяСтрока.Товар = Выборка.Товар для каждого поля.

Решение через получение объекта (упрощенный способ)

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


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

Важные нюансы и типичные ошибки

Рассмотрим ситуацию, с которой столкнулся автор темы: «Данные загружаются сразу из всех документов». Выясним причину. Обычно это происходит, если в запросе пропущено условие ГДЕ Ссылка = &Ссылка. Без этого условия запрос выберет строки всех документов данного типа, существующих в базе. Всегда проверяйте наличие этого фильтра.

Еще один важный момент: при работе с управляемыми формами старайтесь минимизировать количество контекстных серверных вызовов. Если вам нужно просто получить данные и вы не планируете изменять реквизиты самой формы (кроме целевой таблицы), рассмотрите возможность использования &НаСервереБезКонтекста. В этом случае ссылку на документ и саму таблицу (или массив структур с данными) придется передавать как параметры.

Работа с множественным выделением

Проанализируем ситуацию, когда пользователь хочет выделить не один, а сразу пять документов через клавишу Shift или Ctrl и нажать «Добавить». Свойство ТекущаяСтрока вернет только одну последнюю строку. Чтобы обработать все выделенные строки, рассмотрите использование коллекции ВыделенныеСтроки.


&НаКлиенте
Процедура ДобавитьНесколько(Команда)
    
    МассивСсылок = Элементы.СписокДокументов.ВыделенныеСтроки;
    
    Если МассивСсылок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    ЗаполнитьИзМассиваНаСервере(МассивСсылок);
    
КонецПроцедуры

На сервере в этом случае запрос будет использовать оператор В вместо =:

ГДЕ РеализацияТовары.Ссылка В (&МассивСсылок)

Заключение

Мы рассмотрели эффективный алгоритм переноса данных из списка документов в таблицу значений. Подведем итог: наиболее правильным подходом является получение ссылки через ТекущаяСтрока, выполнение запроса к конкретной табличной части на сервере и последующее заполнение коллекции формы. Использование ЗаполнитьЗначенияСвойств делает ваш код чище, а работа через запросы обеспечивает высокую скорость работы приложения даже при больших объемах данных.

← На главную