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

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

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

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

Рассмотрим детально ситуацию, с которой столкнулся автор темы на форуме. На форме программно создается таблица значений тзТехЗадание и соответствующее ей табличное поле тпТехЗадание. Обе структуры изначально не имеют предопределенного набора колонок. Автор попытался решить задачу "в лоб" с помощью следующего программного кода:


Для каждого стрИмя из сзИмена цикл
    стрИмяКолонки = стрИмя;
    тзТехЗадание.Колонки.Добавить(стрИмяКолонки);
    клн = ЭлементыФормы.тпТехЗадание.Колонки.Добавить(стрИмяКолонки);
    клн.УстановитьЭлементУправления(Тип("ПолеВвода"));
КонецЦикла;

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

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

Решение №1: Ручная привязка колонок через свойство Данные

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

Ниже представлен исправленный вариант программного кода с комментариями к каждому шагу:


Для каждого стрИмя из сзИмена цикл
    стрИмяКолонки = стрИмя;
    
    // 1. Создаем физическую колонку в источнике данных (таблице значений)
    тзТехЗадание.Колонки.Добавить(стрИмяКолонки);
    
    // 2. Создаем визуальную колонку в табличном поле формы
    клн = ЭлементыФормы.тпТехЗадание.Колонки.Добавить(стрИмяКолонки);
    
    // 3. Устанавливаем элемент управления для интерактивного ввода
    клн.УстановитьЭлементУправления(Тип("ПолеВвода"));
    
    // 4. Критически важный шаг: связываем визуальную колонку с данными источника
    клн.Данные = стрИмяКолонки;
КонецЦикла;

После добавления строки клн.Данные = стрИмяКолонки; платформа начинает четко понимать адресацию. Теперь при изменении значения в ячейке табличного поля 1С автоматически записывает данные в нужную строку и колонку исходной таблицы значений тзТехЗадание. Проблема с потерей данных полностью решена.

Важная деталь: Соблюдение порядка вызова свойств. При ручной настройке колонок критически важно соблюдать правильную последовательность действий. Метод УстановитьЭлементУправления() должен вызываться строго до того, как вы присвоите значение свойству Данные. Если вы сделаете наоборот (сначала привяжете данные, а потом вызовете метод установки элемента управления), ячейки могут заблокироваться для изменения, стать доступными только для чтения или начать вести себя некорректно.

Решение №2: Использование встроенного метода СоздатьКолонки()

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

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


// Шаг 1. Программно формируем структуру нашей таблицы значений
тзТехЗадание.Колонки.Очистить();
тзТехЗадание.Колонки.Добавить("Номенклатура");
тзТехЗадание.Колонки.Добавить("Количество");
тзТехЗадание.Колонки.Добавить("Цена");

// Шаг 2. Связываем табличное поле на форме с нашей таблицей значений
ЭлементыФормы.тпТехЗадание.Значение = тзТехЗадание;

// Шаг 3. Вызываем автоматическое создание колонок интерфейса
ЭлементыФормы.тпТехЗадание.СоздатьКолонки();

Что происходит при вызове метода СоздатьКолонки()? Платформа автоматически:

  1. Удаляет все ранее созданные колонки из табличного поля тпТехЗадание.
  2. Анализирует структуру колонок связанной таблицы значений тзТехЗадание.
  3. Создает в табличном поле новые колонки с аналогичными именами.
  4. Автоматически заполняет свойство Данные для каждой колонки.
  5. На основе типов данных колонок ТЗ подбирает и устанавливает подходящие элементы управления (например, для числовых колонок и строк будет автоматически назначено стандартное ПолеВвода).

Использование СоздатьКолонки() является наиболее надежным, быстрым и рекомендуемым стилем программирования в обычных формах 1С.

Важные нюансы типизации колонок таблицы значений

При программном добавлении колонок в таблицу значений (тзТехЗадание.Колонки.Добавить()) многие начинающие разработчики опускают второй параметр метода — тип данных. В этом случае колонка создается с типом Неопределено (произвольный тип).

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

Чтобы избежать этих проблем, всегда явно определяйте типы данных с помощью объекта ОписаниеТипов при создании колонок таблицы значений:


// Пример создания описания типов для ссылочных данных
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Номенклатура"));
ОписаниеНоменклатуры = Новый ОписаниеТипов(МассивТипов);

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

// Пример создания описания типов для числовых данных с ограничением разрядности
КвалификаторыЧисла = Новый КвалификаторыЧисла(15, 3, ДопустимыйЗнак.Неотрицательный);
ОписаниеКоличества = Новый ОписаниеТипов("Число", , КвалификаторыЧисла);

// Добавляем колонку количества в ТЗ
тзТехЗадание.Колонки.Добавить("Количество", ОписаниеКоличества);

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

Отображение флажков (типы Булево)

Если в вашей таблице есть колонка с логическим типом Булево (например, признак "Выполнено", "Утверждено", "Активно"), стандартное текстовое поле ввода будет неудобным для пользователя. Гораздо приятнее и привычнее видеть в интерфейсе интерактивный флажок (чекбокс). Однако стандартная привязка через свойство Данные здесь не сработает.

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


// 1. Создаем колонку типа Булево в таблице значений
тзТехЗадание.Колонки.Добавить("Выполнено", Новый ОписаниеТипов("Булево"));

// 2. Создаем колонку в табличном поле
клн = ЭлементыФормы.тпТехЗадание.Колонки.Добавить("Выполнено");

// 3. Вместо свойства Данные используем ДанныеФлажка
клн.ДанныеФлажка = "Выполнено";

// 4. Очищаем свойство Данные, чтобы в ячейке не дублировался текст "Да/Нет"
клн.Данные = "";

// 5. Включаем непосредственное редактирование (флажок будет переключаться в один клик)
клн.РежимРедактирования = РежимРедактированияКолонкиТабличногоПоля.Непосредственно;

Обратите внимание на свойство РежимРедактированияКолонкиТабличногоПоля.Непосредственно. По умолчанию для изменения значения в ячейке пользователю требуется сначала войти в режим редактирования строки (нажав Enter или дважды кликнув), и только потом переключить флажок. Установка режима "Непосредственно" позволяет менять состояние флажка в один клик мыши по ячейке, что сильно улучшает эргономику решения.

Для сравнения: Как аналогичная задача решается в Управляемых формах?

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

Если бы мы решали аналогичную задачу в управляемом интерфейсе, процесс выглядел бы следующим образом:

  1. Программное добавление реквизитов (колонок) в структуру формы с помощью метода ИзменитьРеквизиты().
  2. Программное создание элементов интерфейса (полей формы) и размещение их внутри элемента-таблицы.
  3. Связывание элементов с данными через строковое свойство ПутьКДанным.

Пример кода для управляемых форм (выполняется на сервере):


// 1. Формируем массив новых реквизитов формы
МассивРеквизитов = Новый Массив;
МассивРеквизитов.Добавить(Новый РеквизитФормы("НоваяКолонка", Новый ОписаниеТипов("Строка"), "Объект.тзТехЗадание", "Новая колонка"));

// 2. Добавляем новые колонки в структуру данных формы на сервере
ИзменитьРеквизиты(МассивРеквизитов);

// 3. Создаем визуальный элемент (колонку таблицы) на форме
НовыйЭлемент = Элементы.Добавить("тзТехЗаданиеНоваяКолонка", Тип("ПолеФормы"), Элементы.тзТехЗадание);
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;

// 4. Указываем путь к динамически созданному реквизиту
НовыйЭлемент.ПутьКДанным = "Объект.тзТехЗадание.НоваяКолонка";

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

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

← На главную