Как выделить несколько ячеек в табличном поле на обычной форме и получить их список

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

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

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

Анализ проблемы: почему Табличное поле не отдает ячейки

Начнем с того, что выясним причину затруднений. У объекта ТабличноеПоле (ТП) есть свойство РежимВыделения, которое можно установить в значение Интервал, Множественный или Единичный. Однако эти режимы в основном ориентированы на работу со строками. Если же установить свойство СпособВыбораЯчейки или попытаться работать в режиме выделения ячеек, мы столкнемся со следующими фактами:

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

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

Решение 1: Замена на Поле табличного документа

Если ваша задача предполагает сложную работу с ячейками (например, как в Excel: выделение диапазонов, объединение, произвольная раскраска), наиболее правильным решением будет замена ТабличногоПоля на ПолеТабличногоДокумента.

В ПолеТабличногоДокумента работа с выделением реализована полноценно. Мы можем использовать свойство ВыделенныеОбласти, которое возвращает коллекцию всех выбранных пользователем диапазонов. Проанализируем пример кода для получения данных из выделенных ячеек:


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

Однако этот метод требует переработки логики вывода данных, так как ТабличныйДокумент не связан напрямую с источником данных (например, с ТаблицейЗначений) так же тесно, как ТабличноеПоле.

Решение 2: Эмуляция выделения через вспомогательное соответствие

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

Разберем этот процесс по шагам:

Шаг 1. Подготовка структуры хранения. Создадим в модуле формы переменную (например, СоответствиеВыделенныхЯчеек), где ключом будет уникальный идентификатор строки, а значением — массив имен колонок.

Шаг 2. Обработка клика. В событии ПриАктивизацииЯчейки мы будем проверять, нужно ли добавить текущую ячейку в наш список. Поскольку в 1С 8.2 нет прямого метода проверки зажатого Ctrl, пользователи часто используют выделение через «двойной клик» или простое переключение состояния при каждом заходе в ячейку.


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

Шаг 3. Визуализация. Чтобы пользователь видел, какие ячейки он выбрал, необходимо использовать событие ПриВыводеСтроки. Мы будем менять цвет фона ячеек, которые присутствуют в нашем соответствии.


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

Решение 3: Использование диапазона (начало и конец)

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

Проанализируем ситуацию: пользователь выбирает первую ячейку, затем (например, с зажатым Shift или через специальную кнопку) выбирает вторую. Программно мы можем вычислить все строки, находящиеся между этими двумя индексами в ТаблицеЗначений, которая является источником данных для ТП.

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

Ограничения и важные моменты

При реализации выделения «протягиванием мыши» (Drag-select) в обычном приложении вы столкнетесь с тем, что событие ПриАктивизацииЯчейки не всегда срабатывает корректно при быстром движении мыши. Платформа 1С v8 (обычные формы) не предоставляет низкоуровневого доступа к событиям движения мыши с зажатой кнопкой внутри ТабличногоПоля.

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

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

← На главную