Почему форма выбора возвращает массив чисел вместо ссылок на документы и как это исправить

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

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

Выясним причину: почему возвращаются индексы?

Основным механизмом отображения данных в управляемых формах является Динамический список. Когда мы открываем форму в режиме выбора, платформа ожидает, что основной реквизит формы сможет однозначно идентифицировать выбранную строку. За это отвечает свойство динамического списка ОсновнаяТаблица.

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

Однако, если мы используем произвольный запрос, объединяющий несколько типов документов (например, через оператор ОБЪЕДИНИТЬ ВСЕ), свойство ОсновнаяТаблица часто остается пустым. В этом случае платформа не "знает", какое из полей запроса является уникальным идентификатором. По умолчанию она начинает возвращать внутренние идентификаторы строк динамического списка, которые в программном коде выглядят как обычные числа (индексы).

Решение 1: Использование журнала документов

Проанализируем самый правильный с точки зрения архитектуры 1С способ. Если перед нами стоит задача выбора из нескольких типов документов (например, «Входящее письмо» и «Исходящее письмо»), рекомендуется использовать Журнал документов.

Разберем по шагам, почему это эффективно:

  1. Типизация: Журнал документов изначально предназначен для объединения ссылок разных типов в одну таблицу.
  2. Производительность: Данные в журнале индексированы, что обеспечивает быстрый поиск и отбор.
  3. Стандартное поведение: Если динамический список в форме выбора опирается на таблицу журнала, свойство ОсновнаяТаблица будет указывать на этот журнал, и ссылки будут возвращаться корректно без дополнительного кода.

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

Решение 2: Явное указание ключевых полей

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

Посмотрим на настройки динамического списка в конфигураторе:

  1. Откроем форму выбора и выберем основной реквизит (обычно это Список с типом ДинамическийСписок).
  2. В окне свойств нажмем на ссылку "Настройка списка".
  3. В открывшемся конструкторе перейдем на вкладку Ключевые поля.
  4. Установим флаг напротив поля Ссылка (или того поля, которое содержит ссылку на документ).

Важный нюанс: Чтобы это работало, поле со ссылкой должно присутствовать в тексте запроса. Если запрос объединяет разные таблицы, убедимся, что поле во всех частях ОБЪЕДИНИТЬ называется одинаково.

Решение 3: Программный перехват выбора

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

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


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

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

Решение 4: Обработка множественного выбора

Ситуация усложняется, когда пользователь должен выбрать сразу несколько документов. Как мы помним из описания проблемы, в этом случае форма возвращает массив индексов. Рассмотрим, как правильно собрать массив ссылок перед закрытием формы.

Для этого лучше всего переопределить команду выбора или создать свою кнопку "Ок/Выбрать". Проанализируем код обхода выделенных строк:


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

Здесь важно использовать метод ДанныеСтроки(), так как он позволяет получить доступ к полям динамического списка по идентификатору (тому самому числу), который возвращает коллекция ВыделенныеСтроки.

Особенности работы с произвольными запросами

Разберем еще один тонкий момент. Если вы используете произвольный запрос с объединением типов, убедитесь, что поле Ссылка имеет составной тип, включающий все выбираемые документы. Рассмотрим пример правильной структуры запроса в динамическом списке:


ВЫБРАТЬ
    Док.Ссылка КАК Ссылка,
    Док.Дата КАК Дата,
    Док.Номер КАК Номер,
    "Приход" КАК ТипОперации
ИЗ
    Документ.ПриходныйКассовыйОрдер КАК Док

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Док.Ссылка,
    Док.Дата,
    Док.Номер,
    "Расход"
ИЗ
    Документ.РасходныйКассовыйОрдер КАК Док

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

Резюме и рекомендации

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

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

← На главную