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