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