Как правильно заполнить таблицу на форме результатом запроса в 1С и исправить ошибку «Несоответствие типов»

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

При разработке на управляемых формах 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью отобразить данные, полученные из запроса, в табличной части или таблице значений на форме. Казалось бы, задача тривиальная, однако использование метода ЗначениеВДанныеФормы нередко приводит к ошибке: «Несоответствие типов (параметр номер '1')». В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем различные способы загрузки данных и выясним, какой из них наиболее эффективен в разных ситуациях.

Причина ошибки: РезультатЗапроса против ТаблицыЗначений

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


РезультатЗапроса = Запрос.Выполнить();
ЗначениеВДанныеФормы(РезультатЗапроса, ТаблицаНаФорме);

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

Важный нюанс: Платформа 1С требует, чтобы в первый параметр передавались типы ТаблицаЗначений, ДеревоЗначений, Структура или Соответствие. Чтобы исправить ошибку, необходимо преобразовать результат запроса в таблицу значений.

Решение №1: Использование метода Выгрузить()

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


РезультатЗапроса = Запрос.Выполнить();
ТаблицаДляЗагрузки = РезультатЗапроса.Выгрузить();
ЗначениеВДанныеФормы(ТаблицаДляЗагрузки, ТаблицаНаФорме);

Или в сокращенном варианте, который чаще всего используется на практике:

ЗначениеВДанныеФормы(Запрос.Выполнить().Выгрузить(), ТаблицаНаФорме);

Решение №2: Метод Загрузить() у реквизита формы

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

ТаблицаНаФорме.Загрузить(Запрос.Выполнить().Выгрузить());

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

Преимущества и особенности метода Загрузить():

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

Решение №3: ЗначениеВРеквизитФормы

Некоторые разработчики предпочитают использовать метод ЗначениеВРеквизитФормы. Рассмотрим пример:

ЗначениеВРеквизитФормы(Запрос.Выполнить().Выгрузить(), "ТаблицаНаФорме");

Этот метод отличается тем, что второй параметр передается в виде строки — имени реквизита. С точки зрения производительности для обычных таблиц разницы практически нет, однако ЗначениеВДанныеФормы считается более современным и гибким инструментом в управляемом приложении.

Сравнение методов: что выбрать?

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

  1. Работа с иерархией (Дерево значений): Если вам нужно заполнить ДеревоЗначений на форме с сохранением иерархии, метод ЗначениеВДанныеФормы незаменим. Он автоматически выстраивает узлы. Метод Загрузить() у дерева работает гораздо сложнее и часто требует ручного обхода.
  2. Идентификаторы строк (ID): Это критически важный момент. Оба метода при полной замене данных сбрасывают старые идентификаторы строк. Если у вас на клиенте были сохранены ссылки на конкретные строки таблицы (например, в переменной хранился номер строки или адрес), после загрузки эти ссылки станут недействительными.
  3. Производительность: ЗначениеВДанныеФормы работает чуть быстрее при больших объемах данных, так как оно полностью замещает серверный объект, тогда как Загрузить() выполняет цикл обновления коллекции.

Тонкости сопровождения кода

Рассмотрим ситуацию, о которой часто предупреждают опытные разработчики. Представим, что в запросе вы переименовали поле, например, с СвободныйОстаток на ОстатокНаСкладе, а в таблице на форме колонка осталась со старым именем.

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

Продвинутый пример: Загрузка данных из внешнего файла

В ходе обсуждения часто возникает вопрос: а как реализовать более сложную задачу, например, сравнение остатков из файла с базой? Рассмотрим пример кода, который считывает данные из Excel и помещает их в таблицу на форме с помощью ПостроителяЗапроса, что позволяет избежать ручного перебора строк:


// Предположим, файл уже загружен во временное хранилище
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
ИмяФайла = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанные.Записать(ИмяФайла);

ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла);

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

// Заполняем таблицу на форме
ЗначениеВДанныеФормы(ПЗ.Результат.Выгрузить(), Объект.ТаблицаОстатков);

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

Итоги и рекомендации

Подводя итог, выделим основные правила работы с данными формы:

Соблюдение этих простых правил поможет вам избежать досадных ошибок и сделает ваш код более надежным и поддерживаемым.

← На главную