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

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

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

Анализ структуры данных и постановка задачи

Представим ситуацию: у нас есть основной документ Заявка. В нем три табличные части (ТЧ): одна главная (например, Заявка с перечнем продукции) и две подчиненные (например, Технологии). Нам нужно в другом документе, ОтчетСотрудника, при нажатии кнопки Добавить в его ТЧ Работа вызывать список выбора. Этот список должен содержать комбинированные данные: Продукция + Технология + Характеристики, чтобы пользователь мог выбрать нужную строку одним кликом.

Шаг 1. Оптимизация получения данных через запрос

Рассмотрим типичную ошибку начинающих разработчиков — выполнение запросов внутри цикла. Проанализируем ситуацию: если мы сначала получаем список продукции, а потом в цикле для каждой продукции ищем технологии, это создает лишнюю нагрузку на базу данных. Вместо этого мы используем Левое соединение в одном запросе. Это позволит нам сразу получить готовую таблицу со всеми возможными комбинациями.

Выясним, как составить правильный запрос, который объединит данные из двух табличных частей документа-источника:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ЗаявкаТехнологии.Технологии КАК Технология,
    |    ЗаявкаЗаявка.Продукция КАК Продукция,
    |    ЗаявкаЗаявка.РазмерФормат КАК РазмерФормат,
    |    ЗаявкаТехнологии.Количество КАК Количество
    |ИЗ
    |    Документ.Заявка.Заявка КАК ЗаявкаЗаявка
    |        ЛЕВОЕ СОЕДИНЕНИЕ Документ.Заявка.Технологии КАК ЗаявкаТехнологии
    |        ПО ЗаявкаЗаявка.Ссылка = ЗаявкаТехнологии.Ссылка 
    |        И ЗаявкаЗаявка.Продукция = ЗаявкаТехнологии.Продукция
    |ГДЕ
    |    ЗаявкаЗаявка.Ссылка = &СсылкаЗаявка";

Запрос.УстановитьПараметр("СсылкаЗаявка", Объект.ДокументОснование);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();

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

Шаг 2. Организация интерактивного выбора

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

Проанализируем программную реализацию выбора:


ВыбраннаяСтрока = РезультатЗапроса.ВыбратьСтроку("Выберите технологию из списка");

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

Использование метода ЗаполнитьЗначенияСвойств значительно упрощает код. Он автоматически копирует данные из колонок таблицы запроса в колонки табличной части документа, если их имена совпадают (например, Технология, Количество и т.д.).

Шаг 3. Фильтрация списка в зависимости от контекста

Часто требуется, чтобы список выбора был не общим, а зависел от того, какая продукция уже выбрана в текущей строке документа. Посмотрим, как это реализовать. Если в табличной части Работа уже указана продукция, мы можем передать её в параметры запроса, чтобы ограничить выбор.

Разберем вариант с фильтрацией:


// Допустим, мы вызываем это из события НачалоВыбора или ПриИзменении
ТекущиеДанные = Элементы.Работа.ТекущиеДанные;

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ЗаявкаТехнологии.Технологии КАК Технология,
    |    ЗаявкаТехнологии.Количество КАК Количество
    |ИЗ
    |    Документ.Заявка.Технологии КАК ЗаявкаТехнологии
    |ГДЕ
    |    ЗаявкаТехнологии.Ссылка = &СсылкаЗаявка
    |    И ЗаявкаТехнологии.Продукция = &Продукция";

Запрос.УстановитьПараметр("СсылкаЗаявка", Объект.Заявка);
Запрос.УстановитьПараметр("Продукция", ТекущиеДанные.Продукция);

ТаблицаДляВыбора = Запрос.Выполнить().Выгрузить();
ВыбраннаяТехнология = ТаблицаДляВыбора.ВыбратьСтроку();

Если ВыбраннаяТехнология <> Неопределено Тогда
    ТекущиеДанные.Технология = ВыбраннаяТехнология.Технология;
    ТекущиеДанные.Количество = ВыбраннаяТехнология.Количество;
КонецЕсли;

Шаг 4. Улучшение интерфейса для управляемых форм

Если ваша конфигурация работает на управляемых формах (интерфейс "Такси"), использование ВыбратьСтроку() может быть неудобным или недоступным (из-за модальности). В таком случае мы рекомендуем использовать СписокЗначений с методом ПоказатьВыборЭлемента().

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


СписокВыбора = Новый СписокЗначений;

Для Каждого СтрокаТЗ Из ТаблицаДляВыбора Цикл
    Представление = СтрШаблон("%1 (%2) - %3 шт.", 
        СтрокаТЗ.Продукция, 
        СтрокаТЗ.Технология, 
        СтрокаТЗ.Количество);
    
    // В значение кладем структуру или саму строку ТЗ для последующего разбора
    СписокВыбора.Добавить(СтрокаТЗ, Представление);
КонецЦикла;

// В управляемом приложении используем описание оповещения для немодального вызова
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораТехнологии", ЭтотОбъект);
СписокВыбора.ПоказатьВыборЭлемента(ОписаниеОповещения, "Выберите технологию");

В этом случае пользователь увидит понятный текст, такой как "Вывеска из акрила (Гравировка) - 1 шт.", что сводит к минимуму риск ошибки при вводе данных.

Полезные советы по работе с данными ТЧ

Для того чтобы ваша система работала стабильно и быстро, придерживайтесь следующих правил:

  1. Имена колонок: Старайтесь называть колонки в запросе (через псевдоним КАК) точно так же, как они называются в табличной части. Это позволит использовать ЗаполнитьЗначенияСвойств максимально эффективно.
  2. Проверка на пустые значения: Перед выполнением запроса всегда проверяйте, заполнено ли поле Заявка (ссылка-основание). Если ссылка пустая, запрос не вернет данных, и пользователю стоит вывести предупреждение.
  3. Индексация: Если документов Заявка очень много и в каждой ТЧ сотни строк, убедитесь, что поля, по которым идет соединение (например, Продукция), проиндексированы в метаданных (свойство "Индексировать").
  4. Кэширование: Если пользователь часто открывает список выбора в одном и том же документе, можно один раз получить таблицу технологий при открытии формы и сохранить её в реквизит формы или ВременноеХранилище. Это избавит систему от повторных обращений к базе данных при каждом нажатии кнопки "Добавить".

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

← На главную