Многие разработчики при адаптации конфигурации 1С:Зарплата и Управление Персоналом 3.1 под нужды пользователей сталкиваются со странным поведением системы. Попытка стандартным образом добавить колонку в форму списка или форму выбора справочника Сотрудники оканчивается неудачей: новое поле, добавленное в динамический список в конфигураторе, упорно отказывается выводиться на экран в пользовательском режиме. При этом в настройках «Изменить форму» добавленное поле также отсутствует.
В этой статье мы подробно разберем, почему так происходит, развеем мифы о несуществующих обработках в новых релизах и рассмотрим два проверенных способа решения проблемы: простой пользовательский и продвинутый программный с использованием расширения конфигурации.
Для начала проанализируем поведение системы. Начиная с версии ЗУП 3.1.5, разработчики фирмы «1С» провели масштабную оптимизацию производительности интерфейсов. Основная логика работы со списками сотрудников была вынесена в специализированные общие модули.
Когда пользователь открывает форму списка или выбора справочника Сотрудники, платформа выполняет обработчик события ПриСозданииНаСервере. Внутри этого обработчика вызываются процедуры общего модуля (такие как СотрудникиФормыРасширенный или метод УстановитьЗапросДинамическогоСписка), которые полностью перезаписывают исходный текст запроса динамического списка, заданный разработчиком в конфигураторе. Программа на лету генерирует новый текст SQL-запроса в зависимости от текущих настроек кадрового учета, прав пользователя и активных функциональных опций.
В результате любые ваши ручные изменения динамического списка в конфигураторе просто «затираются» на сервере перед выводом формы клиенту. Именно поэтому колонка пропадает, а в дереве доступных полей формы ее нет.
В процессе обсуждения подобных проблем на форумах часто можно встретить советы вроде: «Вам нужно править не форму списка справочника, а форму обработки СписокСотрудников».
Давайте проясним этот момент. В старых версиях (переходных редакциях ЗУП 3.0) действительно функционировала самостоятельная обработка СписокСотрудников. Однако в современных релизах ЗУП 3.1 (включая версии 3.1.12, 3.1.18, 3.1.23 и новее) этой обработки физически нет в метаданных. Упоминания о ней в коде (например, в модулях документов начисления зарплаты или подбора) остались исключительно как «рудименты» для обеспечения обратной совместимости при обновлении со старых конфигураций. Основным рабочим объектом является именно форма списка самого справочника — Справочник.Сотрудники.Форма.ФормаСписка.
Ниже мы рассмотрим два практических варианта решения задачи по выводу новых данных в эту форму.
Если вам требуется вывести стандартное поле, которое логически связано с сотрудником или его физическим лицом (например, ДатаРождения, ИНН, СНИЛС, Пол, Гражданство), вносить изменения в конфигурацию или писать код вообще не нужно. Платформа «1С:Предприятие 8.3» позволяет сделать это силами пользователя:
Физическое лицо, разверните его по «плюсу» и отметьте галочкой нужное свойство (например, Дата рождения).Этот способ идеален, так как он не требует программирования и сохраняет конфигурацию полностью типовой. Однако он имеет ограничение: таким образом нельзя вытащить данные из сторонних регистров сведений, не связанных напрямую со справочником через реквизиты.
Рассмотрим более сложную задачу. Предположим, вам нужно вывести в список сотрудников информацию из вашего собственного регистра сведений (например, РегистрСведений.ДополнительныеСведенияОСотрудниках, где хранится текстовое поле СтатусПроверки).
Чтобы не снимать конфигурацию с поддержки, мы решим эту задачу с помощью расширения конфигурации. Нам потребуется программно модифицировать динамически формируемый запрос списка и динамически добавить элемент формы.
Разберем процесс реализации по шагам:
Создайте новое расширение в конфигураторе (или используйте существующее). Заимствуйте в него форму списка справочника сотрудников: Справочники -> Сотрудники -> Форма -> ФормаСписка.
Нам необходимо перехватить событие создания формы на сервере, дождаться, пока типовые механизмы сформируют окончательный текст запроса для динамического списка, а затем внедрить туда наше соединение с регистром.
В модуле заимствованной формы списка сотрудников создадим обработчик события ПриСозданииНаСервере с аннотацией &После:
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Получаем текущий программно сформированный текст запроса динамического списка
ИсходныйТекстЗапроса = Список.ТекстЗапроса;
// Определяем текст нашего левого соединения с регистром сведений
ТекстСоединения = "
|ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведенияОСотрудниках КАК ДопСведения
|ПО Источник.Ссылка = ДопСведения.Сотрудник";
// Внедряем левое соединение в блок ИЗ.
// Находим ключевую фразу ""ИЗ Справочник.Сотрудники КАК Источник"" и дополняем её нашим соединением.
НовыйТекстЗапроса = СтрЗаменить(
ИсходныйТекстЗапроса,
"ИЗ Справочник.Сотрудники КАК Источник",
"ИЗ Справочник.Сотрудники КАК Источник " + ТекстСоединения
);
// Добавляем выборку нужного поля из регистра в секцию ВЫБРАТЬ.
// Позиционируемся на поле Источник.Ссылка и дописываем наше поле.
НовыйТекстЗапроса = СтрЗаменить(
НовыйТекстЗапроса,
"Источник.Ссылка КАК Ссылка,",
"Источник.Ссылка КАК Ссылка, ЕСТЬNULL(ДопСведения.СтатусПроверки, """") КАК СтатусПроверки,"
);
// Возвращаем измененный текст запроса обратно в динамический список
Список.ТекстЗапроса = НовыйТекстЗапроса;
КонецПроцедуры
В результате этого кода динамический список формы теперь будет выполнять SQL-запрос с учетом нашего левого соединения и возвращать поле СтатусПроверки.
После того как поле добавлено в динамический список, нам нужно отобразить его на форме в виде колонки таблицы. Если не сделать этого программно, поле будет доступно только в режиме ручной настройки формы пользователем.
Допишем код в ту же процедуру Расш1_ПриСозданииНаСервере сразу после изменения текста запроса:
// Проверяем, не был ли элемент уже добавлен ранее (для надежности)
Если Элементы.Найти("СписокСтатусПроверки") = Неопределено Тогда
// Добавляем новое поле формы в родительскую группу ""Список""
НоваяКолонка = Элементы.Добавить("СписокСтатусПроверки", Тип("ПолеФормы"), Элементы.Список);
// Задаем вид элемента - Поле ввода (для отображения текста)
НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
// Связываем элемент формы с полем нашего динамического списка
НоваяКолонка.ПутьКДанным = "Список.СтатусПроверки";
// Настраиваем визуальные свойства колонки
НоваяКолонка.Заголовок = "Статус проверки";
НоваяКолонка.Ширина = 15;
НоваяКолонка.ТолькоПросмотр = Истина; // Запрещаем редактирование прямо из списка
// Опционально: перемещаем колонку в начало списка или после определенной колонки.
// Например, поместим ее сразу после колонки ""Ссылка"" (ФИО сотрудника)
Элементы.Переместить(НоваяКолонка, Элементы.Список, Элементы.СписокСсылка);
КонецЕсли;
Проанализируем этот программный блок: мы используем метод платформы Элементы.Добавить(), чтобы динамически создать новый визуальный элемент типа ПолеФормы. Затем мы жестко привязываем его к источнику данных динамического списка с помощью свойства ПутьКДанным. С помощью метода Переместить() мы четко позиционируем новую колонку на форме, чтобы она органично смотрелась в интерфейсе кадровика.
Использование метода программной замены текста запроса через функции автозамены (СтрЗаменить) накладывает определенные обязательства при последующих обновлениях конфигурации 1С:ЗУП.
Если фирма «1С» в очередном релизе изменит исходную конструкцию выборки (например, переименует псевдоним таблицы Источник во что-то другое), ваша функция СтрЗаменить не найдет искомую подстроку, и колонка перестанет отображаться. Рекомендуется сопровождать такой код обработкой исключений или логированием, чтобы оперативно выявлять возможные проблемы при переходе на новые релизы.