Как избежать горизонтальной прокрутки в табличной части управляемой формы 1С, автоматически подстроив ширину колонок?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке и использовании конфигураций на платформе 1С:Предприятие 8.3 с управляемыми формами, мы, разработчики, часто сталкиваемся с парадоксальной ситуацией: имея в руках мощный инструмент для создания гибких и адаптивных интерфейсов, мы обнаруживаем, что некоторые базовые, казалось бы, функции, отсутствуют или реализованы неочевидным образом. Одна из таких проблем, вызывающая много вопросов и нареканий, — это "неуправляемая" табличная часть, а именно, отсутствие простого и эффективного способа автоматически уместить все колонки табличной части в видимую область формы, избегая горизонтальной прокрутки.

Давайте вместе разберем эту проблему, выясним, почему она возникает, и рассмотрим различные подходы, которые мы можем использовать для ее минимизации или обхода, учитывая текущие возможности платформы 1С.

Отсутствие штатного механизма автоматического подбора ширины

Начнем с того, что именно является камнем преткновения. Как показывает практика и подтверждают обсуждения на форумах, в платформе 1С:Предприятие 8.3 для управляемых форм отсутствует прямая "галка" или свойство, которое бы автоматически регулировало ширину всех колонок табличной части таким образом, чтобы они полностью помещались в доступное пространство формы без появления горизонтальной полосы прокрутки. Мы, разработчики, перебираем все похожие свойства, но такого функционала не находим. Это вызывает фрустрацию, особенно когда пользователи, привыкшие к другим программам (например, к Microsoft Access, где подобная функциональность часто доступна), ожидают аналогичного поведения.

Эта особенность платформы приводит к значительному неудобству для конечных пользователей. Представьте себе табличную часть с множеством колонок, например, закладку "Параметры" в


Консоли запросов для УФ
, где для просмотра всех параметров приходится постоянно использовать горизонтальный скроллинг. Это замедляет работу, отвлекает внимание и снижает общее удобство использования программы. Мы понимаем, что в основе такого поведения лежит архитектура платформы, которая, по мнению некоторых, больше сфокусирована на "бэкенде" и целостности данных, а "фронтенд" и юзабилити недооцениваются.

Платформа 1С, конечно, пытается по умолчанию ставить ширину колонки в зависимости от ее содержимого, но это не означает автоматическое "сжатие" всех колонок под размер окна. Скорее, это попытка адекватно отобразить данные, но не решить проблему общей ширины табличной части.

Ручное управление шириной колонок

Самый очевидный, но не всегда приемлемый способ контроля над шириной колонок — это ручное задание их размеров. Для каждой колонки табличной части мы можем установить свойство Ширина. Это свойство, задаваемое в символах, влияет на расчет макета формы:

  1. В режиме конфигуратора: Мы, как разработчики, можем открыть форму, найти нужную табличную часть, выбрать колонку и в её свойствах установить желаемое значение для Ширина. Если мы установим 0, платформа попытается определить ширину автоматически, исходя из содержимого, но, как мы уже говорили, это не решит проблему с общей шириной табличной части.
  2. В пользовательском режиме: Пользователи также могут настраивать ширину колонок интерактивно, перетаскивая границы колонок. Эти настройки, как правило, сохраняются между сеансами, и при следующем открытии формы табличная часть будет отображаться с заданными пользователем размерами колонок. Для доступа к этим настройкам обычно используется меню "Изменить форму..." или контекстное меню шапки табличной части.

Рассмотрим пример установки ширины колонок программно в модуле формы при создании на сервере или при открытии:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Устанавливаем ширину для конкретных колонок табличной части "МояТабличнаяЧасть"
    // Например, если колонка "Наименование" должна быть шире, а "Количество" - уже
    Если Элементы.Есть("МояТабличнаяЧасть") Тогда
        Если Элементы.МояТабличнаяЧасть.Колонки.Есть("Наименование") Тогда
            Элементы.МояТабличнаяЧасть.Колонки.Наименование.Ширина = 40; // Ширина в символах
        КонецЕсли;
        Если Элементы.МояТабличнаяЧасть.Колонки.Есть("Количество") Тогда
            Элементы.МояТабличнаяЧасть.Колонки.Количество.Ширина = 15;
        КонецЕсли;
        // Добавляем пустую колонку для "растягивания", если требуется
        Если Элементы.МояТабличнаяЧасть.Колонки.Есть("ПустаяКолонкаДляРастягивания") Тогда
            // Убеждаемся, что она "растягивается"
            Элементы.МояТабличнаяЧасть.Колонки.ПустаяКолонкаДляРастягивания.Растягивать = Истина;
            // Делаем ее невидимой и без заголовка
            Элементы.МояТабличнаяЧасть.Колонки.ПустаяКолонкаДляРастягивания.Видимость = Ложь;
            Элементы.МояТабличнаяЧасть.Колонки.ПустаяКолонкаДляРастягивания.ОтображениеЗаголовка = Ложь;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Этот подход работает, но он не решает проблему динамической подстройки под изменяющийся размер формы или под разные разрешения экранов пользователей. Каждый раз при изменении размеров формы или окна, нам пришлось бы вручную пересчитывать и задавать ширину, что крайне неудобно.

Программные подходы к динамическому изменению ширины (теория и сложности)

Идеальным решением, которое бы удовлетворило нашу потребность в адаптивности, было бы наличие события, срабатывающего при изменении размеров формы, например, `ПриИзмененииРазмераФормы`. В таком обработчике мы могли бы программно пересчитывать и устанавливать ширину колонок пропорционально доступной ширине табличной части. Однако, к сожалению, подобного штатного события в управляемых формах 1С не предусмотрено.

Это ставит нас перед выбором: либо смириться с отсутствием автоматического подбора, либо городить "костыли". Теоретически, мы могли бы попытаться реализовать такой механизм самостоятельно:

  1. Получение размера формы: Нам нужно каким-то образом получать текущую ширину формы. Это можно сделать, но часто требует обращения к серверу или использования косвенных методов.
  2. Периодический опрос: Мы могли бы создать фоновый процесс (например, таймер), который раз в секунду или с другой периодичностью проверял бы размер формы и, если он изменился, запускал бы пересчет ширины колонок.
  3. Алгоритм распределения ширины:
    1. Мы получаем доступную ширину области, которую занимает табличная часть.
    2. Определяем "минимально допустимую" или "предпочтительную" ширину для каждой колонки (например, на основе самого длинного заголовка или предполагаемого содержимого).
    3. Рассчитываем, сколько "свободного" места осталось (доступная ширина минус сумма минимальных ширин).
    4. Пропорционально распределяем свободное место между колонками, которым разрешено "растягиваться", либо "сжимаем" колонки до минимального размера, если места не хватает.

Пример (концептуальный) кода, который бы выполнял пересчет ширины колонок, мог бы выглядеть так:


// Этот код является концептуальным и требует доработки,
// а также механизма отслеживания изменения размера формы.

&НаКлиенте
Процедура ОбновитьШиринуКолонокТабличнойЧасти()
    // Получаем элемент табличной части формы
    Перем ЭлементТабличнойЧасти;
    Если Элементы.Есть("МояТабличнаяЧасть") Тогда
        ЭлементТабличнойЧасти = Элементы.МояТабличнаяЧасть;
    Иначе
        Возврат;
    КонецЕсли;

    // Определяем доступную ширину (это самое сложное на клиенте без события ПриИзмененииРазмераФормы)
    // Здесь нужен механизм получения текущей ширины контейнера или формы
    // Предположим, что мы как-то получили доступнуюШиринуВПикселях
    Перем ДоступнаяШиринаВПикселях;
    // Например, можно получить ширину элемента, если он растянут на всю форму.
    // ЭлементТабличнойЧасти.Ширина - это ширина в символах или единицах формы, не в пикселях.
    // Для получения пиксельной ширины требуется более сложный обходной путь,
    // например, через JavaScript в веб-клиенте или COM-объекты в толстом клиенте.
    // Для простоты примера, допустим, мы ее знаем или получили через сервер
    ДоступнаяШиринаВПикселях = 1000; // Примерное значение

    Если ДоступнаяШиринаВПикселях <= 0 Тогда
        Возврат;
    КонецЕсли;

    Перем ОбщаяТекущаяШиринаКолонок = 0;
    Перем МассивКолонокДляРастягивания = Новый Массив;
    Перем СуммарнаяШиринаНеРастягиваемых = 0;

    Для Каждого Колонка Из ЭлементТабличнойЧасти.Колонки Цикл
        // Пропускаем невидимые колонки
        Если Не Колонка.Видимость Тогда
            Продолжить;
        КонецЕсли;

        // Если колонка должна растягиваться, пока не учитываем ее в сумме
        Если Колонка.Растягивать Тогда
            МассивКолонокДляРастягивания.Добавить(Колонка);
        Иначе
            // Получаем текущую ширину колонки, или задаем минимальную
            // Свойство Ширина задается в символах, что затрудняет точный пересчет пикселей
            // Придется использовать среднюю ширину символа или эвристику
            Перем ШиринаКолонкиВПикселях = Колонка.Ширина * 8; // Примерная конверсия символ -> пиксель
            Если ШиринаКолонкиВПикселях = 0 Тогда // Автоматическая ширина
                ШиринаКолонкиВПикселях = 50; // Минимальная ширина по умолчанию
            КонецЕсли;
            СуммарнаяШиринаНеРастягиваемых = СуммарнаяШиринаНеРастягиваемых + ШиринаКолонкиВПикселях;
        КонецЕсли;
    КонецЦикла;

    Перем ОставшаясяШиринаДляРастягивания = ДоступнаяШиринаВПикселях - СуммарнаяШиринаНеРастягиваемых;
    Если ОставшаясяШиринаДляРастягивания < 0 Тогда
        ОставшаясяШиринаДляРастягивания = 0; // Не можем сжать меньше минимума
    КонецЕсли;

    Перем КоличествоРастягиваемыхКолонок = МассивКолонокДляРастягивания.Количество();
    Если КоличествоРастягиваемыхКолонок > 0 Тогда
        Перем ШиринаНаКаждуюРастягиваемую = ОставшаясяШиринаДляРастягивания / КоличествоРастягиваемыхКолонок;
        Для Каждого КолонкаИзМассива Из МассивКолонокДляРастягивания Цикл
            // Преобразуем пиксели обратно в "символы" или единицы формы
            КолонкаИзМассива.Ширина = Цел(ШиринаНаКаждуюРастягиваемую / 8);
            Если КолонкаИзМассива.Ширина < 5 Тогда // Задаем минимальную ширину
                КолонкаИзМассива.Ширина = 5;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Мы видим, что такой подход чрезвычайно сложен в реализации и может негативно сказаться на производительности отрисовки формы и нагрузке на процессор. Платформа 1С не предназначена для таких динамических манипуляций с интерфейсом в реальном времени. Поэтому, хотя теоретически это возможно, на практике это часто становится нецелесообразным.

Практические обходные пути и рекомендации для удобства пользователя

Поскольку идеального автоматического решения нет, мы вынуждены искать компромиссы и использовать различные обходные пути, которые, хотя и не решают проблему "в лоб", значительно повышают удобство работы с табличной частью.

1. Интерактивное скрытие/отображение колонок

Один из наиболее эффективных методов, о котором упоминалось в обсуждении, — это предоставление пользователю возможности самому управлять видимостью колонок. Мы можем реализовать это несколькими способами:

  1. Стандартные настройки формы: Пользователь всегда может зайти в меню "Все действия" -> "Изменить форму...", перейти на вкладку табличной части и снять флажки с тех колонок, которые ему в данный момент не нужны. Эти настройки сохраняются.
  2. Программные "галки" или кнопки: Мы, разработчики, можем добавить на форму интерактивные элементы управления (например, флажки или кнопки), которые будут динамически скрывать или показывать группы колонок. Например, можно создать группу "ДополнительныеРеквизиты" и дать пользователю возможность ее скрывать. Это гораздо удобнее для пользователя, чем каждый раз заходить в настройки формы.

Пример такого подхода (фрагмент кода для кнопки "Показать/Скрыть дополнительные колонки"):


&НаКлиенте
Перем ДополнительныеКолонкиВидимы;

&НаКлиенте
Процедура ПриСозданииНаСервереНаКлиенте(Отказ, СтандартнаяОбработка)
    // Инициализация состояния видимости, например, по пользовательским настройкам
    ДополнительныеКолонкиВидимы = Ложь; // Или загрузить из пользовательских настроек
    // Обновить видимость колонок при открытии формы
    ОбновитьВидимостьДополнительныхКолонок();
КонецПроцедуры

&НаКлиенте
Процедура ПереключитьВидимостьДополнительныхКолонок(Команда)
    ДополнительныеКолонкиВидимы = Не ДополнительныеКолонкиВидимы;
    ОбновитьВидимостьДополнительныхКолонок();
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьВидимостьДополнительныхКолонок()
    // Предполагаем, что у нас есть колонки "ДопРеквизит1", "ДопРеквизит2" в табличной части "МояТабличнаяЧасть"
    Если Элементы.Есть("МояТабличнаяЧасть") Тогда
        Если Элементы.МояТабличнаяЧасть.Колонки.Есть("ДопРеквизит1") Тогда
            Элементы.МояТабличнаяЧасть.Колонки.ДопРеквизит1.Видимость = ДополнительныеКолонкиВидимы;
        КонецЕсли;
        Если Элементы.МояТабличнаяЧасть.Колонки.Есть("ДопРеквизит2") Тогда
            Элементы.МояТабличнаяЧасть.Колонки.ДопРеквизит2.Видимость = ДополнительныеКолонкиВидимы;
        КонецЕсли;
        // Можно также обновить текст кнопки или флажка, если они есть на форме
        Если Элементы.Есть("Кнопка_ПереключитьДопКолонки") Тогда
            Если ДополнительныеКолонкиВидимы Тогда
                Элементы.Кнопка_ПереключитьДопКолонки.Заголовок = "Скрыть дополнительные";
            Иначе
                Элементы.Кнопка_ПереключитьДопКолонки.Заголовок = "Показать дополнительные";
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

2. Фиксация важных колонок

В "Системе стандартов и методик разработки конфигураций для платформы 1С:Предприятие 8" рекомендуется фиксировать наиболее важные колонки слева, если их много и они не помещаются на экране. Это значительно улучшает восприятие данных для пользователя, так как ключевые идентификаторы строки (например, номер по порядку, наименование) всегда остаются на виду, даже при активной горизонтальной прокрутке остальных колонок.

Для фиксации колонки мы можем использовать свойство Фиксированная:


// В модуле формы при создании на сервере или при открытии
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Элементы.Есть("МояТабличнаяЧасть") Тогда
        // Фиксируем колонку "НомерСтроки"
        Если Элементы.МояТабличнаяЧасть.Колонки.Есть("НомерСтроки") Тогда
            Элементы.МояТабличнаяЧасть.Колонки.НомерСтроки.Фиксированная = Истина;
        КонецЕсли;
        // Фиксируем колонку "Наименование"
        Если Элементы.МояТабличнаяЧасть.Колонки.Есть("Наименование") Тогда
            Элементы.МояТабличнаяЧасть.Колонки.Наименование.Фиксированная = Истина;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

3. Добавление пустой колонки с растягиванием

Интересный дизайнерский прием, который позволяет контролировать распределение свободного пространства. В конце табличной части можно добавить пустую колонку со свойством ТолькоПросмотр = Истина и отключенным отображением заголовка (ОтображениеЗаголовка = НеИспользовать). Самое главное — для этой колонки устанавливаем свойство Растягивать = Истина. Эта колонка будет "забирать" на себя все оставшееся свободное пространство, не давая другим колонкам растягиваться сверх меры и обеспечивая более компактный вид табличной части, особенно на широких мониторах.

Пример настройки такой колонки в конфигураторе:

  1. Создайте новую колонку в табличной части, например, с именем "ПустаяКолонкаДляРастягивания".
  2. В свойствах колонки установите:
    • Данные: Не заполнять (оставьте пустым или свяжите с неиспользуемым реквизитом).
    • ТолькоПросмотр: Истина.
    • ОтображениеЗаголовка: Не использовать.
    • Растягивать: Истина.
    • Видимость: Установите по необходимости (можно сделать невидимой, если она нужна только для управления растягиванием).

Мы увидим, что эта колонка эффективно поглощает излишки свободного пространства, улучшая визуальное представление.

4. Оптимизация заголовков и содержимого

Еще один важный аспект, который мы часто упускаем из виду, — это сам дизайн табличной части. Чтобы минимизировать необходимость в широких колонках и прокрутке, мы можем:

  1. Сокращать заголовки колонок: Делаем их максимально лаконичными.
  2. Использовать однострочные шапки: Избегаем "многоэтажных" заголовков. Если требуется больше информации, используем подсказки ввода.
  3. Пересматривать состав колонок: Действительно ли все эти колонки нужны одновременно? Возможно, часть данных можно вынести в отдельную форму просмотра или в подсказки, появляющиеся при наведении на ячейку.

5. Учет поведения на мобильной платформе

Важно помнить, что на мобильной платформе 1С поведение табличной части может отличаться. Вместо отображения полосы прокрутки при множестве колонок платформа может автоматически сжимать колонки, уменьшая их ширину. Это также может быть нежелательным поведением, приводящим к нечитаемости данных. Мы должны тестировать наши формы на различных устройствах и разрешениях.

Заключение

Как мы выяснили, проблема автоматического адаптивного изменения ширины колонок табличной части в 1С Управляемых формах без горизонтальной прокрутки остается актуальной и не имеет простого штатного решения. Платформа 1С, решая свои стратегические задачи, возможно, не уделяет достаточного внимания тактическим вопросам фронтенда. Однако это не значит, что мы бессильны.

Мы, как разработчики, должны применять комплексный подход, используя сочетание:

  1. Ручных настроек ширины для базового удобства.
  2. Дизайнерских решений, таких как фиксация важных колонок и добавление "растягивающейся" пустой колонки.
  3. Пользовательских механизмов скрытия/отображения колонок.
  4. Тщательной проработки структуры и содержимого самой табличной части.

Хотя "идеальная" автоматизация отсутствует, применив эти методы, мы сможем значительно улучшить пользовательский опыт и сделать наши управляемые формы более удобными и гармоничными.

← На главную