Каждый разработчик 1С, работающий с управляемыми формами и расширениями конфигурации, рано или поздно сталкивается с загадочным поведением платформы: вы добавляете новый элемент на форму в расширении (например, декорацию-надпись, кнопку или целую страницу), запускаете режим «1С:Предприятие» — все отображается отлично. Но стоит вам изменить текст надписи, цвет шрифта или вовсе удалить этот элемент из расширения, как в пользовательском режиме продолжает упорно отображаться старая «фантомная» версия элемента. Даже полное отключение расширения порой не помогает избавиться от некогда добавленной декорации.
В этой статье мы подробно разберем, почему возникает этот эффект «зависания» элементов, как устроена внутренняя архитектура платформы «1С:Предприятие 8.3» в части работы с управляемыми формами, и рассмотрим практические способы решения этой проблемы как для одного разработчика, так и для всех пользователей работающей базы данных.
Для того чтобы понять, откуда берется «неудаляемый» элемент, давайте проанализировать, как платформа 1С строит интерфейс управляемой формы в режиме «Предприятие». Этот процесс нельзя назвать простым чтением одного XML-файла. На самом деле финальный вид формы, который видит пользователь на своем экране, формируется путем последовательного наложения трех независимых слоев:
Когда мы впервые открываем измененную форму в режиме «Предприятие», платформа видит добавленную нами в расширении декорацию и отображает ее. В этот же момент структура формы (включая эту новую декорацию) записывается в специальную системную таблицу базы данных — Хранилище системных настроек (SystemSettingsStorage). Это делается для того, чтобы при последующих открытиях формы интерфейс отрисовывался мгновенно, с учетом всех персональных настроек пользователя.
Если мы затем возвращаемся в конфигуратор, меняем текст декорации с «123» на «456» или вовсе удаляем ее, платформа при запуске «Предприятия» снова обращается к третьему слою — сохраненным настройкам в базе данных. Она видит там старую структуру формы, в которой прописан элемент с заголовком «123», и принудительно восстанавливает его «как было». В итоге мы получаем конфликт: в конфигураторе элемента нет (или он другой), а на экране пользователя он присутствует в неизменном первозданном виде.
Часто разработчики путают два разных понятия: локальный кэш платформы на компьютере и пользовательские настройки в базе данных. Давайте разберем разницу между ними, чтобы применять правильные инструменты для решения проблемы:
AppData\Local\1C и AppData\Roaming\1C). Если вы обновили код или изменили свойства объектов, а у пользователя запускается старая версия, то помогает очистка этих папок или запуск базы с параметром /ClearCache в дополнительных параметрах запуска./ClearCache здесь не помогут, поскольку настройки загружаются сервером 1С напрямую из базы данных при каждой авторизации пользователя.Если вы ведете разработку или тестирование и столкнулись с тем, что форма не реагирует на изменения в расширении, выполните следующие шаги для сброса настроек текущего пользователя:
После этого платформа сотрет персональную сохраненную структуру формы из хранилища настроек для вашего пользователя, заново прочитает актуальные метаданные из расширения и отобразит корректный интерфейс с обновленной декорацией (или удалит ее).
Метод ручного сброса идеален для разработчика, но совершенно не подходит для живой базы, в которой работают десятки или сотни сотрудников. Мы не можем зайти под каждым пользователем и вручную сбросить настройки формы. Для массового решения проблемы в типовых конфигурациях (таких как «Управление нашей фирмой», «ERP», «Комплексная автоматизация» или «Бухгалтерия предприятия») предусмотрен специальный инструмент администратора.
Рассмотрим по шагам, как очистить настройки формы для всех пользователей сразу:
Этот способ позволяет гарантированно доставить ваши изменения в расширении до конечных пользователей без вмешательства в их персональные настройки отчетов или рабочего стола — сбросится только визуальное представление конкретной формы.
В некоторых случаях (например, если конфигурация сильно доработана или не является типовой) административного интерфейса для очистки настроек может не оказаться под рукой. Тогда мы можем написать небольшую обработку и выполнить очистку настроек программным путем на встроенном языке 1С.
Для удаления сохраненных настроек формы для всех пользователей базы данных мы можем использовать следующий код:
// Процедура очищает сохраненные настройки конкретной формы для всех пользователей базы данных
Процедура ОчиститьНастройкиФормыПрограммно() Экспорт
// Указываем полное системное имя формы, настройки которой нужно сбросить
ПолноеИмяФормы = "Документ.ЗаказПокупателя.Форма.ФормаДокумента";
КлючОбъекта = "Общая/НастройкиФорм/" + ПолноеИмяФормы;
Попытка
// Метод Удалить с третьим параметром Неопределено очищает настройки для всех пользователей
ХранилищеСистемныхНастроек.Удалить(КлючОбъекта, "", Неопределено);
Сообщить("Настройки формы успешно очищены для всех пользователей базы данных.");
Исключение
ВызватьИсключение "Не удалось очистить настройки формы: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
Этот код обращается напрямую к системному хранилищу настроек. Ключ "Общая/НастройкиФорм/" является стандартным префиксом платформы для хранения кастомизированных форм. Передавая в качестве имени пользователя пустую строку, а в качестве третьего параметра значение Неопределено, мы принудительно стираем записи кэша формы для абсолютно всех учетных записей в текущей базе данных.
Еще один важный платформенный нюанс связан с так называемыми «снимками состояния» (snapshots) заимствованных форм в расширении. Когда мы заимствуем форму из основной конфигурации в расширение, платформа делает и сохраняет снимок ее структуры на момент заимствования.
Если после этого основная конфигурация обновляется (например, вы обновили релиз «УНФ»), структура оригинальной формы меняется. При запуске предприятия расширение пытается сопоставить свой старый сохраненный снимок с новой формой из конфигурации. В результате элементы могут начать вести себя непредсказуемо: игнорировать изменение цвета, шрифта, видимости или двоиться.
Чтобы решить эту проблему на уровне разработки, выполним следующие действия:
Чтобы полностью обезопасить себя и пользователей от подобных «фантомных» элементов и необходимости регулярной чистки кэша настроек, опытные разработчики рекомендуют использовать динамическое программное создание элементов формы вместо их визуального добавления в редакторе расширения.
Когда мы добавляем декорацию или кнопку в визуальном редакторе расширения, ее описание жестко прописывается в XML-структуру формы, которая затем кэшируется в хранилище настроек. Если же мы создаем элемент кодом при открытии формы, он конструируется «на лету» в оперативной памяти сервера при каждом открытии и никогда не сохраняется в системных таблицах базы данных как статический элемент структуры.
Давайте рассмотрим пример, как правильно и безопасно добавить декорацию-надпись программно в модуле формы расширения:
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Определим имя нашего будущего элемента
ИмяЭлемента = "Расш_ДекорацияИнформационнаяНадпись";
// Проверим, чтобы элемент не был создан ранее (избегаем дублирования)
Если Элементы.Найти(ИмяЭлемента) = Неопределено Тогда
// Определим группу на форме, в которую мы хотим поместить нашу надпись.
// Пусть это будет стандартная группа "ГруппаШапка"
РодительНаФорме = Элементы.ГруппаШапка;
// Добавляем элемент на форму. Метод принимает: Имя, ТипЭлемента, Родитель
НоваяДекорация = Элементы.Добавить(ИмяЭлемента, Тип("ДекорацияФормы"), РодительНаФорме);
// Настраиваем свойства нашей декорации
НоваяДекорация.Вид = ВидДекорацииФормы.Надпись;
НоваяДекорация.Заголовок = "Внимание! Данный документ находится на контроле у руководства.";
НоваяДекорация.ГоризонтальноеПоложение = ГоризонтальноеПоложениеЭлемента.Центр;
// Зададим полужирный красный шрифт для привлечения внимания
НоваяДекорация.Шрифт = Новый Шрифт(НоваяДекорация.Шрифт, , , Истина); // Полужирный
НоваяДекорация.ЦветТекста = ЦветаСтиля.ЦветОсобогоТекста;
КонецЕсли;
КонецПроцедуры
Используя этот подход, мы получаем колоссальное преимущество: если нам потребуется изменить текст надписи с «Внимание...» на любой другой или вовсе убрать этот элемент, нам достаточно будет просто скорректировать (или удалить) этот кусок кода в расширении. При первом же последующем открытии формы у всех пользователей без исключения отобразится новый актуальный интерфейс, и нам не придется прибегать к очистке кэша или сбросу настроек пользователей.