Как получить ссылку на документ из выделенной строки или нескольких строк на форме списка документов?

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

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

Часть 1. Получение ссылки на один выбранный документ (Текущая строка)

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

Способ 1. Использование свойства ТекущаяСтрока

Если у вашего динамического списка (который выведен на форму в виде таблицы) в конфигураторе заполнено свойство «Основная таблица» (например, указано Документ.ПоступлениеТоваровУслуг), то свойство ТекущаяСтрока содержит непосредственно ссылку на этот документ. Выясним, как это выглядит в коде:


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

Способ 2. Использование свойства ТекущиеДанные

Если динамический список построен на основе произвольного запроса и у него не задана «Основная таблица», то свойство ТекущаяСтрока вернет не ссылку на документ, а внутренний идентификатор строки (ключ строки). Чтобы гарантированно получить ссылку в таком случае, мы обращаемся к свойству ТекущиеДанные:


&НаКлиенте
Процедура ПолучитьСсылкуЧерезДанные(Команда)
    ТекущиеДанные = Элементы.Список.ТекущиеДанные;
    
    Если ТекущиеДанные <> Неопределено Тогда
        СсылкаНаДокумент = ТекущиеДанные.Ссылка;
        // Работаем со ссылкой...
    КонецЕсли;
КонецПроцедуры

Анализ типичных ошибок при получении одиночной ссылки

Разберем классические ошибки, с которыми сталкиваются разработчики при написании кода.

Ошибка №1: Ошибка передачи данных XDTO (тип 'ПолеФормы')

Очень часто программисты пытаются получить ссылку напрямую из элемента управления формы, обращаясь к нему по имени, например: этаформа.Элементы.СписокДокументыПоступленияСсылка. При попытке передать этот параметр на сервер или в метод открытия формы возникает ошибка:

«Ошибка преобразования данных XDTO: Запись значения свойства 'val'... Отсутствует отображение для типа 'ПолеФормы'».

Причина: Элементы формы (ПолеФормы) — это визуальные объекты интерфейса. Их нельзя передавать между клиентом и сервером. Передавать можно только чистые типы данных (в данном случае саму ссылку типа ДокументСсылка), которая извлекается через свойства ТекущаяСтрока или ТекущиеДанные.Ссылка, как показано в примерах выше.

Ошибка №2: Поле объекта не обнаружено (Ссылка)

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

Решение: В конфигураторе откройте свойства вашего динамического списка, перейдите в настройки полей запроса и для поля Ссылка установите флаг «Использовать всегда». Платформа начнет принудительно передавать это поле на клиент, даже если колонка скрыта пользователем в настройках формы.

Часть 2. Получение ссылок при множественном выделении строк

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

Шаг 1. Включение режима множественного выделения

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

Шаг 2. Универсальный алгоритм обхода выделенных строк на клиенте

Для получения массива выделенных строк используется свойство ВыделенныеСтроки таблицы. Посмотрим на универсальный код получения массива ссылок на клиенте, который корректно работает независимо от того, задана ли «Основная таблица» у динамического списка:


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

Часть 3. Передача выделенных документов в запрос на сервере

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

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


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

Важный нюанс: Свойства колонок и "Использовать всегда"

Если вы рассчитываете простые итоги прямо на клиенте без обращения к серверу (например, суммируете числовые значения колонок, как показано в Сообщении 9 форума), обязательно помните:

  1. Если пользователь скроет колонку (например, «Влажность» или «Вес») через настройки формы («Изменить форму...»), то в свойстве ДанныеСтроки(Идентификатор) это свойство примет значение Неопределено или вызовет ошибку отсутствия поля.
  2. Чтобы избежать подобных падений интерфейса, всегда устанавливайте свойство «Использовать всегда» в свойствах полей динамического списка в конфигураторе для всех реквизитов, участвующих в расчетах.

Альтернатива: Получение данных всего списка с учетом фильтров пользователя

Иногда пользователи просят показать итоги по выделенным строкам, но на самом деле им нужны итоги по всему списку с учетом наложенных ими фильтров, поиска и отборов. Заставлять бухгалтера вручную выделять тысячи строк неудобно.

Для решения этой задачи в современных версиях платформы 1С (начиная с 8.3.6) используется механизм компоновки данных динамического списка прямо на сервере. Рассмотрим, как программно получить все данные из списка с учетом пользовательских настроек:


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

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

← На главную