Почему сбрасывается флажок в табличном поле 1С при переходе на другую строку и как это исправить?

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

Приветствуем вас, уважаемые коллеги! Сегодня мы детально разберем одну из классических проблем, с которой часто сталкиваются разработчики при работе с обычными формами в среде 1С:Предприятие 8 (начиная от версии 8.0 и заканчивая современными релизами 8.3 в режиме обычного приложения). Речь пойдет о поведении элемента управления Табличное поле, когда колонка с типом Булево настроена как флажок (галочка), но при клике на нее и последующем переходе на другую строку отмеченное значение таинственным образом сбрасывается или исчезает.

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

Выясняем причину: почему пропадает флажок?

Для начала давайте разберемся, как устроено отображение данных в 1С. Элемент управления Табличное поле на форме — это лишь визуальное окно (представление), которое само по себе не хранит данные. Оно жестко связано с источником данных, в роли которого в нашем случае выступает Таблица значений (ТЗ).

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

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

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

Давайте рассмотрим детальные варианты решения этой проблемы.

Решение 1: Добавление булевой колонки непосредственно в текст запроса

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

Рассмотрим пример реализации такого подхода:


// Формируем текст запроса, где сразу создаем пустое булево поле
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЛОЖЬ КАК Пометка, // Создаем колонку с типом Булево и значением по умолчанию
    |	Номенклатура.Ссылка КАК Номенклатура,
    |	Номенклатура.Код КАК Код
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура";

// Выгружаем результат в Таблицу Значений
ТабДанных = Запрос.Выполнить().Выгрузить();

// Связываем полученную таблицу с элементом формы
ЭлементыФормы.Таб.Значение = ТабДанных;
ЭлементыФормы.Таб.СоздатьКолонки();

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

Решение 2: Программное добавление колонки в Таблицу значений

Что делать, если текст запроса формируется в другой части системы, изменить его напрямую нельзя или таблица значений заполняется из внешнего источника (например, из файла Excel или XML)? В этом случае мы можем программно расширить структуру таблицы значений перед тем, как вывести её на форму.

Давайте разберем по шагам, как это сделать:


// Предположим, мы получили таблицу значений из внешнего источника
ТабДанных = ПолучитьТаблицуИзЗапросаИлиФайла();

// Проверяем, существует ли уже колонка "Пометка", чтобы избежать ошибок
Если ТабДанных.Колонки.Найти("Пометка") = Неопределено Тогда
    // Добавляем колонку с явным указанием типа Булево
    ТабДанных.Колонки.Добавить("Пометка", Новый ОписаниеТипов("Булево"));
КонецЕсли;

// Заполняем новую колонку значением по умолчанию (Ложь), чтобы в ячейках не было значения Неопределено
ТабДанных.ЗаполнитьЗначения(Ложь, "Пометка");

// Отображаем данные на форме
ЭлементыФормы.Таб.Значение = ТабДанных;
ЭлементыФормы.Таб.СоздатьКолонки();

Использование метода ЗаполнитьЗначения крайне важно, так как по умолчанию новые строки в добавленной колонке будут иметь значение Неопределено, что может привести к некорректному отображению флажков на форме.

Решение 3: Правильная настройка свойств колонки табличного поля

После того как мы обеспечили наличие физической колонки в источнике данных, нам необходимо правильно настроить свойства самой колонки элемента управления Табличное поле. Часто разработчики допускают ошибку, указывая имя колонки и в свойстве Данные, и в свойстве ДанныеФлажка одновременно. Это приводит к конфликту отображения текста и галочки.

Проанализируем правильные настройки свойств колонки (их можно выполнить как в конфигураторе, так и программно):

  1. Свойство Данные (Data) — должно быть абсолютно пустым. Если связать его с булевым полем, система попытается вывести в ячейке текстовое представление («Да» / «Нет» или «Истина» / «Ложь»), перекрывая сам флажок.
  2. Свойство ДанныеФлажка (DataFlag) — сюда мы строго пишем имя нашей колонки из таблицы значений в виде строки (например, "Пометка").
  3. Свойство РежимРедактирования (EditMode) — устанавливаем в значение РежимРедактированияКолонки.Непосредственно. Это позволит пользователю менять состояние флажка в один клик мыши без перехода строки в режим редактирования.
  4. Свойство ТолькоПросмотр (ReadOnly) — убедитесь, что у данной колонки и у табличного поля в целом это свойство установлено в значение Ложь, иначе редактирование будет заблокировано.

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


// Очищаем и заново создаем колонки табличного поля на форме
ЭлементыФормы.Tab.СоздатьКолонки();

// Получаем ссылку на созданную колонку "Пометка"
КолонкаПометка = ЭлементыФормы.Tab.Колонки.Пометка;

// Применяем правильные настройки свойств
КолонкаПометка.Данные = ""; // Обязательно очищаем текстовые данные!
КолонкаПометка.ДанныеФлажка = "Пометка"; // Привязываем к булевой колонке в ТЗ
КолонкаПометка.РежимРедактирования = РежимРедактированияКолонки.Непосредственно;
КолонкаПометка.Ширина = 3;
КолонкаПометка.ТекстШапки = "";

Как убрать текст «Да» / «Нет» рядом с флажком?

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

Способ А: Использование свойства Формат

Самый простой бескодовый вариант — настроить формат отображения логических величин в колонке:


КолонкаПометка = ЭлементыФормы.Tab.Колонки.Пометка;
КолонкаПометка.Формат = "БЛ=; БИ="; // Указываем пустые строки для лжи и истины

Способ Б: Управление отображением через событие ПриВыводеСтроки

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


Процедура ТабПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    // Отключаем отображение любого текста в ячейке "Пометка"
    ОформлениеСтроки.Ячейки.Пометка.ОтображатьТекст = Ложь;
    
    // Включаем отображение флажка
    ОформлениеСтроки.Ячейки.Пометка.ОтображатьФлажок = Истина;
КонецПроцедуры

Альтернативный вариант: Виртуальные флажки без изменения структуры ТЗ

Рассмотрим продвинутый сценарий. Бывают ситуации, когда таблица значений содержит сотни тысяч строк, и добавление дополнительной колонки в память нежелательно, либо структура таблицы строго зафиксирована и защищена от изменений на уровне ядра системы. Как быть в таком случае?

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

Давайте реализуем этот алгоритм по шагам:

Шаг 1. Объявим переменную для хранения выбранных строк в модуле формы:

Перем ОтмеченныеСтроки; // Переменная модуля формы

Шаг 2. Инициализируем коллекцию при открытии формы:


Процедура ПриОткрытии()
    ОтмеченныеСтроки = Новый Соответствие;
КонецПроцедуры

Шаг 3. Настроим визуализацию флажков в обработчике события ПриВыводеСтроки табличного поля. Наша виртуальная колонка на форме пусть называется "ВиртПометка" (при этом свойства Данные и ДанныеФлажка у нее должны быть абсолютно пустыми):


Процедура ТабПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    Ячейка = ОформлениеСтроки.Ячейки.ВиртПометка;
    Ячейка.ОтображатьФлажок = Истина;
    Ячейка.ОтображатьТекст = Ложь;
    
    // Проверяем, содержится ли текущая строка данных в нашем соответствии отмеченных строк
    ЕстьОтметка = (ОтмеченныеСтроки.Получить(ДанныеСтроки) <> Неопределено);
    Ячейка.Флажок = ЕстьОтметка;
КонецПроцедуры

Шаг 4. Обработаем изменение состояния флажка пользователем через событие табличного поля ПриИзмененииФлажка:


Процедура ТабПриИзмененииФлажка(Элемент, Колонка)
    Если Колонка.Имя = "ВиртПометка" Тогда
        // Получаем строку, на которой кликнули по флажку
        ТекСтрока = Элемент.ТекущиеДанные;
        
        Если ТекСтрока <> Неопределено Тогда
            // Проверяем текущее состояние в соответствии
            Если ОтмеченныеСтроки.Получить(ТекСтрока) = Неопределено Тогда
                // Если строки нет в списке отмеченных — добавляем
                ОтмеченныеСтроки.Вставить(ТекСтрока, Истина);
            Иначе
                // Если строка уже была отмечена — снимаем выделение (удаляем из списка)
                ОтмеченныеСтроки.Удалить(ТекСтрока);
            КонецЕсли;
        КонецЕсли;
        
        // Принудительно обновляем визуальное состояние строки на экране
        Элемент.ОбновитьСтроки(ТекСтрока);
    КонецЕсли;
КонецПроцедуры

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

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

← На главную