При разработке внешних обработок выгрузки данных в 1С:Зарплата и Управление Персоналом 3.1 разработчики нередко сталкиваются с ошибкой при вызове метода контекста СоздатьФайл объекта XBase. Код, который безупречно работал в обычных формах на платформе «1С:Предприятие 8.2», в клиент-серверной архитектуре управляемого приложения начинает выдавать исключение «Ошибка создания файла». Разберем причины возникновения этой проблемы и пошагово построим надежный механизм формирования и выгрузки DBF-файлов.
Проанализируем стандартную ситуацию: процедура формы объявлена с директивой компиляции &НаСервере, а внутри нее указан путь к локальному диску пользователя, например, D:\FOMS.DBF. В клиент-серверном режиме кластер 1С исполняет этот код на стороне физического сервера. Это порождает сразу две проблемы:
D:, которого на серверной машине может вовсе не существовать либо к корню которого нет доступа на запись.USR1CV8). У этой службы нет прав доступа к рабочему столу, профилям пользователей и локальным накопителям клиентских компьютеров.Кроме того, если разработчик пытается передать серверу путь к подключенному сетевому диску (например, Z:\Share), серверная служба его не увидит, так как буквы сетевых дисков монтируются только внутри интерактивного сеанса конкретного пользователя Windows. Сервер способен работать только с прямыми сетевыми путями в формате UNC (\\server\share\file.dbf) и исключительно при наличии соответствующих прав у служебной учетной записи 1С.
После переноса пути во временный каталог программисты часто сталкиваются со следующим исключением: платформа сообщает, что длина имени файла превышает допустимую, даже если имя кажется коротким. Выясним причину такого поведения.
Встроенный в 1С объект XBase жестко привязан к стандарту таблиц dBASE III/IV. Имя самого файла (без учета расширения) не может быть длиннее 8 символов. Типичная ловушка возникает при вызове штатной функции ПолучитьИмяВременногоФайла(".dbf"). Платформа генерирует уникальное имя по шаблону вида v8_XXXX_YY.dbf, длина которого вместе с префиксом практически всегда превышает 8 символов, что сразу приводит к падению метода СоздатьФайл.
Также важно помнить о жестких ограничениях по структуре самих таблиц DBF:
S) составляет 254 символа.XBase не поддерживает поля неограниченной длины типа Memo.Рассмотрим по шагам архитектурно правильное решение для ЗУП 3.1. Создавать файл напрямую на клиенте не рекомендуется, так как системное перечисление КодировкаXBase недоступно на тонком клиенте (оно работает только на сервере или в толстом клиенте). Оптимальный сценарий выглядит так: формируем файл во временной папке сервера, закрываем его, помещаем во временное хранилище и асинхронно передаем клиенту.
Посмотрим на пример серверной функции, которая выполняет выгрузку:
&НаСервере
Функция СформироватьDBFНаСервере()
// Формируем имя файла с ограничением не более 8 символов
ИмяФайла = "EXP_" + Лев(Строка(Новый УникальныйИдентификатор()), 4) + ".dbf";
ПолныйПутьСервер = КаталогВременныхФайлов() + ИмяФайла;
БД = Новый XBase;
БД.Кодировка = КодировкаXBase.ANSI;
// Описываем структуру колонок (имена латиницей до 10 знаков)
БД.Поля.Добавить("ID", "N", 10, 0);
БД.Поля.Добавить("FIO", "S", 100, 0);
БД.Поля.Добавить("SUMMA", "N", 15, 2);
Попытка
БД.СоздатьФайл(ПолныйПутьСервер);
Исключение
ВызватьИсключение "Не удалось создать DBF-файл на сервере: " + ОписаниеОшибки();
КонецПопытки;
// Заполняем строки данными
Попытка
Для Счетчик = 1 По 5 Цикл
БД.Добавить();
БД.ID = Счетчик;
БД.FIO = "Иванов Иван Иванович";
БД.SUMMA = 15000.50;
БД.Записать();
КонецЦикла;
Исключение
БД.ЗакрытьФайл();
УдалитьФайлы(ПолныйПутьСервер);
ВызватьИсключение "Ошибка при записи строк в DBF: " + ОписаниеОшибки();
КонецПопытки;
// Обязательно освобождаем монопольную блокировку файла
БД.ЗакрытьФайл();
// Помещаем сформированный файл во временное хранилище
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПолныйПутьСервер);
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла, УникальныйИдентификатор);
// Удаляем временный файл с диска сервера
УдалитьФайлы(ПолныйПутьСервер);
Возврат АдресХранилища;
КонецФункции
Теперь разберем клиентскую часть. Чтобы соответствовать стандартам платформы 1С:Предприятие 8.3 и избежать использования устаревших синхронных вызовов, воспользуемся асинхронным методом передачи файла пользователю:
&НаКлиенте
Процедура ВыполнитьВыгрузку(Команда)
АдресВХранилище = СформироватьDBFНаСервере();
Если Не ЗначениеЗаполнено(АдресВХранилище) Тогда
Возврат;
КонецЕсли;
ПараметрыПолучения = Новый ПараметрыПолученияФайлов;
ПараметрыПолучения.Интерактивно = Истина;
// Имя, которое будет предложено пользователю для сохранения на клиенте
ЦелевоеИмяФайла = "FOMS_DATA.DBF";
НачатьПолучениеФайлаССервера(Неопределено, АдресВХранилище, ЦелевоеИмяФайла, ПараметрыПолучения);
КонецПроцедуры
Часто сторонние ведомства и банковские программы требуют строго определенный формат имени выгрузки, например, REESTR_FOMS_2024.DBF, который превышает ограничение 8.3. В таком случае применяем следующий прием:
temp.dbf).ЗакрытьФайл(), чтобы снять блокировку операционной системы.ПереместитьФайл(ВременныйПуть, ФинальныйПутьСДлиннымИменем) либо указываем требуемое длинное имя в третьем параметре метода НачатьПолучениеФайлаССервера. Сама операционная система Windows поддерживает длинные имена файлов для формата DBF, ограничение накладывает только внутренний метод создания объекта XBase.Следуя этой схеме, мы изолируем серверные операции от клиентской файловой системы, исключаем проблемы с правами служб и корректно обходим внутренние ограничения механизма XBase.