Как исправить ошибку «деление на ноль» при загрузке данных из Excel в 1С?

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

При автоматизации складского учета часто возникает необходимость загрузки данных из внешних файлов, таких как Excel. Однако даже отлаженная программистом обработка может внезапно дать сбой с неочевидной ошибкой, например, деление на ноль. В этой статье мы детально разберем, почему возникает такая ситуация при использовании COM-объектов, как найти проблемную строку в коде и какие нюансы в данных справочника Номенклатура могут приводить к фатальной остановке процесса.

Поиск причины ошибки: диагностика и локализация

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

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

Использование блока Попытка...Исключение для выявления ошибки

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

Вместо прямой команды записи используем следующую конструкцию:


Попытка
    Док.Записать(РежимЗаписиДокумента.Проведение);
Исключение
    Инфо = ИнформацияОбОшибке();
    Сообщить("Описание ошибки: " + Инфо.Описание);
    Сообщить("Имя модуля: " + Инфо.ИмяМодуля);
    Сообщить("Номер строки кода: " + Инфо.НомерСтроки);
    Сообщить("Исходная строка кода: " + Инфо.ИсходнаяСтрока);
КонецПопытки;

Этот фрагмент кода крайне полезен, так как он не просто прерывает работу программы, а дает нам «карту» для поиска. Если ошибка происходит внутри общего модуля 1С при расчете итогов, мы увидим это в описании. Если же ошибка в самой обработке — номер строки укажет на конкретное вычисление.

Анализ кода загрузки и работа с коэффициентами

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


НаимТовар = Сокрлп(НашЛист.Cells(й2,5).Value);
Товар = Справочники.Номенклатура.НайтиПоНаименованию(НаимТовар, Истина);

Если Не Товар.Пустая() Тогда
    Кол = НашЛист.Cells(й2,9).Value;
    Если Кол <> 0 Тогда
        Стр = Док.Товары.Добавить();
        Стр.Товар = Товар;
        Стр.Единица = Товар.БазоваяЕдиница;
        Стр.Коэффициент = Стр.Единица.Коэффициент; // Потенциально опасное место!
        Стр.Количество = Кол;
    КонецЕсли;
КонецЕсли;

Проанализируем строку Стр.Коэффициент = Стр.Единица.Коэффициент;. Это одно из самых «узких» мест в логике. Если в справочнике Номенклатура у товара не заполнена единица измерения или у самой единицы измерения Коэффициент равен нулю, система может выдать ошибку деления на ноль при проведении документа. Это происходит потому, что 1С при формировании движений по регистрам пересчитывает количество в базовые единицы, используя этот коэффициент как делитель или множитель.

Проблемы в данных Excel и использование COM-объекта

Когда мы работаем через Excel.Application, 1С обращается к ячейкам файла напрямую. Здесь нас могут подстерегать «подводные камни» в виде битых формул в самом Excel. Если в ячейке с количеством или ценой в Excel отображается #ДЕЛ/0!, то при попытке прочитать Value этой ячейки, 1С получит не число, а объект ошибки, что приведет к непредсказуемому поведению.

Рассмотрим, как обезопасить чтение данных. Рекомендуется всегда явно приводить значение из Excel к числовому типу и проверять его:


ЗначениеИзЯчейки = НашЛист.Cells(й2, 9).Value;
Попытка
    Кол = Число(ЗначениеИзЯчейки);
Исключение
    Кол = 0;
    Сообщить("В строке " + й2 + " некорректное значение количества!");
КонецПопытки;

Оптимизация работы с транзакциями и памятью

В представленном коде используется конструкция НачатьТранзакцию() и ЗафиксироватьТранзакцию(). Это правильный подход для обеспечения целостности данных, однако он требует осторожности. Если внутри транзакции происходит ошибка деление на ноль, транзакция остается «висеть», что может привести к блокировкам базы данных.

Выясним, как правильно завершать работу с внешним приложением Excel. Часто после ошибки в диспетчере задач остаются процессы EXCEL.EXE, которые «съедают» оперативную память и блокируют файлы. Чтобы этого избежать, всегда закрывайте книгу и обнуляйте объект в блоке завершения:


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

НашФайл.Close(Ложь);
Эксел.Quit();
Эксел = Неопределено;

Практические советы по поиску «битых» строк

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

  1. Добавьте в цикл загрузки вывод текущей строки: Состояние("Обработка строки: " + й2); или Сообщить("Строка: " + й2);.
  2. Запустите обработку. Последний номер строки, который появится в окне сообщений перед возникновением ошибки, и будет искомым.
  3. Проверьте эту строку в Excel: нет ли там пустых ячеек, пробелов вместо цифр или ошибок в формулах.
  4. Проверьте карточку товара в 1С, который указан в этой строке: заполнены ли единицы измерения и их коэффициенты.

Таким образом, мы выяснили, что ошибка деление на ноль чаще всего является следствием некорректных входных данных. Тщательная проверка реквизитов Номенклатуры и очистка данных в исходном Excel файле в 90% случаев решают проблему без радикального изменения программного кода.

← На главную