Динамическое создание колонок на форме — это классическая задача в 1С:Предприятии, с которой разработчики сталкиваются при построении различных планировщиков, шахматок, бюджетов или сложных отчетов с возможностью интерактивного ввода данных. В обычных формах (обычном приложении) эта задача имеет ряд своих специфических особенностей и подводных камней.
Довольно часто разработчики сталкиваются с проблемой: колонки на форме программно создаются, данные выводятся, но при попытке дважды кликнуть по ячейке редактирование не активируется. В этой статье мы подробно разберем, почему так происходит, и по шагам рассмотрим правильную методику динамического построения интерактивной таблицы.
Выясним причину, по которой ячейки могут оставаться доступными только для чтения при их ручном добавлении на форму. Обычно это связано с тремя ключевыми ошибками:
ЭлементыФормы.ТабличноеПоле.Колонки.Добавить(), но не добавили соответствующую колонку в связанную ТаблицаЗначений (или другой источник), платформе будет просто некуда записывать вводимые пользователем данные.УстановитьЭлементУправления() должен вызываться строго до назначения свойства Данные. Если сделать наоборот, привязка к данным собьется, и поле ввода не будет активироваться.Давайте рассмотрим два основных способа решения этой задачи: через прямое добавление колонок на форму и через предварительную подготовку Таблицы Значений (ТЗ).
---
Проектирование структуры таблицы «от данных к форме» — самый надежный и простой в реализации способ. Вместо того чтобы вручную настраивать свойства каждой колонки элемента формы, мы сначала полностью формируем структуру в объекте ТаблицаЗначений, типизируем её, привязываем к табличному полю и генерируем элементы управления одной командой.
Рассмотрим по шагам, как реализовать этот алгоритм программно:
Шаг 1. Создаем объект Таблицы Значений и описываем типы колонок. При добавлении колонок в ТЗ обязательно нужно использовать ОписаниеТипов. Это гарантирует, что платформа автоматически подберет правильный элемент управления для формы.
Шаг 2. Привязываем ТЗ к табличному полю. Связываем свойство Значение нашего элемента формы с созданной ТЗ.
Шаг 3. Генерируем колонки формы. Вызываем метод СоздатьКолонки(). Платформа самостоятельно создаст визуальные колонки, свяжет их с реквизитами ТЗ и назначит соответствующие поля ввода.
Посмотрим на практический пример реализации этого подхода в коде:
// 1. Создаем структуру Таблицы Значений
ТЗ = Новый ТаблицаЗначений;
// Базовая колонка номенклатуры
ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
// Динамически добавляем колонки по периодам
д = ДатаС;
Пока д <= ДатаПо Цикл
// Форматируем год без разделителей групп (например, "2026", а не "2 026")
стрГод = Формат(Год(д), "ЧГ=");
стрМесяц = Месяц(д);
Постфикс = "_" + стрГод + "_" + стрМесяц;
// Добавляем типизированные колонки в ТЗ
ТЗ.Колонки.Добавить("План" + Постфикс, Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
ТЗ.Колонки.Добавить("Факт" + Постфикс, Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
ТЗ.Колонки.Добавить("План2" + Постфикс, Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
д = ДобавитьМесяц(д, 1);
КонецЦикла;
// 2. Связываем ТЗ с элементом формы
ЭлементыФормы.СтрокиПлана.Значение = ТЗ;
// 3. Автоматически создаем элементы управления на форме
ЭлементыФормы.СтрокиПлана.СоздатьКолонки();
Этот лаконичный код полностью решает проблему редактирования ячеек. Платформа сама определила, что для колонок планов и фактов нужны поля ввода числового формата, и связала их с данными ТЗ.
---
Если по каким-то причинам вам необходимо добавлять колонки вручную непосредственно в коллекцию ЭлементыФормы.ТабличноеПоле.Колонки, то крайне важно соблюдать правильную последовательность установки свойств. Разберем этот алгоритм.
Проанализируем пример ручной настройки одной колонки:
// Добавляем колонку в элемент формы
Кол = ЭлементыФормы.СтрокиПлана.Колонки.Добавить("Номенклатура");
// Устанавливаем режим редактирования непосредственно в ячейке
Кол.РежимРедактирования = РежимРедактированияКолонки.Непосредственно;
// ВАЖНО: Сначала устанавливаем элемент управления (Поле ввода)
Кол.УстановитьЭлементУправления(Тип("ПолеВвода"));
// Теперь настраиваем параметры самого элемента управления
Кол.ЭлементУправления.КнопкаВыбора = Истина;
Кол.ЭлементУправления.КнопкаОчистки = Истина;
// И только в самом конце привязываем колонку к полю источника данных ТЗ
Кол.Данные = "Номенклатура";
Запомните: Нарушение этой последовательности (например, установка свойства Кол.Данные = "Номенклатура" до вызова метода УстановитьЭлементУправления) приведет к тому, что ячейка заблокируется для изменения на форме.
---
После вызова метода СоздатьКолонки() все созданные поля будут выстроены в один ряд. В нашей задаче для каждого месяца создается сразу по три колонки: «План», «Факт» и «План2». Чтобы таблица не растягивалась бесконечно по горизонтали, логично расположить эти показатели друг под другом в рамках одной колонки-периода.
В обычных формах 1С это реализуется с помощью управления свойством Положение у объекта КолонкаТабличногоПоля. Разберем по шагам, как распределить колонки по строкам:
ПоложениеКолонки.НоваяКолонка.ПоложениеКолонки.НаСледующейСтроке.ПоложениеКолонки.НаСледующейСтроке.Давайте посмотрим, как программно настроить отображение колонок после их создания:
д = ДатаС;
Пока д <= ДатаПо Цикл
стрГод = Формат(Год(д), "ЧГ=");
стрМесяц = Месяц(д);
Постфикс = "_" + стрГод + "_" + стрМесяц;
// Получаем ссылки на созданные колонки формы
КолПлан = ЭлементыФормы.СтрокиПлана.Колонки["План" + Постфикс];
КолФакт = ЭлементыФормы.СтрокиПлана.Колонки["Факт" + Постфикс];
КолПлан2 = ЭлементыФормы.СтрокиПлана.Колонки["План2" + Постфикс];
// Настраиваем положение колонок друг под другом
КолПлан.Положение = ПоложениеКолонки.НоваяКолонка;
КолФакт.Положение = ПоложениеКолонки.НаСледующейСтроке;
КолФакт.РежимРедактирования = РежимРедактированияКолонки.Непосредственно;
КолПлан2.Положение = ПоложениеКолонки.НаСледующейСтроке;
КолПлан2.РежимРедактирования = РежимРедактированияКолонки.Непосредственно;
// Зададим понятные заголовки колонок для пользователя
КолПлан.ТекстШапки = "План (" + Формат(д, "ДФ='MMMM yy'") + ")";
КолФакт.ТекстШапки = "Факт";
КолПлан2.ТекстШапки = "План 2";
д = ДобавитьМесяц(д, 1);
КонецЦикла;
Использование свойства РежимРедактированияКолонки.Непосредственно позволяет пользователю начать редактирование ячеек сразу в один клик мыши без необходимости совершать двойной щелчок.
---
Когда мы выводим несколько показателей на один месяц, на форме получается визуальная каша из-за повторяющихся названий месяцев в заголовках. Намного удобнее сделать одну общую шапку с названием месяца (например, «Январь 2026»), а под ней расположить три подколонки: «План», «Факт», «План2».
В обычных формах 1С нет штатных «групп колонок», как в управляемом интерфейсе, но мы можем использовать изящный обходной прием:
"Период" + Постфикс. Задаем ей текст шапки с названием месяца и положение ПоложениеКолонки.НоваяКолонка.ПоложениеКолонки.НаСледующейСтроке под нашей служебной колонкой.ПриВыводеСтроки. Мы просто отключаем видимость ячеек этой служебной колонки для каждой выводимой строки:
Процедура СтрокиПланаПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
// Скрываем ячейки служебных колонок-шапок, чтобы они не отображались в теле таблицы
Для Каждого Колонка Из Элемент.Колонки Цикл
Если Лев(Колонка.Имя, 6) = "Шапка_" Тогда
ОформлениеСтроки.Ячейки[Колонка.Имя].Видимость = Ложь;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В результате в шапке таблицы мы получим красивое визуальное объединение колонок по месяцам, а в области данных будут выводиться и редактироваться только наши показатели.
---
Обратим внимание на важную деталь, упомянутую в обсуждении темы. При динамическом формировании имен колонок (например, привязанных к году) никогда не преобразовывайте год в строку стандартными строковыми функциями вроде Строка(Год(Дата)).
В зависимости от региональных настроек операционной системы пользователя, число 2026 при преобразовании в строку может превратиться в "2 026" (с неразрывным пробелом в качестве разделителя тысяч). Поскольку пробелы в именах колонок баз данных и таблиц значений недопустимы, это гарантированно вызовет ошибку инициализации колонки.
Правильное решение: всегда используйте функцию Формат() с отключением группировки чисел:
ИмяКолонки = "План_" + Формат(Год(РабочаяДата), "ЧГ=");
Символ "ЧГ=" в параметрах форматирования указывает платформе 1С, что группировку разрядов числа выполнять не нужно, и мы гарантированно получим монолитную строку вида "2026".