Как динамически менять состав и положение колонок таблицы значений в 1С 7.7 с помощью FormEx?

Программист 1С v7.7 Управленческий учет IT и автоматизация бизнеса
← На главную

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

Рассмотрим ситуацию, когда при изменении флага на форме (например, «Полная ведомость») нам необходимо не только скрыть или показать колонки, но и изменить их положение, имитируя многострочную шапку, как в табличных частях документов. Проанализируем типичные ошибки, возникающие при таком подходе, и выработаем оптимальный алгоритм решения задачи.

Разбор типичных проблем при динамическом обновлении колонок

Основная сложность заключается в том, что при программном удалении и добавлении колонок в объект ТаблицаЗначений, который связан с визуальным элементом на форме, связь между данными и их представлением может нарушиться. Это приводит к «вылетам» системы или отображению пустой таблицы. Выясним основные причины нестабильности:

  1. Неправильная очистка структуры: Использование циклов с методом УдалитьКолонку() менее эффективно, чем специализированные методы.
  2. Момент вызова методов FormEx: Попытка изменить положение колонок в событии ПриОткрытии или ПриОбновленииФормы часто приводит к ошибкам, так как визуальный объект (контрол Windows) может быть еще не инициализирован или находиться в процессе перерисовки.
  3. Конфликт индексов: Методы FormEx обращаются к колонкам по их порядковым номерам. Если структура ТЗ изменилась, а индексы в визуальном объекте не обновились, происходит обращение к несуществующему элементу.

Шаг 1. Правильная очистка и инициализация таблицы

Вместо того чтобы в цикле удалять каждую колонку по отдельности, проанализируем возможности стандартного метода Очистить(). Этот метод полностью сбрасывает и строки, и структуру колонок таблицы значений, что позволяет начать формирование структуры «с чистого листа».

Рассмотрим фрагмент кода для подготовки таблицы:


Процедура НастроитьТбТовары()
    // Полностью очищаем структуру и данные
    тбТовары.Очистить();
    
    // Добавляем базовые колонки, которые есть всегда
    тбТовары.НоваяКолонка("Цвет", "Строка");
    тбТовары.ВидимостьКолонки("Цвет", 0); // Служебная колонка для раскраски
    тбТовары.НоваяКолонка("Товар", , , , "Товар", 50);
    
    Если ПолнаяВедомость = 1 Тогда      
        тбТовары.НоваяКолонка("СуммаНачИнв", "Число", 12, 2, "Сумма Нач. Инв.", 10);
        тбТовары.НоваяКолонка("КвоНачИнв", "Число", 12, 0, "Кво Нач. Инв.", 10);
        // ... добавление остальных колонок
    КонецЕсли;
КонецПроцедуры

Важный нюанс: метод Очистить() работает надежнее, чем ручное удаление колонок в цикле Пока тбТовары.КоличествоКолонок() <> 0, так как гарантирует атомарность операции.

Шаг 2. Использование метода ПоложениеКолонкиТаблицы

Метод ПоложениеКолонкиТаблицы объекта РасширениеФормы позволяет управлять тем, как колонки размещаются друг относительно друга. Разберем параметры этого метода:

  1. Имя таблицы: Идентификатор элемента формы.
  2. Номер колонки: Индекс колонки (начиная с 1).
  3. Тип положения:
    • 1 — Обычное положение (справа от предыдущей).
    • 2 — В той же колонке (под предыдущей ячейкой).
    • 3 — На следующей строке (перенос всей группы колонок на новый ряд внутри одной строки ТЗ).

Посмотрим на пример реализации настройки многострочного вида:


Процедура НастроитьГеометриюТаблицы()
    РФорма = СоздатьОбъект("РасширениеФормы");
    
    Если ПолнаяВедомость = 1 Тогда
        // Размещаем КвоНачИнв под СуммаНачИнв
        // Допустим, СуммаНачИнв — это 3-я колонка, а КвоНачИнв — 4-я
        РФорма.ПоложениеКолонкиТаблицы("тбТовары", 4, 2); 
        
        // Размещаем КвоНач под СуммаНач (колонки 5 и 6)
        РФорма.ПоложениеКолонкиТаблицы("тбТовары", 6, 2);
    Иначе
        // Возвращаем стандартное отображение (в ряд)
        РФорма.ПоложениеКолонкиТаблицы("тбТовары", 4, 1);
        РФорма.ПоложениеКолонкиТаблицы("тбТовары", 6, 1);
    КонецЕсли;
КонецПроцедуры

Шаг 3. Оптимизация запроса и загрузка данных

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

Если мы используем ODBCRecordset, лучше всего сначала получить данные в промежуточную (внутреннюю) таблицу значений, а затем перенести их в экранную таблицу. Это позволяет избежать конфликтов при отрисовке в момент изменения структуры.


// Пример получения данных через 1С++
тбДанные = RS.ВыполнитьИнструкцию(ТекстЗапроса);

// Вместо прямой выгрузки (которая убьет структуру экранной ТЗ), 
// заполняем экранную таблицу построчно или через Заполнить()
тбТовары.КоличествоСтрок(0);
тбДанные.ВыбратьСтроки();
Пока тбДанные.ПолучитьСтроку() = 1 Цикл
    тбТовары.НоваяСтрока();
    // Копируем данные по именам колонок
    Для Ном = 1 По тбТовары.КоличествоКолонок() Цикл
        ИмяКол = тбТовары.ПолучитьПараметрыКолонки(Ном);
        Если тбДанные.КоличествоКолонок(ИмяКол) > 0 Тогда
            тбТовары.УстановитьЗначение(тбТовары.НомерСтроки, ИмяКол, тбДанные.ПолучитьЗначение(тбДанные.НомерСтроки, ИмяКол));
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

Шаг 4. Управление событиями формы

Как отмечалось в обсуждении, методы FormEx наиболее стабильно работают, когда форма уже полностью «жива». Рекомендуется использовать специальное событие ПослеОткрытия(), предоставляемое компонентой FormEx.

Проанализируем правильную последовательность действий при переключении режима (флажка):

  1. Пользователь меняет флаг ПолнаяВедомость.
  2. Вызывается процедура Сформировать().
  3. Внутри Сформировать() сначала вызывается НастроитьТбТовары() (очистка и создание колонок).
  4. Затем выполняется запрос и заполнение данными.
  5. В самом конце вызывается настройка визуального положения колонок через ПоложениеКолонкиТаблицы.
  6. Обязательно вызывается Форма.Обновить().

Совет: Если при смене режима 1С все же ведет себя нестабильно, попробуйте вынести настройку положения колонок в ОбработкаОжидания с минимальной задержкой (0.1 сек). Это даст платформе время завершить внутренние процессы перерисовки ТЗ.

Дополнительные советы по использованию FormEx

Работа с видимостью: Если вам нужно просто скрыть колонки без изменения их «этажности», используйте штатный метод ВидимостьКолонки(Имя, Состояние). Однако помните, что скрытые колонки все равно занимают индекс в коллекции. Если вы скрыли колонку №2, то визуально колонка №3 станет второй, но для FormEx она может остаться под номером 3. Всегда проверяйте соответствие индексов после изменения видимости.

Цветовое выделение: При динамическом формировании строк удобно использовать возможности FormEx для раскраски. Создайте колонку Цвет, сделайте ее невидимой и записывайте туда значения в формате "BRUSH[0xRRGGBB]". Это позволит наглядно выделить ошибки или итоги в вашей обновленной таблице.

Закрытие формы: Если при проверке условий (например, не найдена предыдущая инвентаризация) вам нужно прервать работу, используйте конструкцию СтатусВозврата(0); Возврат; в предопределенных процедурах. Это корректно остановит открытие формы или выполнение процесса.

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

← На главную