После обновления конфигурации 1С:Бухгалтерия с версии 3.0.187.20 до 3.0.190.25 на платформе 8.3.27.1859 (клиент-сервер, SQL) внешние обработки могут перестать корректно работать, в частности, функция создания файлов Excel. В этой статье мы подробно разберем типичную проблему, когда файл не создается в заданном каталоге, и программа выдает сообщение "Не удалось записать файл № ...", а также предложим шаги по диагностике и устранению этой ошибки.
Для начала, давайте внимательно рассмотрим предоставленный код, который отвечает за формирование и сохранение файлов Excel. Обычно этот процесс состоит из двух частей: серверного вызова для формирования табличного документа и клиентского вызова для его сохранения.
Обратимся к серверной части, где происходит формирование табличного документа и помещение его во временное хранилище:
&НаСервере
Процедура СФ_СформироватьНаСервере
Для Каждого ТекСтрока Из Объект.СчетаФактуры Цикл
Если ТекСтрока.Создавать Тогда
Таб = Печать(ТекСтрока.Документ, ЛОЖЬ);
Адрес = ПоместитьВоВременноеХранилище(Таб, Новый УникальныйИдентификатор);
ТекСтрока.ПутьКФайлу = Адрес;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В этом блоке кода:
ТекСтрока.Создавать.Печать() для получения табличного документа (переменная Таб).Таб во временное хранилище, получая его адрес (переменная Адрес).ТекСтрока.ПутьКФайлу.Теперь рассмотрим клиентскую часть, где выполняется попытка получить табличный документ из временного хранилища и записать его на диск:
&НаКлиенте
Процедура ЗаписатьФайлыНаКлиенте
Для каждого ТекСтрока Из объект.СчетаФактуры Цикл
Если ЗначениеЗаполнено(ТекСтрока.ПутьКФайлу) Тогда
Файл = ПолучитьИзВременногоХранилища(ТекСтрока.ПутьКФайлу);
Если НЕ Файл = НЕОПРЕДЕЛЕНО Тогда
ИмяФайла = СокрЛП(ЭтаФорма.Каталог) + "\Счет-Фактура" + СокрЛП(ТекСтрока.НомерДокумента) + ".xls";
Файл.Записать(ИмяФайла,"XLS");
ТекСтрока.ПутьКФайлу = ИмяФайла;
Иначе
Сообщить("Не удалось записать файл № " + СокрЛП(ТекСтрока.НомерДокумента));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В этом клиентском блоке:
ТекСтрока.ПутьКФайлу.ПолучитьИзВременногоХранилища().Файл не НЕОПРЕДЕЛЕНО), формируем имя файла и сохраняем его.Файл = НЕОПРЕДЕЛЕНОПо описанию проблемы, сообщение "Не удалось записать файл № ..." указывает на то, что мы попадаем в блок Иначе в клиентской процедуре. Это однозначно говорит нам о том, что переменная Файл после вызова ПолучитьИзВременногоХранилища(ТекСтрока.ПутьКФайлу) получает значение НЕОПРЕДЕЛЕНО. Теперь нам необходимо выяснить, почему это происходит.
ПолучитьИзВременногоХранилища() может возвращать НЕОПРЕДЕЛЕНОТекСтрока.ПутьКФайлуПрежде всего, нам необходимо убедиться, что поле ТекСтрока.ПутьКФайлу действительно содержит корректный адрес временного хранилища к моменту вызова клиентской процедуры. Рассмотрим потенциальные проблемы:
ТекСтрока.Создавать: Проверьте в отладчике на сервере, выполняется ли условие Если ТекСтрока.Создавать Тогда. Если этот флаг по какой-либо причине не установлен, то блок кода, помещающий табличный документ в хранилище, не будет выполнен, и ТекСтрока.ПутьКФайлу останется незаполненным.Печать(): Убедитесь, что функция Печать(ТекСтрока.Документ, ЛОЖЬ) успешно возвращает табличный документ и переменная Таб заполнена. Возможно, в новой версии конфигурации произошли изменения во внутренней функции Печать или ее параметрах, что приводит к возврату пустого или некорректного значения.ТекСтрока.ПутьКФайлу = Адрес; действительно присваивает полученный адрес.Данные, помещенные во временное хранилище, имеют ограниченный "срок жизни". Они привязаны к сеансу и могут быть удалены в определенных ситуациях:
УникальныйИдентификатор: При вызове ПоместитьВоВременноеХранилище(Значение, УникальныйИдентификатор) второй параметр (Новый УникальныйИдентификатор) играет важную роль. Если этот параметр не указан или указан неверно (например, каждый раз генерируется новый без сохранения), то помещенное значение может быть удалено раньше времени, например, после очередного запроса сервера, при контекстном или неконтекстном серверном вызове из формы, или при серверном вызове из модуля команды. Убедитесь, что УникальныйИдентификатор, если он используется для "продления жизни" данных, действительно уникален для сеанса и корректно передается. В вашем коде используется Новый УникальныйИдентификатор, что является корректным подходом для создания нового адреса. Проблема может быть в том, что сам объект во временном хранилище "умирает" из-за других серверных вызовов между моментом помещения и моментом получения.В дополнение к основной проблеме, связанной с получением файла из хранилища, важно проверить синтаксис записи файла. В вашем коде используется строка:
Файл.Записать(ИмяФайла,"XLS");
Хотя в старых версиях платформы это могло работать, рекомендуется использовать перечисление ТипФайлаТабличногоДокумента для явного указания формата сохранения. Правильный синтаксис должен быть таким:
Файл.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLS);
Это обеспечивает явное и безопасное указание формата, что может предотвратить потенциальные ошибки или несовместимости с новыми версиями платформы или форматов файлов.
Необходимо также убедиться, что формируемое имя файла и путь к каталогу корректны и не содержат запрещенных символов. Несмотря на то, что это, вероятно, не является основной причиной вашей проблемы (так как она проявляется на этапе получения файла, а не записи), это важный аспект при работе с файловой системой.
ИмяФайла = СокрЛП(ЭтаФорма.Каталог) + "\Счет-Фактура" + СокрЛП(ТекСтрока.НомерДокумента) + ".xls";
ТекСтрока.НомерДокумента не содержит символов, запрещенных для использования в именах файлов операционной системой (например, \ / : * ? " < > |).ЭтаФорма.Каталог содержит существующий и доступный путь.Самый эффективный способ найти причину проблемы — это использовать отладчик 1С. Мы предлагаем следующий план действий:
СФ_СформироватьНаСервере):
Если ТекСтрока.Создавать Тогда.ТекСтрока.Создавать. Должно быть Истина.Таб = Печать(ТекСтрока.Документ, ЛОЖЬ);. После выполнения этой строки проверьте, заполнена ли переменная Таб. В рабочем варианте вы утверждаете, что она заполнена, это важно подтвердить и для нерабочего. Если Таб НЕОПРЕДЕЛЕНО или пустой табличный документ, то это и есть корень проблемы.Адрес = ПоместитьВоВременноеХранилище(Таб, Новый УникальныйИдентификатор);. После выполнения проверьте, что переменная Адрес получила корректный путь к временному хранилищу (например, "e1cib/tempstorage/c33f2c5d-c6a6-44b2-a42e-ec5f8c32d9f3").ТекСтрока.ПутьКФайлу = Адрес;. Убедитесь, что адрес успешно присвоен объекту.ЗаписатьФайлыНаКлиенте):
Файл = ПолучитьИзВременногоХранилища(ТекСтрока.ПутьКФайлу);.ТекСтрока.ПутьКФайлу. Оно должно быть тем же самым адресом, который мы получили на сервере. Если значение другое, или оно пустое, то причина уже здесь.Файл = ПолучитьИзВременногоХранилища(ТекСтрока.ПутьКФайлу);.Файл. Если она НЕОПРЕДЕЛЕНО, это подтверждает вашу проблему.Файл все еще НЕОПРЕДЕЛЕНО, это указывает на то, что объект из временного хранилища не был найден или был удален. Вероятные причины:
ПоместитьВоВременноеХранилище и ПолучитьИзВременногоХранилища, которые могли привести к очистке хранилища.Файл заполнен, тогда проверьте формирование ИмяФайла и синтаксис Файл.Записать().Если после тщательной отладки вы не смогли найти прямую причину, или она оказалась связана с глубинными изменениями в платформе или БСП, рассмотрите следующие подходы:
ТипФайлаТабличногоДокумента: Как уже было указано, всегда явно указывайте тип файла при сохранении:
Файл.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX); // Или ТипФайлаТабличногоДокумента.XLS
Это не только правильный подход, но и может решить проблемы совместимости форматов в новых версиях.
Печать() использует БСП-функции, возможно, их сигнатуры или логика работы изменились. Попробуйте найти аналогичные функции в новой конфигурации и сравнить их с вашей реализацией.ПотокВПамяти) и последующим чтением из них, или даже через промежуточный файл на сервере, а затем передачу его на клиент.Мы настоятельно рекомендуем начать с пошаговой отладки. Только так вы сможете точно определить, на каком именно этапе происходит сбой и почему переменная Файл становится НЕОПРЕДЕЛЕНО. После выявления корневой причины, применение вышеуказанных рекомендаций поможет эффективно устранить проблему.