Как программно открыть форму нужного документа из таблицы значений в обычных формах 1С

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

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

Разбор типичной ошибки: почему открывается новый документ?

Рассмотрим ситуацию, когда при щелчке по строке вызывается метод ОткрытьФорму с указанием типа документа. Если в функцию передается только путь к форме, например, Документ.Продавцы.Форма.ФормаДокумента, платформа воспринимает это как команду на создание нового объекта. Чтобы открыть существующий документ, системе необходимо передать Ссылку на этот конкретный объект в базе данных.

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


Процедура ПродажиПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
    ОткрытьФорму("Документ.Продавцы.Форма.ФормаДокумента"); // Это создаст новый документ
КонецПроцедуры

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

Решение №1: Использование события «Выбор» и метода ОткрытьЗначение

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

  1. Выделим элемент управления «Табличное поле» на форме.
  2. В свойствах перейдем к событиям и создадим обработчик Выбор.
  3. Установим параметр СтандартнаяОбработка = Ложь, чтобы предотвратить системные действия 1С.
  4. Вызовем функцию ОткрытьЗначение.

Посмотрим на пример кода:


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

Функция ОткрытьЗначение универсальна: она сама определяет тип объекта, находит его основную форму и открывает ее для просмотра или редактирования.

Решение №2: Использование метода ПолучитьФорму (классика обычных форм)

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


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

Обратите внимание: в обычных формах мы обращаемся к данным строки через параметр события ВыбраннаяСтрока или через ЭлементыФормы.ВашаТаблица.ТекущиеДанные. Оба варианта вернут нам структуру данных текущей строки ТЗ.

Решение №3: Скрытая колонка со ссылкой (Best Practice)

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

  1. При заполнении таблицы значений запросом обязательно выбирайте поле Ссылка.
  2. Добавьте колонку Ссылка в табличное поле на форме.
  3. В свойствах этой колонки снимите галочку Видимость.

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

Проблема поиска по дате: нюансы со временем

Если архитектура решения не позволяет хранить ссылку и вы вынуждены искать документ по дате, помните о критической особенности 1С: тип данных Дата всегда содержит время (час, минута, секунда). Если в вашей таблице дата документа отображается как «23.08.2024», это не значит, что в базе документ записан ровно на 00:00:00.

Выясним причину, почему запрос может не находить документ:


// ОПАСНО: Поиск по точному совпадению даты
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Документ.Продавцы ГДЕ Дата = &Дата";

Если документ создан в 15:30:22, а вы передаете в параметр дату начала дня, запрос вернет пустой результат. Чтобы решить эту проблему, используйте поиск в интервале дня:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	Ссылка
    |ИЗ
    |	Документ.Продавцы
    |ГДЕ
    |	Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) И КОНЕЦПЕРИОДА(&Дата, ДЕНЬ)
    |	И Номер = &Номер"; // Дополнительный фильтр по номеру для точности

Запрос.УстановитьПараметр("Дата", ТекущаяСтрока.ДатаИзТЗ);
Запрос.УстановитьПараметр("Номер", ТекущаяСтрока.НомерИзТЗ);

Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
    Выборка = Результат.Выбрать();
    Выборка.Следующий();
    ОткрытьЗначение(Выборка.Ссылка);
КонецЕсли;

Подведем итоги

Для открытия формы существующего документа в обычных формах 1С всегда стремитесь использовать прямую ссылку на объект. Использование скрытых колонок в таблице значений — это наиболее производительный и надежный метод. Если же вы вынуждены использовать поиск по реквизитам, всегда учитывайте наличие времени в дате документа и используйте функцию НАЧАЛОПЕРИОДА в запросах, чтобы избежать пустых результатов.

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

← На главную