В разработке на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с аппаратными ограничениями интерфейса. Одно из наиболее известных ограничений — отсутствие полноценной объектной модели для работы с элементами формы «на лету». В частности, возникают сложности при попытке программно управлять фокусом в журналах документов после выполнения поиска.
Представим типичную ситуацию: в журнале документов мы открываем кастомную форму поиска (например, взамен стандартного поиска по номеру). После того как нужный документ найден, нам необходимо спозиционировать на нем курсор в журнале и сделать так, чтобы пользователь мог сразу открыть его нажатием клавиши Enter. Однако, если до этого фокус ввода находился на кнопке формы поиска, стандартная таблица журнала теряет активность. Метод Форма.ТекущаяКолонка() возвращает пустое значение, а метод активации не срабатывает должным образом. При нажатии клавиши Enter вместо открытия документа система повторно открывает форму поиска, так как фокус остался на управляющем элементе.
В этой статье мы подробно разберем, как обойти это ограничение, рассмотрим структуру колонок журналов документов и проанализируем четыре практических способа решения проблемы.
Прежде чем перейти к решениям, выясним причину, почему стандартная объектная модель 1С 7.7 не позволяет легко получить список колонок открытой формы журнала. Дело в том, что на форме реального журнала могут присутствовать элементы трех разных типов, которые метаданные конфигурации «не видят» как единую коллекцию колонок:
ДатаДок, ВремяДок, НомерДок, ВидДок).Метаданные.Журнал(i).Графа(j).Идентификатор.Если мы попытаемся вызвать метод Конт.Активизировать(ИмяКолонки), передав туда пустую строку или неверный идентификатор, система либо проигнорирует команду, либо вызовет ошибку времени выполнения. Поэтому нам нужны надежные обходные пути.
Наиболее простое и элегантное решение, не требующее изменения метаданных или использования внешних компонент, заключается в проверке текущей колонки и подмене её на стандартный системный реквизит в случае потери фокуса.
Как мы уже выяснили, в любом журнале гарантированно присутствует колонка даты документа с идентификатором "ДатаДок". Если пользователь потерял фокус (например, перешел в модальное окно поиска), метод ТекущаяКолонка() вернет пустоту. В этом случае мы принудительно устанавливаем фокус на колонку даты.
Разберем по шагам реализацию этого алгоритма в коде:
// Позиционируем журнал на найденном документе
Конт.АктивизироватьОбъект(НайденныйДокумент);
// Пытаемся получить колонку, которая была активна до поиска
ТекКолонка = Конт.Form.ActiveControl(); // Для некоторых контекстов или используем:
ТекКолонка = Конт.Форма.ТекущаяКолонка();
// Если фокус был потерян и колонка не определена
Если ПустоеЗначение(ТекКолонка) = 1 Тогда
// Активизируем гарантированно существующую колонку даты
ТекКолонка = "ДатаДок";
КонецЕсли;
// Возвращаем фокус в таблицу журнала на нужную колонку
Конт.Активизировать(ТекКолонка, 0);
Этот метод хорош тем, что он абсолютно безопасен, работает во всех конфигурациях «из коробки» и решает главную задачу — возвращает фокус в табличное поле журнала. Теперь при нажатии клавиши Enter документ откроется в обычном режиме.
Если вы разрабатываете собственную конфигурацию или имеете возможность редактировать существующую, рекомендуется применить профессиональный архитектурный прием — создание специальной «технической» колонки-якоря.
Рассмотрим этот процесс по шагам:
"Старт" или "Фокус".0 или 1. Визуально для пользователя она станет полностью невидимой.
Конт.АктивизироватьОбъект(НайденныйДокумент);
// Гарантированно активизируем невидимый якорь в начале строки
Конт.Aктивизировать("Старт", 0);
Преимущество этого подхода заключается в стабильности интерфейса. Фокус гарантированно возвращается в левую часть таблицы журнала, строка выделяется целиком, и интерфейс программы выглядит аккуратно и предсказуемо для конечного пользователя.
Для конфигураций, в которых нельзя менять метаданные, а фокусировка на конкретной колонке "ДатаДок" визуально не устраивает (например, колонка даты находится в середине или в конце таблицы), можно использовать программную эмуляцию клавиш управления фокусом.
Когда фокус находится на кнопке поиска, нам достаточно один раз нажать клавишу Tab (или Shift+Tab в зависимости от порядка обхода элементов формы), чтобы фокус переместился обратно в таблицу журнала. Сделать это можно двумя путями.
Вариант А. Через стандартный Windows Script Host (WshShell):
// Создаем объект для работы с операционной системой
Шелл = СоздатьОбъект("WScript.Shell");
// Позиционируем на объекте
Конт.АктивизироватьОбъект(НайденныйДокумент);
// Посылаем нажатие клавиши TAB для перехода фокуса в таблицу
Шелл.SendKeys("{TAB}");
Важное замечание: Данный способ имеет недостаток. Если пользователь в момент выполнения кода случайно переключит активное окно операционной системы, имитация нажатия клавиши отправится в другое приложение.
Вариант Б. Через внешнюю компоненту FormEx:
Если в вашей базе используется популярная библиотека расширения возможностей интерфейса FormEx, вы можете выполнить имитацию нажатия клавиши внутри потока самого приложения 1С, что абсолютно безопасно:
Сервис = СоздатьОбъект("Сервис");
Конт.АктивизироватьОбъект(НайденныйДокумент);
// Безопасно имитируем нажатие клавиши Tab внутри 1С (код клавиши 9)
Сервис.ИмитироватьНажатиеКлавиши(9);
Для сложных систем автоматизации отличным решением является перевод стандартных журналов документов на объектные таблицы класса ТабличноеПоле (с использованием связки ВК FormEx и 1С++).
Этот подход полностью заменяет стандартный рендеринг списков 1С 7.7. Объект ТабличноеПоле предоставляет полноценный программный интерфейс к своим колонкам:
ТабличноеПоле.ПолучитьКолонку(1).Имя.Хотя этот метод требует существенной переработки интерфейсной части конфигурации, он полностью решает любые проблемы с позиционированием, поиском и кастомизацией внешнего вида журналов.
Мы проанализировали проблему активации колонок журналов в 1С 7.7 и рассмотрели практические способы ее решения. Для быстрой и надежной работы без изменения конфигурации лучше использовать Решение 1 (активация резервной колонки "ДатаДок"). Если вы разрабатываете конфигурацию с нуля или имеете к ней полный доступ — используйте Решение 2 со скрытой колонкой-якорем для обеспечения максимальной стабильности интерфейса.