При разработке внешних обработок на обычных формах часто возникает задача отображения данных, структура которых заранее неизвестна. Например, это может быть загрузка данных из произвольного Excel или CSV файла, где количество и состав колонок определяются содержимым самого файла. В процессе реализации программисты часто сталкиваются с ошибками при попытке очистить таблицу и заполнить её заново.
Рассмотрим подробнее, как правильно организовать процесс динамического создания колонок, заполнения строк и, что немаловажно, корректной очистки интерфейсных элементов перед повторным выполнением операции.
Проанализируем ситуацию: разработчик пытается программно создать структуру таблицы. При первом нажатии кнопки на форме всё работает корректно, но при повторном вызове процедуры система выдает ошибку: «Ошибка при вызове метода контекста (Добавить): Недопустимое значение параметра (параметр номер '1')». Это происходит на этапе добавления колонки в ЭлементыФормы.ТаблицаЗагрузки.Колонки.
Выясним причину этой проблемы. Когда мы вручную добавляем колонку в визуальный элемент ТабличноеПоле, 1С жестко связывает имя колонки с её внутренним идентификатором в коллекции элементов формы. Даже если вы вызываете Очистить() для самой таблицы значений, визуальный элемент управления на форме может сохранять «память» о старых колонках или конфликтовать с новыми данными при попытке их пересоздания с теми же именами.
Основной секрет стабильной работы динамических таблиц на обычных формах заключается в том, что нам не нужно вручную добавлять колонки в ЭлементыФормы. Вместо этого следует использовать автоматизацию, предусмотренную платформой.
Разберем по шагам правильную последовательность действий:
ТаблицаЗначений).ТаблицаЗначений, определяя их имена и типы данных.СоздатьКолонки() у элемента формы. Этот метод автоматически анализирует структуру привязанной таблицы значений и перестраивает визуальное отображение «с нуля», удаляя всё старое и создавая новое.Посмотрим на пример кода, который реализует чтение текстового файла и отображение его данных в табличном поле на форме. Предположим, что на форме у нас есть элемент ТабличноеПоле с именем ТаблицаЗагрузки, который связан с одноименным реквизитом обработки.
Процедура ЗагрузитьДанныеНажатие(Элемент)
// 1. Проверка выбора файла
Если Не ЗначениеЗаполнено(ФайлЗагрузки) Тогда
Предупреждение("Выберите файл для загрузки!");
Возврат;
КонецЕсли;
// 2. Полная очистка структуры данных
// Сначала удаляем данные и колонки из программного объекта
ТаблицаЗагрузки.Очистить();
ТаблицаЗагрузки.Колонки.Очистить();
// Теперь синхронизируем визуальный элемент с пустой таблицей
// Это удалит все старые колонки из интерфейса
ЭлементыФормы.ТаблицаЗагрузки.СоздатьКолонки();
// 3. Подготовка типов данных
КвалификаторСтроки = Новый КвалификаторыСтроки(250);
ОписаниеТипаСтрока = Новый ОписаниеТипов("Строка", , КвалификаторСтроки);
// 4. Чтение файла и создание структуры
ЗагружаемыйФайл = Новый ТекстовыйДокумент;
ЗагружаемыйФайл.Прочитать(ФайлЗагрузки);
Если ЗагружаемыйФайл.КоличествоСтрок() = 0 Тогда
Возврат;
КонецЕсли;
// Читаем первую строку (шапку) для создания колонок
СтрокаШапки = ЗагружаемыйФайл.ПолучитьСтроку(1);
МассивИменКолонок = РазложитьСтрокуВМассивПодстрок(СтрокаШапки, ";"); // Используем ваш разделитель
Для Каждого ИмяКолонки Из МассивИменКолонок Цикл
// Очищаем имя от пробелов и спецсимволов для корректного идентификатора
ИмяБезОшибок = СтрЗаменить(ИмяКолонки, " ", "");
// Добавляем колонку ТОЛЬКО в таблицу значений (объект данных)
ТаблицаЗагрузки.Колонки.Добавить(ИмяБезОшибок, ОписаниеТипаСтрока, ИмяКолонки, 15);
КонецЦикла;
// 5. КЛЮЧЕВОЙ МОМЕНТ: Обновляем колонки на форме одной командой
ЭлементыФормы.ТаблицаЗагрузки.СоздатьКолонки();
// 6. Заполнение данными
Для НомерСтроки = 2 по ЗагружаемыйФайл.КоличествоСтрок() Цикл
ТекСтрокаФайла = ЗагружаемыйФайл.ПолучитьСтроку(НомерСтроки);
Если ПустаяСтрока(ТекСтрокаФайла) Тогда
Продолжить;
КонецЕсли;
ДанныеСтроки = РазложитьСтрокуВМассивПодстрок(ТекСтрокаФайла, ";");
НоваяСтрокаТЗ = ТаблицаЗагрузки.Добавить();
// Заполняем колонки по индексу
Для Индекс = 0 По ТаблицаЗагрузки.Колонки.Количество() - 1 Цикл
Если Индекс < ДанныеСтроки.Количество() Тогда
НоваяСтрокаТЗ[Индекс] = ДанныеСтроки[Индекс];
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Проанализируем вопрос типизации. В приведенном выше примере мы создаем все колонки с типом Строка. Это самый безопасный вариант для первичного отображения данных из текстовых файлов. Однако, если вы планируете в дальнейшем выполнять математические операции или сортировку по датам, рекомендуется использовать ОписаниеТипов для соответствующих типов данных.
Посмотрим на пример создания числовой колонки с квалификаторами:
КЧ = Новый КвалификаторыЧисла(15, 2);
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Число"));
ОписаниеТипаЧисло = Новый ОписаниеТипов(МассивТипов, , , КЧ);
ТаблицаЗагрузки.Колонки.Добавить("Сумма", ОписаниеТипаЧисло, "Сумма документа");
Многие начинающие разработчики пытаются использовать цикл ЭлементыФормы.ТаблицаЗагрузки.Колонки.Удалить(). Проанализируем, почему это плохая практика:
СоздатьКолонки() реализован на уровне платформы оптимальным образом. Он сначала сбрасывает все привязки, а затем строит новую структуру за один такт работы графической системы.Подводя итог, можно сказать, что динамическая работа с таблицами в 1С требует четкого разделения между данными (объект ТаблицаЗначений) и отображением (элемент ТабличноеПоле). Всегда манипулируйте колонками в программном объекте, а для синхронизации с интерфейсом используйте метод СоздатьКолонки().
Если вам требуется дополнительно настроить внешний вид созданных колонок (например, установить ширину или запретить редактирование), делайте это сразу после вызова метода СоздатьКолонки(), обращаясь к коллекции ЭлементыФормы.ТаблицаЗагрузки.Колонки. На этот момент структура уже будет соответствовать вашей таблице, и вы сможете безопасно обращаться к колонкам по их именам.