Как исправить запись одинаковых данных в Excel через COM-объект 1С

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

Работа с внешними приложениями через технологию COM является классическим способом интеграции 1С с Microsoft Excel. Однако при написании кода часто возникают логические ловушки, из-за которых данные обрабатываются некорректно — например, во все строки записывается одно и то же значение из последней итерации цикла. Рассмотрим подробнее, как правильно организовать алгоритм разбора строк и записи результатов, а также разберем сопутствующие технические нюансы.

Анализ основной проблемы: почему данные дублируются

Проанализируем ситуацию, представленную в исходном коде. Основная ошибка заключается в разделении процесса обработки данных на несколько независимых циклов. В первом цикле автор пытается найти вхождение подстроки, во втором — выделить характеристики, а в третьем — записать результат в ячейки.

Разберем, что происходит в памяти компьютера: когда завершается второй цикл, переменные ШКХарактеристика и ШКМодель хранят значения, полученные на последней итерации (для последней строки файла). Затем запускается третий цикл по переменной k, который просто копирует эти зафиксированные значения во все строки подряд. В итоге весь результирующий файл заполняется дублями последней строки.

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

Реструктуризация кода: объединение циклов

Вместо того чтобы плодить три разных цикла, мы будем обрабатывать каждую строку индивидуально. Прочитали строку — разобрали ее на части — сразу записали в нужные колонки этой же строки. Это не только исправит логическую ошибку, но и значительно ускорит работу скрипта.


&НаКлиенте
Процедура ОбработатьФайлExcel(Команда)
    
    // Подготовка объекта Excel
    Попытка
        Эксель = Новый COMОбъект("Excel.Application");
    Исключение
        Сообщить("Excel не установлен на данном компьютере!");
        Возврат;
    КонецПопытки;
    
    // Указывать прямые пути к файлам важно для стабильности
    ПутьКФайлу = "C:\Temp\art_.xls"; 
    ИтоговыйФайл = "C:\Temp\art_2.xls";
    
    Книга = Эксель.WorkBooks.Open(ПутьКФайлу);
    Лист = Книга.WorkSheets(1);
    
    // Отключаем обновление экрана для ускорения процесса
    Эксель.ScreenUpdating = 0;
    Эксель.Calculation = -4135; // xlCalculationManual
    
    КолВоСтрок = Лист.UsedRange.Rows.Count;
    
    Для i = 1 По КолВоСтрок Цикл
        
        // Получаем исходное значение из второй колонки
        ИсходныйТекст = СокрЛП(Лист.Cells(i, 2).Value);
        Если ПустаяСтрока(ИсходныйТекст) Тогда
            Продолжить;
        КонецЕсли;
        
        // 1. Поиск ключевого слова "Модель"
        ПозицияМодель = Найти(ИсходныйТекст, "Модель");
        Если ПозицияМодель > 0 Тогда
            // Извлекаем часть строки после слова "Модель"
            ОбработаннаяСтрока = Сред(ИсходныйТекст, ПозицияМодель);
            
            // 2. Разбор на Модель и Характеристику по первому пробелу
            ПоискПробела = Найти(ОбработаннаяСтрока, " ");
            Если ПоискПробела > 0 Тогда
                ТекШКМодель = Лев(ОбработаннаяСтрока, ПоискПробела - 1);
                ТекШКХарактеристика = Сред(ОбработаннаяСтрока, ПоискПробела + 1);
            Иначе
                ТекШКМодель = ОбработаннаяСтрока;
                ТекШКХарактеристика = "";
            КонецЕсли;
            
            // 3. Запись результатов в нужные колонки сразу
            Лист.Cells(i, 3).Value = ТекШКМодель;
            Лист.Cells(i, 4).Value = ТекШКХарактеристика;
            
            // Установка текстового формата для штрихкодов, чтобы Excel не обрезал нули
            Лист.Cells(i, 1).NumberFormat = "@"; 
        КонецЕсли;
        
    КонецЦикла;
    
    // Удаление ненужной теперь колонки B
    Лист.Columns("B:B").Delete();
    
    // Сохранение и закрытие
    Эксель.DisplayAlerts = 0;
    Книга.SaveAs(ИтоговыйФайл);
    Книга.Close();
    Эксель.Quit();
    
    // Обязательная очистка переменной для выгрузки процесса из памяти
    Эксель = Неопределено;
    
    Сообщить("Обработка завершена успешно!");
    
КонецПроцедуры

Работа с путями и системными переменными

Выясним причину, по которой код может выдавать ошибку на этапе открытия файла. В исходном примере автор использовал путь %USERPROFILE%\Desktop\art_.xls. Важно понимать, что 1С не умеет автоматически распознавать переменные окружения Windows (такие как %USERPROFILE% или %APPDATA%) в строковых переменных.

Для того чтобы получить реальный путь к рабочему столу текущего пользователя, необходимо воспользоваться объектом WScript.Shell. Проанализируем пример получения корректного пути:


Шелл = Новый COMОбъект("WScript.Shell");
ПутьКРабочемуСтолу = Шелл.SpecialFolders("Desktop");
ПолныйПуть = ПутьКРабочемуСтолу + "\art_.xls";

Также обратим внимание на опечатку в исходном сообщении: Desktop]art_2.xls. Использование закрывающей квадратной скобки вместо обратного слэша гарантированно приведет к ошибке доступа к файлу.

Оптимизация форматирования и типов данных

При записи данных в Excel из 1С программисты часто сталкиваются с тем, что длинные числовые коды (артикулы или штрихкоды) преобразуются в экспоненциальный вид (например, 4,6E+12). Чтобы этого избежать, рассмотрим несколько правил:

  1. Текстовый формат: Для колонок со штрихкодами всегда устанавливайте формат @ (текстовый) ДО записи данных в ячейку. Это делается командой Лист.Columns(НомерКолонки).NumberFormat = "@".
  2. Числовой формат: Если вам нужно число без знаков после запятой, используйте NumberFormat = "0".
  3. Очистка памяти: После завершения работы с COM-объектом недостаточно просто вызвать Quit(). Нужно обязательно присвоить переменной значение Неопределено, иначе процесс EXCEL.EXE останется висеть в диспетчере задач, блокируя файл для других пользователей.

Альтернативный способ: использование Табличного документа

Посмотрим на ситуацию шире. Если ваша задача сводится к простому преобразованию данных и сохранению их в формат Excel, использование COM-объекта может быть избыточным и медленным. В 1С есть встроенный мощный инструмент — ТабличныйДокумент.

Мы можем программно заполнить таблицу в 1С, используя метод Область(), а затем вызвать встроенный метод Записать() с типом файла ТипФайлаТабличногоДокумента.XLSX. Этот метод работает в десятки раз быстрее, не требует наличия установленного Microsoft Office на сервере или компьютере пользователя и работает стабильнее в фоновых заданиях.

Таким образом, для решения задачи автора достаточно было объединить циклы обработки в один, корректно определить пути к файлам и не забыть про очистку COM-соединения в конце процедуры. Это обеспечит корректную запись различных данных в каждую строку и стабильную работу системы.

← На главную