Как исправить ошибки при загрузке контрагентов из CSV и обеспечить корректный поиск по ИНН в 1С

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

Загрузка данных из внешних файлов — одна из самых частых задач для разработчика 1С. Однако даже в простом коде чтения текстового документа могут скрываться ошибки, которые приводят к остановке выполнения программы. В этой статье мы подробно разберем, как исправить типичные ошибки «Переменная не определена» и «Недостаточно фактических параметров», а также оптимизируем алгоритм загрузки для профессиональной работы с базой данных.

Разбор первой ошибки: Недостаточно фактических параметров

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

НовыйКонтрагент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН");

В данном случае система не понимает, какое именно значение ИНН нужно найти. Исправим это, передав второй параметр — переменную, содержащую значение из файла. Посмотрим, как должен выглядеть корректный вызов:


// Правильный синтаксис: НайтиПоРеквизиту("ИмяРеквизита", ЗначениеПоиска)
НовыйКонтрагент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ИННКонтрагента);

Исправление ошибки: Переменная не определена (ИНН)

Часто при копировании или быстром написании кода возникают опечатки. В исходном примере автор использовал переменную ИННКонтрагента для получения данных из массива, но при поиске обратился к несуществующей переменной ИНН. Выясним причину: компьютер строго различает имена переменных, и для него ИНН и ИННКонтрагента — это абсолютно разные объекты.

Чтобы решить проблему, нам нужно убедиться, что во всем цикле используется одно и то же имя переменной. Рассмотрим исправленный блок кода:


// Извлекаем данные из массива (вторая колонка CSV)
ИННКонтрагента = МассивЗначенийСтроки[1];

// Используем именно эту переменную для поиска в справочнике
НовыйКонтрагент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", Строка(ИННКонтрагента));

Корректировка логики: Поиск перед созданием

Разберем важный архитектурный момент. В исходном коде создание нового элемента (СоздатьЭлемент()) происходило вне основного цикла или некорректно сочеталось с проверкой на дубли. Если мы не проверим существование контрагента перед созданием, база данных быстро заполнится дублями.

Проанализируем правильную последовательность действий внутри цикла:

  1. Получаем данные из строки файла.
  2. Пытаемся найти контрагента в базе по ИНН.
  3. Если контрагент не найден (ссылка пустая), то создаем новый объект.
  4. Заполняем реквизиты и записываем.

Посмотрим на пример реализации этой логики:


Для НомерСтроки = 2 По Документ.КоличествоСтрок() Цикл
    СтрокаДокумента = Документ.ПолучитьСтроку(НомерСтроки);
    МассивЗначенийСтроки = СтрРазделить(СтрокаДокумента, ";");
    
    НаименованиеКонтрагента = МассивЗначенийСтроки[0];
    ИННКонтрагента = МассивЗначенийСтроки[1];

    // Ищем, нет ли уже такого контрагента в базе
    НайденнаяСсылка = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ИННКонтрагента);

    Если НайденнаяСсылка.Пустая() Тогда
        // Создаем новый элемент, если поиск не дал результатов
        ОбъектКонтрагент = Справочники.Контрагенты.СоздатьЭлемент();
        ОбъектКонтрагент.Наименование = НаименованиеКонтрагента;
        ОбъектКонтрагент.ИНН = ИННКонтрагента;
        // Установим дополнительные реквизиты, например, ЮрФизЛицо
        ОбъектКонтрагент.Записать();
    Иначе
        // Контрагент уже есть, можно обновить его данные или пропустить
        Продолжить;
    КонецЕсли;
КонецЦикла;

Продвинутые методы оптимизации загрузки

Для того чтобы ваша обработка работала быстро и надежно, рассмотрим несколько профессиональных советов, которые помогут избежать проблем при больших объемах данных.

1. Использование запросов вместо поиска в цикле. Метод НайтиПоРеквизиту внутри цикла — это «тяжелая» операция, так как она создает отдельный запрос к базе на каждой итерации. Если в файле 10 000 строк, будет 10 000 обращений. Проанализируем более эффективный путь:

2. Проблема ведущих нулей в ИНН. В некоторых регионах ИНН начинается с нуля. При чтении из CSV 1С может ошибочно интерпретировать это как число и отбросить ноль. Всегда используйте явное преобразование к строке и проверяйте длину ИНН (10 символов для юридических лиц и 12 для физических). Если символов меньше, нужно добавить недостающие нули слева с помощью функции Прав() или специализированных функций БСП.

3. Использование объекта ЧтениеТекста. Объект ТекстовыйДокумент загружает весь файл в память целиком. Если ваш файл CSV весит несколько сотен мегабайт, сервер может выдать ошибку нехватки памяти. Разберем альтернативу — ЧтениеТекста:


ФайлЧтения = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8);
СтрокаФайла = ФайлЧтения.ПрочитатьСтроку(); // Читаем заголовок
СтрокаФайла = ФайлЧтения.ПрочитатьСтроку(); // Первая строка данных
Пока СтрокаФайла <> Неопределено Цикл
    // Обработка строки...
    СтрокаФайла = ФайлЧтения.ПрочитатьСтроку();
КонецЦикла;

4. Транзакционная запись. Чтобы в случае ошибки в середине файла у вас не записалась «половина» данных, используем механизм транзакций. Это обеспечит целостность данных в информационной базе.


НачатьТранзакцию();
Попытка
    // Весь код загрузки здесь
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    Сообщить("Ошибка при загрузке: " + ОписаниеОшибки());
КонецПопытки;

Применяя эти подходы, мы не только исправляем текущие ошибки компиляции, но и создаем отказоустойчивый инструмент для интеграции данных в 1С.

← На главную