При разработке сложных интерфейсов на управляемых формах 1С программисты часто сталкиваются с задачей: нужно выполнить определенное действие (например, сформировать отчет или выгрузить данные) только для тех колонок, которые пользователь в данный момент видит на экране. Однако стандартная проверка свойства Видимость часто возвращает Истина, даже если пользователь скрыл колонку через меню «Изменить форму». Разберем, почему так происходит и как корректно решить эту задачу.
Прежде всего, проанализируем архитектурную особенность платформы 1С:Предприятие 8.3. В системе разделены два понятия:
Видимость) — это управление отображением элемента из кода. Если мы устанавливаем Элементы.ИмяКолонки.Видимость = Ложь, колонка исчезает, и пользователь не может включить ее самостоятельно через настройки формы.Видимость.Именно поэтому цикл по ПодчиненныеЭлементы не дает ожидаемого результата: он видит состояние программного флага, но игнорирует настройки, которые пользователь сохранил для своего удобства. Более того, прямого свойства ПользовательскаяВидимость, доступного для чтения в объекте ЭлементФормы, не существует. Это сделано намеренно, чтобы логика бизнес-процессов не зависела от того, как пользователь настроил «красоту» на своем экране.
Рассмотрим подробнее способы, которые позволяют обойти это ограничение и получить реальное состояние интерфейса.
Прежде чем переходить к сложным методам, убедимся, что мы правильно проверяем хотя бы программную видимость. Иногда колонка может иметь значение Видимость = Истина, но быть скрытой, так как скрыт ее родитель (группа колонок или сама таблица). Проанализируем пример функции для проверки иерархической видимости:
Функция КолонкуДействительноВидно(Элемент) Экспорт
ТекущийЭлемент = Элемент;
Пока ТекущийЭлемент <> Неопределено Цикл
Если Не ТекущийЭлемент.Видимость Тогда
Возврат Ложь;
КонецЕсли;
// Переходим к родителю (группе или форме)
ТекущийЭлемент = ТекущийЭлемент.Родитель;
КонецЦикла;
Возврат Истина;
КонецФункции
Этот метод полезен, но он все еще не учитывает настройки «Изменить форму».
Если ваша цель — сформировать печатную форму или отчет на основе того, что видит пользователь, самым правильным и «штатным» способом будет использование метода Вывести(). Этот метод платформы автоматически учитывает все слои видимости: и программную, и пользовательскую, и функциональные опции.
Разберем по шагам, как это работает:
ТабличныйДокумент.Вывести() для элемента формы (табличной части).
// Пример на клиенте
ТабДок = Новый ТабличныйДокумент;
Элементы.ОсновнаяТаблица.Вывести(ТабДок);
// Теперь в ТабДок только те колонки, которые видел пользователь.
// Мы можем перебрать области ТабДока, чтобы понять, какие данные попали в вывод.
Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
ТекстЗаголовка = ТабДок.Область(1, НомерКолонки).Текст;
Сообщить("Выведена колонка: " + ТекстЗаголовка);
КонецЦикла;
Этот метод считается наиболее надежным, так как он задействует встроенные механизмы отрисовки 1С.
Для более глубокого анализа (например, если нужно знать видимость без вывода в таблицу) можно обратиться к ХранилищеСистемныхНастроек. Именно там 1С хранит дампы настроек форм для каждого пользователя.
Посмотрим на логику процесса:
Настройки формы сохраняются по ключу, который обычно выглядит как "Общая/НастройкиФорм/ИмяВашейФормы". С помощью метода ХранилищеСистемныхНастроек.Загрузить() можно получить структуру, содержащую настройки элементов. Однако стоит учесть, что формат этих данных официально не документирован и может меняться. Это сложный путь, требующий парсинга дерева настроек, где для каждого элемента хранится флаг видимости.
Существует интересный прием, упомянутый опытными разработчиками. Платформа 1С не позволяет программно установить фокус (сделать активным) элемент, который скрыт от пользователя. Это можно использовать как быструю проверку на клиенте.
Проанализируем ситуацию на примере:
&НаКлиенте
Функция ЭтоПользовательскаяВидимость(ИмяЭлемента)
СтарыйЭлемент = ЭтаФорма.ТекущийЭлемент;
ПроверяемыйЭлемент = Элементы[ИмяЭлемента];
// Пытаемся назначить элемент текущим
ЭтаФорма.ТекущийЭлемент = ПроверяемыйЭлемент;
// Проверяем, приняла ли платформа это назначение
Если ЭтаФорма.ТекущийЭлемент = ПроверяемыйЭлемент Тогда
// Возвращаем фокус назад
ЭтаФорма.ТекущийЭлемент = СтарыйЭлемент;
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Важно: этот метод имеет побочные эффекты в виде кратковременного переключения фокуса, что может вызвать срабатывание событий ПриАктивизацииЯчейки или ПриАктивизацииСтроки. Используйте его с осторожностью и только в тех случаях, когда другие методы недоступны.
Если вы создаете элементы формы программно, вы можете заранее ограничить возможность пользователя влиять на их видимость или, наоборот, задать начальные настройки. Для этого используется метод УстановитьВидимость() объекта ЭлементФормы, который принимает вторым параметром настройки пользователя.
Выясним причину, по которой это важно: при программном создании колонки в ПриСозданииНаСервере, она по умолчанию получает статус видимой везде. Если вам нужно скрыть её «по-умному», используйте такой подход:
НоваяКолонка = Элементы.Добавить("ТехническоеПоле", Тип("ПолеФормы"), Элементы.Список);
НоваяКолонка.ПутьКДанным = "Объект.ТехническоеПоле";
// Устанавливаем видимость так, чтобы пользователь не мог её включить
НоваяКолонка.Видимость = Ложь;
// Или управляем доступностью в меню "Изменить форму" через ПользовательскаяВидимость
НоваяКолонка.ПользовательскаяВидимость.Доступность = Ложь;
Подводя итог, можно сказать, что «честного» и простого свойства ПользовательскаяВидимость в режиме «только чтение» у элементов нет. Выбор решения зависит от вашей конкретной задачи:
Вывести().Родитель.Видимость.ТекущийЭлемент.ХранилищеСистемныхНастроек.Помните, что архитектурно 1С рекомендует отделять логику данных от визуального представления. Если вашему алгоритму требуются данные из колонки, лучше брать их напрямую из Объект.ТабличнаяЧасть, не опираясь на то, видит их пользователь в данный момент или нет.