При разработке на управляемых формах 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью отобразить данные, полученные из запроса, в табличной части или таблице значений на форме. Казалось бы, задача тривиальная, однако использование метода ЗначениеВДанныеФормы нередко приводит к ошибке: «Несоответствие типов (параметр номер '1')». В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем различные способы загрузки данных и выясним, какой из них наиболее эффективен в разных ситуациях.
Рассмотрим типичную ситуацию, с которой сталкивается разработчик. Мы написали запрос, выполнили его и хотим передать данные в реквизит формы. На первый взгляд код выглядит логично:
РезультатЗапроса = Запрос.Выполнить();
ЗначениеВДанныеФормы(РезультатЗапроса, ТаблицаНаФорме);
В этот момент платформа выбрасывает исключение. Проанализируем причину. Метод ЗначениеВДанныеФормы спроектирован так, что его первым параметром должен выступать конкретный прикладной объект, содержащий данные в памяти. Объект РезультатЗапроса — это лишь итератор, который позволяет обходить выборку или выгружать данные, но сам он не является коллекцией данных в том смысле, который ожидает метод.
Важный нюанс: Платформа 1С требует, чтобы в первый параметр передавались типы ТаблицаЗначений, ДеревоЗначений, Структура или Соответствие. Чтобы исправить ошибку, необходимо преобразовать результат запроса в таблицу значений.
Самый простой и правильный способ исправить ошибку — это добавить метод Выгрузить(). В этом случае мы сначала переносим данные из выборки запроса в оперативную память (в объект ТаблицаЗначений), а затем платформа успешно транслирует их в данные формы.
РезультатЗапроса = Запрос.Выполнить();
ТаблицаДляЗагрузки = РезультатЗапроса.Выгрузить();
ЗначениеВДанныеФормы(ТаблицаДляЗагрузки, ТаблицаНаФорме);
Или в сокращенном варианте, который чаще всего используется на практике:
ЗначениеВДанныеФормы(Запрос.Выполнить().Выгрузить(), ТаблицаНаФорме);
Существует альтернативный подход, который также часто упоминается разработчиками. Мы можем использовать метод Загрузить() непосредственно у объекта ДанныеФормыКоллекция (которым является таблица на форме).
ТаблицаНаФорме.Загрузить(Запрос.Выполнить().Выгрузить());
Давайте разберем разницу между этими подходами. Метод Загрузить() работает аналогично методу ЗначениеВДанныеФормы, но он специфичен именно для коллекций.
Преимущества и особенности метода Загрузить():
Число), платформа попытается сделать неявное преобразование. Если оно не удастся, вы получите пустое значение в ячейке, но не критическую ошибку.Некоторые разработчики предпочитают использовать метод ЗначениеВРеквизитФормы. Рассмотрим пример:
ЗначениеВРеквизитФормы(Запрос.Выполнить().Выгрузить(), "ТаблицаНаФорме");
Этот метод отличается тем, что второй параметр передается в виде строки — имени реквизита. С точки зрения производительности для обычных таблиц разницы практически нет, однако ЗначениеВДанныеФормы считается более современным и гибким инструментом в управляемом приложении.
Выбор между ЗначениеВДанныеФормы и Загрузить() часто становится предметом споров. Проанализируем технические детали, которые помогут вам принять решение:
ДеревоЗначений на форме с сохранением иерархии, метод ЗначениеВДанныеФормы незаменим. Он автоматически выстраивает узлы. Метод Загрузить() у дерева работает гораздо сложнее и часто требует ручного обхода.ЗначениеВДанныеФормы работает чуть быстрее при больших объемах данных, так как оно полностью замещает серверный объект, тогда как Загрузить() выполняет цикл обновления коллекции.Рассмотрим ситуацию, о которой часто предупреждают опытные разработчики. Представим, что в запросе вы переименовали поле, например, с СвободныйОстаток на ОстатокНаСкладе, а в таблице на форме колонка осталась со старым именем.
При использовании Загрузить() или ЗначениеВДанныеФормы платформа не выдаст ошибку, она просто загрузит пустые значения в несовпавшие колонки. Это может привести к «тихим» ошибкам, которые сложно диагностировать. Поэтому всегда проверяйте соответствие имен колонок в запросе и в реквизитах формы.
В ходе обсуждения часто возникает вопрос: а как реализовать более сложную задачу, например, сравнение остатков из файла с базой? Рассмотрим пример кода, который считывает данные из Excel и помещает их в таблицу на форме с помощью ПостроителяЗапроса, что позволяет избежать ручного перебора строк:
// Предположим, файл уже загружен во временное хранилище
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
ИмяФайла = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанные.Записать(ИмяФайла);
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла);
// Используем ПостроительЗапроса для быстрого преобразования ТабДока в ТаблицуЗначений
ПЗ = Новый ПостроительЗапроса;
ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область());
ПЗ.Выполнить();
// Заполняем таблицу на форме
ЗначениеВДанныеФормы(ПЗ.Результат.Выгрузить(), Объект.ТаблицаОстатков);
В данном примере мы видим комбинацию техник: чтение файла, использование ПостроителяЗапроса для получения структуры данных и финальную загрузку через ЗначениеВДанныеФормы. Это гораздо эффективнее, чем построчный обход табличного документа в цикле.
Подводя итог, выделим основные правила работы с данными формы:
РезультатЗапроса напрямую в функции преобразования — всегда используйте .Выгрузить().ЗначениеВДанныеФормы для работы с деревьями значений и в случаях, когда требуется максимальная производительность.ВЫБРАТЬ вашего запроса — они должны в точности совпадать с именами реквизитов таблицы формы.Соблюдение этих простых правил поможет вам избежать досадных ошибок и сделает ваш код более надежным и поддерживаемым.