Загрузка данных из внешних файлов (текстовых, CSV, Excel) в табличную часть документа — одна из самых частых задач, с которой сталкивается разработчик 1С. Несмотря на кажущуюся простоту, этот процесс скрывает в себе множество нюансов: от правильного использования методов платформы до корректной передачи данных между сервером и клиентом. В этой статье мы подробно разберем типичные ошибки, возникшие у автора темы, и выработаем надежный алгоритм реализации данной задачи.
В начале обсуждения мы видим типичную ошибку: попытку использовать метод Загрузить для одной строки. Давайте проанализируем, почему код НовыйДок.Товары.Загрузить(ТаблицаТоваров) вызывает ошибку. Метод Загрузить объекта ТабличнаяЧасть предназначен для массовой вставки данных и ожидает на вход объект типа ТаблицаЗначений. Если вы передаете в него результат метода Добавить() (который возвращает СтрокаТабличнойЧасти), платформа выдаст ошибку несоответствия типов.
Вариант 1: Использование метода Добавить() в цикле
Если мы обходим массив данных или текстовый файл построчно, нам достаточно использовать метод Добавить(). Рассмотрим исправленный фрагмент кода:
Для Каждого СтрокаРезультат Из Результат Цикл
НоваяСтрока = НовыйДок.Товары.Добавить();
НоваяСтрока.Количество = Число(СтрокаРезультат[1]);
НоваяСтрока.Сумма = Число(СтрокаРезультат[2]);
КонецЦикла;
Вариант 2: Использование метода Загрузить()
Этот метод эффективнее, если у вас уже есть готовая ТаблицаЗначений. Важно помнить, что метод Загрузить полностью очищает табличную часть перед заполнением. Разберем, как это сделать правильно:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура");
ТЗ.Колонки.Добавить("Количество");
ТЗ.Колонки.Добавить("Сумма");
// Заполняем ТЗ из вашего источника
Для Каждого Строка Из Результат Цикл
НоваяСтрокаТЗ = ТЗ.Добавить();
НоваяСтрокаТЗ.Номенклатура = НайтиНоменклатуру(Строка[0]);
НоваяСтрокаТЗ.Количество = Число(Строка[1]);
НоваяСтрокаТЗ.Сумма = Число(Строка[2]);
КонецЦикла;
// Загружаем всю таблицу целиком
НовыйДок.Товары.Загрузить(ТЗ);
Одной из проблем, описанных в теме, стало появление «пустого» документа после выполнения серверного кода. Рассмотрим ситуацию: вы получили форму документа, программно заполнили ее данные на сервере, но при открытии формы данные не отображаются. Это происходит из-за некорректной работы с объектом ДанныеФормы.
При работе в управляемом приложении важно понимать, что форма работает с типом ДанныеФормыСтруктура (или ДанныеФормыКоллекция для таблиц), а не с самим объектом базы данных. Для решения проблемы мы рекомендуем использовать следующий подход: выполнять заполнение непосредственно в контексте формы или правильно использовать КопироватьДанныеФормы.
Выясним причину неудачи автора. Если вы вызываете процедуру заполнения и передаете туда Объект формы, убедитесь, что изменения применяются именно к нему. Посмотрим на правильный пример вызова:
&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
// Получаем данные из файла в массив 'Рез'
// ...
ЗаполнитьДокументНаСервере(Рез);
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьДокументНаСервере(Данные)
// Объект — это реквизит управляемой формы
Для Каждого СтрокаДанных Из Данные Цикл
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Количество = Число(СтрокаДанных[1]);
// Дальнейшее заполнение
КонецЦикла;
КонецПроцедуры
В сообщении 11 автор столкнулся с ошибкой «Поле не найдено» при поиске номенклатуры по штрихкоду. Проанализируем текст запроса:
Штрихкоды.Штрихкод = ЗначШтрихкод
Ошибка заключается в том, что в языке запросов 1С обращение к параметру всегда должно начинаться с символа амперсанда &. Без него платформа воспринимает ЗначШтрихкод как имя колонки (поля) в таблицах базы данных. Правильный код запроса должен выглядеть так:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Штрихкоды.Владелец КАК СсылкаНаНоменклатуру
|ИЗ
| РегистрСведений.Штрихкоды КАК Штрихкоды
|ГДЕ
| Штрихкоды.Штрихкод = &ЗначШтрихкод";
Запрос.УстановитьПараметр("ЗначШтрихкод", НужныйШтрихкод);
РезультатЗапроса = Запрос.Выполнить();
В финальных сообщениях темы обсуждалось, что номенклатура загружается, а числовые показатели (Количество, Сумма) — нет. Рассмотрим подробнее причину этого явления. При чтении текстового файла (через ЧтениеТекста или ТекстовыйДокумент) все данные считываются как тип Строка.
Когда вы пытаетесь присвоить строковое значение "10" числовому реквизиту табличной части напрямую, платформа иногда может выполнить неявное преобразование, но зачастую (особенно в сложных формах с обработчиками) это приводит к тому, что значение сбрасывается в 0.
Как избежать потери данных:
Число().СтрЗаменить().Пример надежного заполнения числовых полей:
// Очищаем строку от пробелов и преобразуем в число
СтроковоеЗначение = СтрЗаменить(СтрокаРезультат[1], Символы.НПП, "");
СтроковоеЗначение = СтрЗаменить(СтроковоеЗначение, " ", "");
НоваяСтрока.Количество = Число(СтроковоеЗначение);
Если вы работаете в современных решениях на базе БСП (например, УТ 11, ERP 2.5), поиск номенклатуры по штрихкоду через прямой запрос к регистру Штрихкоды может не сработать, так как структура хранения изменилась. Теперь часто используется регистр ШтрихкодыНоменклатуры, где владелец может быть не только номенклатурой, но и характеристикой или упаковкой.
Проанализируем ситуацию: для стабильной работы лучше использовать программный интерфейс (API) вашей конфигурации. Например, поиск через типовые модули:
// Пример для современных конфигураций (схематично)
ПараметрыПоиска = МенеджерОборудованияКлиентСервер.ПараметрыСканирования();
ДанныеШтрихкода = ШтрихкодыНоменклатурыКлиентСервер.ДанныеШтрихкода(Штрихкод);
Если ДанныеШтрихкода.Номенклатура <> Неопределено Тогда
НоваяСтрока.Номенклатура = ДанныеШтрихкода.Номенклатура;
КонецЕсли;
Подводя итог, можно сказать, что успешная загрузка данных в 1С требует внимательного отношения к типам переменных, строгого соблюдения синтаксиса запросов и понимания того, как данные передаются между серверным кодом и интерфейсом пользователя. Разбор ошибок, представленный выше, поможет вам избежать «детских болезней» при разработке собственных обработок загрузки.