При разработке интерфейсов на обычных формах (толстый клиент) часто возникает задача: предоставить пользователю возможность открыть документ, кликнув по строке в таблице значений. Начинающие разработчики часто сталкиваются с тем, что вместо открытия конкретного существующего документа система создает новый «пустой» объект. В этой статье мы подробно разберем, как правильно реализовать переход к нужному документу, проанализируем типичные ошибки при поиске объектов по реквизитам и рассмотрим наиболее эффективные методы программирования этой задачи.
Рассмотрим ситуацию, когда при щелчке по строке вызывается метод ОткрытьФорму с указанием типа документа. Если в функцию передается только путь к форме, например, Документ.Продавцы.Форма.ФормаДокумента, платформа воспринимает это как команду на создание нового объекта. Чтобы открыть существующий документ, системе необходимо передать Ссылку на этот конкретный объект в базе данных.
Проанализируем некорректный код:
Процедура ПродажиПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
ОткрытьФорму("Документ.Продавцы.Форма.ФормаДокумента"); // Это создаст новый документ
КонецПроцедуры
Помимо неверного метода, здесь выбрано неподходящее событие — ПриНачалеРедактирования. Оно срабатывает, когда пользователь пытается изменить данные в ячейке, что не всегда совпадает с намерением просто «открыть» документ. Для этих целей лучше использовать событие Выбор.
Это самый простой и правильный способ, если в вашей таблице значений (ТЗ) уже содержится колонка со ссылкой на документ. Рассмотрим алгоритм действий:
Выбор.СтандартнаяОбработка = Ложь, чтобы предотвратить системные действия 1С.ОткрытьЗначение.Посмотрим на пример кода:
Процедура ПродажиВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Отменяем стандартное поведение
// Предполагаем, что в ТЗ есть колонка "СсылкаНаДокумент"
Если ЗначениеЗаполнено(ВыбраннаяСтрока.СсылкаНаДокумент) Тогда
ОткрытьЗначение(ВыбраннаяСтрока.СсылкаНаДокумент);
КонецЕсли;
КонецПроцедуры
Функция ОткрытьЗначение универсальна: она сама определяет тип объекта, находит его основную форму и открывает ее для просмотра или редактирования.
Если нам нужно больше контроля над процессом (например, передать в форму специфические параметры или открыть форму не в модальном режиме), мы воспользуемся методом ПолучитьФорму от самого объекта ссылки. Разберем этот пример подробнее:
Процедура ПродажиВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
СсылкаНаОбъект = ВыбраннаяСтрока.СсылкаНаДокумент;
Если СсылкаНаОбъект.Пустая() Тогда
Возврат;
КонецЕсли;
// Получаем форму конкретного документа
Форма = СсылкаНаОбъект.ПолучитьФорму("ФормаДокумента");
Если Форма <> Неопределено Тогда
Форма.Открыть();
КонецЕсли;
КонецПроцедуры
Обратите внимание: в обычных формах мы обращаемся к данным строки через параметр события ВыбраннаяСтрока или через ЭлементыФормы.ВашаТаблица.ТекущиеДанные. Оба варианта вернут нам структуру данных текущей строки ТЗ.
Часто программисты пытаются найти документ по косвенным признакам — дате или номеру, которые видны пользователю в таблице. Это плохая практика, так как поиск в базе данных при каждом клике замедляет работу системы. Проанализируем правильный архитектурный подход:
Ссылка.Ссылка в табличное поле на форме.Таким образом, ссылка всегда будет доступна в ТекущиеДанные, но не будет перегружать интерфейс пользователя лишней информацией.
Если архитектура решения не позволяет хранить ссылку и вы вынуждены искать документ по дате, помните о критической особенности 1С: тип данных Дата всегда содержит время (час, минута, секунда). Если в вашей таблице дата документа отображается как «23.08.2024», это не значит, что в базе документ записан ровно на 00:00:00.
Выясним причину, почему запрос может не находить документ:
// ОПАСНО: Поиск по точному совпадению даты
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Документ.Продавцы ГДЕ Дата = &Дата";
Если документ создан в 15:30:22, а вы передаете в параметр дату начала дня, запрос вернет пустой результат. Чтобы решить эту проблему, используйте поиск в интервале дня:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Ссылка
|ИЗ
| Документ.Продавцы
|ГДЕ
| Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) И КОНЕЦПЕРИОДА(&Дата, ДЕНЬ)
| И Номер = &Номер"; // Дополнительный фильтр по номеру для точности
Запрос.УстановитьПараметр("Дата", ТекущаяСтрока.ДатаИзТЗ);
Запрос.УстановитьПараметр("Номер", ТекущаяСтрока.НомерИзТЗ);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
ОткрытьЗначение(Выборка.Ссылка);
КонецЕсли;
Для открытия формы существующего документа в обычных формах 1С всегда стремитесь использовать прямую ссылку на объект. Использование скрытых колонок в таблице значений — это наиболее производительный и надежный метод. Если же вы вынуждены использовать поиск по реквизитам, всегда учитывайте наличие времени в дате документа и используйте функцию НАЧАЛОПЕРИОДА в запросах, чтобы избежать пустых результатов.
Помните, что использование ОткрытьЗначение() или ПолучитьФорму().Открыть() гарантирует, что пользователь увидит именно тот документ, который соответствует строке в его таблице, что исключает ошибки дублирования данных.