При работе с файлами формата xlsx через 1С:Предприятие разработчики часто сталкиваются с тем, что файл оказывается «заблокирован» или «уже открыт в другой программе». Эта проблема возникает, когда операционная система ограничивает доступ к файлу, так как процесс EXCEL.EXE еще не завершил работу, либо сам метод ТабличныйДокумент.Прочитать() требует эксклюзивного доступа. Давайте разберем, как избавиться от этой ошибки и сделать обмен данными стабильным.
Основная причина заключается в том, что COM-объект Excel — это полноценное приложение. Даже если мы вызываем команду Excel.Quit, процесс в памяти может закрываться с задержкой. Кроме того, если в коде возникла ошибка до момента закрытия объекта, Excel.Application остается «висеть» в диспетчере задач, продолжая удерживать файл. Метод ТабличныйДокумент.Прочитать() также весьма требователен: при чтении файлов формата xlsx он часто конфликтует с уже открытыми в Excel документами.
Самый надежный способ избежать конфликтов блокировок — не работать с исходным файлом напрямую. Вместо этого мы будем копировать целевой файл во временный каталог пользователя и считывать данные уже из копии.
Этот метод гарантирует, что даже если исходный файл открыт у пользователя, 1С будет работать со своей локальной копией, на которую не распространяются ограничения доступа.
ИмяФайлаИсточник = \"C:\\Docs\\Data.xlsx\";
ИмяВременногоФайла = ПолучитьИмяВременногоФайла(\"xlsx\");
КопироватьФайл(ИмяФайлаИсточник, ИмяВременногоФайла);
ТабДокумент = Новый ТабличныйДокумент;
ТабДокумент.Прочитать(ИмяВременногоФайла, СпособЧтенияЗначенийТабличногоДокумента.Текст);
УдалитьФайлы(ИмяВременногоФайла);
Если вам необходимо использовать именно COM-объект, важно убедиться, что приложение закрывается полностью. Часто программисты забывают закрыть рабочую книгу Workbooks перед закрытием самого приложения.
Рассмотрим правильный порядок действий:
ReadOnly, чтобы не блокировать изменения для других пользователей.Excel значение Неопределено (или 0), чтобы принудительно очистить память.
Попытка
Excel = Новый COMОбъект(\"Excel.Application\");
// Открываем файл: ИмяФайла, [UpdateLinks], [ReadOnly]
Excel.Workbooks.Open(ИмяФайла, 0, True);
// Выполняем действия с листами
Лист = Excel.Workbooks(1).Worksheets(1);
// ... логика обработки ...
Excel.ActiveWorkbook.Close(False); // Закрываем книгу без сохранения
Excel.Quit(); // Закрываем приложение
Excel = 0; // Освобождаем память
Исключение
// В случае ошибки обязательно закрываем приложение, чтобы оно не зависло
Если Excel <> 0 Тогда
Excel.DisplayAlerts = 0;
Excel.Quit();
Excel = 0;
КонецЕсли;
КонецПопытки;
Если вы комбинируете COM-объект и ТабличныйДокумент в одной процедуре, попробуйте изменить последовательность их вызовов. Часто ошибка возникает из-за того, что COM-объект успевает «захватить» файл, а последующая команда Прочитать() уже не может получить к нему доступ. Попробуйте сначала считать данные методом ТабличныйДокумент.Прочитать(), а уже потом использовать тяжелые COM-интерфейсы.
Чтобы код работал максимально предсказуемо, примите на вооружение следующие рекомендации:
Попытка...Исключение при работе с COM. Это позволит закрыть экземпляр Excel даже в том случае, если в коде возникнет ошибка.DisplayAlerts. Установка свойства Excel.DisplayAlerts = 0 позволяет подавить диалоговые окна (например, «Сохранить изменения?»), которые могут возникнуть при попытке закрытия файла и остановить выполнение кода 1С.Workbooks. Недостаточно просто написать Excel.Quit(). Всегда закрывайте открытую книгу методом Close(), чтобы освободить дескриптор файла.Применение этих методов позволит вам раз и навсегда забыть об ошибках доступа и значительно повысить надежность ваших обработок по загрузке данных из форматов MS Excel.