Как получить данные из объекта ТабличноеПоле в 1С++ для 1С 7.7

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

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

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

Способ 1. Получение данных напрямую через свойства объекта ТабличноеПоле

Рассмотрим прямой способ обращения к источнику данных. Объявлять отдельную глобальную или модульную переменную под исходную таблицу значений вовсе не обязательно, если на форме уже есть доступ к объекту табличного поля. У объекта ТабличноеПоле присутствует свойство ПоставщикДанных, а у объекта ПоставщикДанныхТЗ — свойство ТаблицаЗначений.

Посмотрим на пример извлечения исходной таблицы значений в любой процедуре модуля формы (например, перед сохранением или закрытием):


Процедура ПриЗакрытии()
    // Получаем ссылку на таблицу значений напрямую из поставщика данных
    ТЗ = ТаблПоле.ПоставщикДанных.ТаблицаЗначений;
    
    // Проверяем заполненность или выполняем обработку строк
    Если ТЗ.КоличествоСтрок() > 0 Тогда
        // Обработка данных
    КонецЕсли;
КонецПроцедуры

Важно понимать, что метод УстТаблицуЗначений() связывает поставщика данных с переданной таблицей по ссылке. Это значит, что любые изменения, вносимые в объект ТаблицаЗначений, отражаются в поставщике без необходимости создания промежуточных копий.

Способ 2. Использование модульной переменной формы

Проанализируем классический подход, при котором переменная таблицы объявляется в заголовке модуля формы. Этот вариант удобен, если таблица формируется или очищается в разных процедурах документа или отчета:

  1. Объявляем переменную в самом начале модуля формы через ключевое слово Перем.
  2. Создаем объект ТаблицаЗначений при инициализации (например, в ПриОткрытии) и связываем его с поставщиком данных.
  3. Используем переменную в любых обработчиках модуля напрямую.

Разберем пример реализации инициализации и обращения:


// В самом начале модуля формы
Перем глТЗ;

Процедура ПриОткрытии()
    глТЗ = СоздатьОбъект("ТаблицаЗначений");
    глТЗ.НоваяКолонка("Артикул", "Строка");
    глТЗ.НоваяКолонка("Количество", "Число");

    // Привязываем к табличному полю
    ТаблПоле.ПоставщикДанных = СоздатьОбъект("ПоставщикДанныхТЗ");
    ТаблПоле.ПоставщикДанных.УстТаблицуЗначений(глТЗ);
    ТаблПоле.СоздатьКолонки();
КонецПроцедуры

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

Как получить значение текущей активной строки

Выясним, как узнать, на какой именно строке позиционирован пользователь в данный момент. Для этого у табличного поля предусмотрены свойства ТекущаяСтрока и ТекущаяКолонка:

  1. Для ПоставщикДанныхТЗ свойство ТекущаяСтрока возвращает целочисленный номер строки во внутренней таблице значений.
  2. Значение конкретной ячейки извлекается вызовом стандартного метода ПолучитьЗначение().

Посмотрим на пример:


Процедура ОбработатьВыбраннуюСтроку()
    НомерСтр = ТаблПоле.ТекущаяСтрока;
    Если НомерСтр > 0 Тогда
        ТЗ = ТаблПоле.ПоставщикДанных.ТаблицаЗначений;
        ТекАртикул = ТЗ.ПолучитьЗначение(НомерСтр, "Артикул");
        Сообщить("Выбран артикул: " + ТекАртикул);
    КонецЕсли;
КонецПроцедуры

Фиксация изменений: событие ПриРедактированииЗначения и перерисовка

Рассмотрим подробнее процесс редактирования ячеек пользователем. Чтобы новое значение записалось в таблицу и отобразилось на экране, используется событие ИмяТабПоляПриРедактированииЗначения. Обратите внимание на входящий параметр режима редактирования:

  1. 0 — начало редактирования ячейки;
  2. 1 — отмена редактирования (пользователь нажал клавишу Esc);
  3. 2 — изменение значения в процессе интерактивного ввода текста;
  4. 3 — фиксация введенного значения (нажатие Enter или смена фокуса ячейки).

Запись в источник данных и визуальное обновление нужно выполнять только при значении режима 3:


Процедура ТаблПолеПриРедактированииЗначения(ТабПоле, НомерСтроки, Колонка, Режим, НовоеЗначение)
    Если Режим = 3 Тогда
        ТЗ = ТабПоле.ПоставщикДанных.ТаблицаЗначений;
        НомерКолонки = ТабПоле.Колонки.Индекс(Колонка) + 1;
        
        ТЗ.УстановитьЗначение(НомерСтроки, НомерКолонки, НовоеЗначение);
        
        // Метод ОбновитьСтроки() обновляет только видимую область ячеек
        ТабПоле.ОбновитьСтроки();
    КонецЕсли;
КонецПроцедуры

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

Организация работы с несколькими табличными полями на одной форме

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

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


Процедура ОбработатьРедактированиеУниверсально(ТабПоле, НомерСтроки, Колонка, Режим, НовоеЗначение)
    Если Режим = 3 Тогда
        ТЗ = ТабПоле.ПоставщикДанных.ТаблицаЗначений;
        НомерКолонки = ТабПоле.Колонки.Индекс(Колонка) + 1;
        ТЗ.УстановитьЗначение(НомерСтроки, НомерКолонки, НовоеЗначение);
        ТабПоле.ОбновитьСтроки();
    КонецЕсли;
КонецПроцедуры

Процедура ТП1ПриРедактированииЗначения(ТП, Стр, Кол, Рег, Знач)
    ОбработатьРедактированиеУниверсально(ТП, Стр, Кол, Рег, Знач);
КонецПроцедуры

Процедура ТП2ПриРедактированииЗначения(ТП, Стр, Кол, Рег, Знач)
    ОбработатьРедактированиеУниверсально(ТП, Стр, Кол, Рег, Знач);
КонецПроцедуры

2. Вынос логики в собственный класс 1С++.
Наиболее чистое объектно-ориентированное решение — создать пользовательский класс, унаследованный от ТабличноеПоле. В коде этого класса объявляется метод ПриРедактированииЗначения с ключевым словом Экспорт. В этом случае каждое табличное поле на форме будет полностью инкапсулировать редактирование и обновление внутри своего экземпляра, а в модуле самой формы не потребуется писать ни строчки кода для стандартных обработчиков.

← На главную