При разработке механизмов выгрузки данных из 1С в сторонние форматы (например, в Excel) программисты часто сталкиваются с ситуацией, когда файл создается успешно, но операционная система определяет его тип как просто «Файл» без расширения. В итоге пользователю приходится вручную дописывать расширение или выбирать программу для открытия. Разберем, почему так происходит и как сделать процесс сохранения корректным и удобным.
Рассмотрим стандартную ситуацию. Программист использует объект ДиалогВыбораФайла для получения пути сохранения и затем вызывает метод Записать() у табличного документа. Ошибка часто кроется в непонимании того, как взаимодействуют путь к файлу и параметры сохранения. Проанализируем типичный фрагмент кода:
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
Если Диалог.Выбрать() Тогда
ИмяФайла = Диалог.ПолноеИмяФайла;
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.xlsx);
КонецЕсли;
В данном примере во втором параметре метода Записать() мы явно указываем ТипФайлаТабличногоДокумента.xlsx. Однако этот параметр влияет только на внутреннюю структуру файла (форматирование данных), но он никогда не меняет строку пути, хранящуюся в переменной ИмяФайла. Если в диалоговом окне пользователь просто ввел «Отчет» и не выбрал тип файла, в переменную попадет строка без расширения. Система создаст файл с именем «Отчет», который по факту является Excel-файлом, но Windows не узнает его «в лицо».
Самый простой и эффективный способ гарантировать наличие расширения — использовать свойство Расширение объекта ДиалогВыбораФайла. Это свойство работает как «страховка»: если пользователь забудет поставить точку и написать расширение вручную, платформа сделает это автоматически.
Выясним, как это работает на практике. Достаточно добавить одну строку перед вызовом диалога:
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
Диалог.Расширение = "xlsx"; // Указываем расширение по умолчанию
Если Диалог.Выбрать() Тогда
// Теперь, если пользователь ввел "МойФайл",
// ПолноеИмяФайла вернет "МойФайл.xlsx"
ИмяФайла = Диалог.ПолноеИмяФайла;
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.xlsx);
КонецЕсли;
Важный нюанс: свойство Расширение задается без точки. Оно срабатывает в момент нажатия кнопки «Сохранить» в диалоговом окне.
Для того чтобы пользователь видел в выпадающем списке диалога доступные форматы (например, «Лист Excel (*.xlsx)»), необходимо настроить свойство Фильтр. Это не только улучшает интерфейс, но и помогает системе сопоставить выбранный пользователем тип с расширением файла.
Проанализируем синтаксис строки фильтра. Она состоит из описания и маски, разделенных вертикальной чертой |:
Диалог.Фильтр = "Таблицы Excel (*.xlsx)|*.xlsx|Все файлы (*.*)|*.*";
Рассмотрим структуру этой строки подробнее:
Посмотрим на полный пример кода с использованием и фильтра, и индекса фильтра:
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
Диалог.Заголовок = "Выберите место для сохранения отчета";
Диалог.Фильтр = "Excel 2007+ (*.xlsx)|*.xlsx|Excel 97-2003 (*.xls)|*.xls";
Диалог.ИндексФильтра = 0; // По умолчанию выбираем первый вариант (xlsx)
Диалог.Расширение = "xlsx";
Если Диалог.Выбрать() Тогда
// Обработка сохранения...
КонецЕсли;
Иногда пользователи умудряются обойти настройки диалога или вводят имя файла программно из других источников. В таких случаях надежнее всего проверить расширение непосредственно перед записью, используя объект Файл. Разберем этот алгоритм:
// Предположим, путь получен из диалога или настроек
ВыбранныйПуть = Диалог.ПолноеИмяФайла;
// Создаем объект для анализа пути
ПроверкаФайла = Новый Файл(ВыбранныйПуть);
// Проверяем, есть ли расширение
Если ПустаяСтрока(ПроверкаФайла.Расширение) Тогда
// Если расширения нет, добавляем его принудительно
ВыбранныйПуть = ВыбранныйПуть + ".xlsx";
КонецЕсли;
ТабДок.Записать(ВыбранныйПуть, ТипФайлаТабличногоДокумента.xlsx);
Этот метод гарантирует, что файл всегда будет иметь правильный суффикс, независимо от того, как отработал диалог выбора.
Важно помнить, что в современной платформе 1С:Предприятие (начиная с версии 8.3.15) использование метода Выбрать() в управляемых формах считается устаревшим (Synchronous Extension). В веб-клиенте такой код работать не будет. Правильнее использовать асинхронный метод Показать().
Проанализируем, как изменится наш код:
&НаКлиенте
Процедура СохранитьФайл(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
Диалог.Фильтр = "Excel (*.xlsx)|*.xlsx";
Диалог.Расширение = "xlsx";
Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект);
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы <> Неопределено Тогда
ПутьКФайлу = ВыбранныеФайлы[0];
// Здесь вызываем процедуру записи табличного документа
ЗаписатьДокументНаДиск(ПутьКФайлу);
КонецЕсли;
КонецПроцедуры
Использование асинхронности — это лучшая практика для кроссплатформенной разработки, обеспечивающая стабильную работу кода в тонком клиенте, браузере и мобильном приложении.
Если ваша база работает через браузер, работа с файлами усложняется тем, что прямой доступ к файловой системе клиента ограничен. В этом случае схема меняется:
ПолучитьФайл(), который инициирует скачивание через браузер.При вызове ПолучитьФайл() имя с расширением также нужно задавать явно, иначе браузер сохранит его как «file» без типа. Проанализируем пример получения файла:
// АдресХранилища — это ссылка на сформированный Excel в памяти сервера
ИмяФайлаДляСкачивания = "Отчет_Продаж.xlsx";
ПолучитьФайл(АдресХранилища, ИмяФайлаДляСкачивания, Истина);
Для корректного создания файла с расширением в 1С необходимо соблюдать следующие правила:
Диалог.Расширение, чтобы платформа автоматически дописывала его к пути.Диалог.Фильтр для удобства пользователя и корректной фильтрации в окне проводника.Записать() отвечает за формат данных, но не за имя файла в операционной системе.Показать() для обеспечения совместимости с веб-клиентом.Соблюдение этих простых рекомендаций позволит избежать путаницы с «безымянными» файлами и сделает вашу разработку профессиональной и удобной для конечного пользователя.