При автоматизации складского учета часто возникает необходимость загрузки данных из внешних файлов, таких как Excel. Однако даже отлаженная программистом обработка может внезапно дать сбой с неочевидной ошибкой, например, деление на ноль. В этой статье мы детально разберем, почему возникает такая ситуация при использовании COM-объектов, как найти проблемную строку в коде и какие нюансы в данных справочника Номенклатура могут приводить к фатальной остановке процесса.
Прежде чем приступать к исправлению кода, нам необходимо понять, в какой именно момент происходит ошибка. В 1С ошибка деление на ноль может возникнуть как непосредственно в теле обработки при вычислениях, так и внутри типовых механизмов платформы при попытке записи или проведения документа. Рассмотрим алгоритм поиска «виновника» по шагам.
Проанализируем ситуацию: если загрузка десяти документов проходит успешно, а на одиннадцатом возникает ошибка, значит, проблема кроется в специфических данных конкретного файла. Для начала попробуем изменить режим записи документа. Если в коде стоит РежимЗаписиДокумента.Проведение, заменим его на простой Запись. Это позволит исключить ошибки, возникающие при расчете регистров и себестоимости. Однако, если ошибка сохраняется даже при записи, нам потребуется расширенная диагностика.
Чтобы не гадать, на какой строке Excel-файла происходит сбой, мы воспользуемся механизмом перехвата исключений. Это позволит нам вывести в окно сообщений подробную информацию о месте возникновения проблемы. Рассмотрим, как модифицировать стандартный код записи документа.
Вместо прямой команды записи используем следующую конструкцию:
Попытка
Док.Записать(РежимЗаписиДокумента.Проведение);
Исключение
Инфо = ИнформацияОбОшибке();
Сообщить("Описание ошибки: " + Инфо.Описание);
Сообщить("Имя модуля: " + Инфо.ИмяМодуля);
Сообщить("Номер строки кода: " + Инфо.НомерСтроки);
Сообщить("Исходная строка кода: " + Инфо.ИсходнаяСтрока);
КонецПопытки;
Этот фрагмент кода крайне полезен, так как он не просто прерывает работу программы, а дает нам «карту» для поиска. Если ошибка происходит внутри общего модуля 1С при расчете итогов, мы увидим это в описании. Если же ошибка в самой обработке — номер строки укажет на конкретное вычисление.
Разберем типичный код обработки, который часто становится причиной подобных проблем. Обратим внимание на фрагмент, где заполняется табличная часть документа ОприходованиеТоваров:
НаимТовар = Сокрлп(НашЛист.Cells(й2,5).Value);
Товар = Справочники.Номенклатура.НайтиПоНаименованию(НаимТовар, Истина);
Если Не Товар.Пустая() Тогда
Кол = НашЛист.Cells(й2,9).Value;
Если Кол <> 0 Тогда
Стр = Док.Товары.Добавить();
Стр.Товар = Товар;
Стр.Единица = Товар.БазоваяЕдиница;
Стр.Коэффициент = Стр.Единица.Коэффициент; // Потенциально опасное место!
Стр.Количество = Кол;
КонецЕсли;
КонецЕсли;
Проанализируем строку Стр.Коэффициент = Стр.Единица.Коэффициент;. Это одно из самых «узких» мест в логике. Если в справочнике Номенклатура у товара не заполнена единица измерения или у самой единицы измерения Коэффициент равен нулю, система может выдать ошибку деления на ноль при проведении документа. Это происходит потому, что 1С при формировании движений по регистрам пересчитывает количество в базовые единицы, используя этот коэффициент как делитель или множитель.
Когда мы работаем через Excel.Application, 1С обращается к ячейкам файла напрямую. Здесь нас могут подстерегать «подводные камни» в виде битых формул в самом Excel. Если в ячейке с количеством или ценой в Excel отображается #ДЕЛ/0!, то при попытке прочитать Value этой ячейки, 1С получит не число, а объект ошибки, что приведет к непредсказуемому поведению.
Рассмотрим, как обезопасить чтение данных. Рекомендуется всегда явно приводить значение из Excel к числовому типу и проверять его:
ЗначениеИзЯчейки = НашЛист.Cells(й2, 9).Value;
Попытка
Кол = Число(ЗначениеИзЯчейки);
Исключение
Кол = 0;
Сообщить("В строке " + й2 + " некорректное значение количества!");
КонецПопытки;
В представленном коде используется конструкция НачатьТранзакцию() и ЗафиксироватьТранзакцию(). Это правильный подход для обеспечения целостности данных, однако он требует осторожности. Если внутри транзакции происходит ошибка деление на ноль, транзакция остается «висеть», что может привести к блокировкам базы данных.
Выясним, как правильно завершать работу с внешним приложением Excel. Часто после ошибки в диспетчере задач остаются процессы EXCEL.EXE, которые «съедают» оперативную память и блокируют файлы. Чтобы этого избежать, всегда закрывайте книгу и обнуляйте объект в блоке завершения:
Попытка
// Основной код загрузки
Исключение
ОтменитьТранзакцию();
Сообщить("Загрузка прервана из-за ошибки.");
КонецПопытки;
НашФайл.Close(Ложь);
Эксел.Quit();
Эксел = Неопределено;
Если файл Excel содержит тысячи строк, ручной поиск ошибки невозможен. Рассмотрим эффективный метод локализации:
Состояние("Обработка строки: " + й2); или Сообщить("Строка: " + й2);.Таким образом, мы выяснили, что ошибка деление на ноль чаще всего является следствием некорректных входных данных. Тщательная проверка реквизитов Номенклатуры и очистка данных в исходном Excel файле в 90% случаев решают проблему без радикального изменения программного кода.