Разработка для мобильной платформы 1С:Предприятие имеет множество нюансов, связанных с аппаратными ограничениями мобильных устройств и усеченным функционалом самой платформы. Одна из распространенных проблем, с которой сталкиваются разработчики при переносе десктопного функционала на мобильные устройства, — это ошибка «Поле объекта не обнаружено» при попытке сохранить отчет или печатную форму в привычном формате MS Excel (XLS или XLSX).
В рамках этой статьи мы подробно разберем, почему возникает эта ошибка, проанализируем ограничения мобильной платформы 1С и изучим четыре практических сценария решения этой проблемы, начиная от простых альтернативных форматов и заканчивая интеграцией с сервером и генерацией файлов «на лету».
Для начала проанализируем, почему мобильное приложение выдает ошибку «Поле объекта не обнаружено» при попытке выполнить следующую строку кода:
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLS97);
Причина кроется в системном перечислении ТипФайлаТабличногоДокумента. В «настольной» версии платформы 1С (для тонкого, толстого и веб-клиента под Windows/Linux) это перечисление содержит широкий спектр поддерживаемых форматов: XLS, XLS97, XLSX, DOCX, ODS, HTML, PDF, MXL и другие. Однако на мобильной платформе состав этого перечисления сильно ограничен из-за отсутствия встроенных библиотек конвертации в проприетарные форматы Microsoft.
Согласно официальной документации 1С, на мобильной платформе метод Записать() объекта ТабличныйДокумент поддерживает сохранение только в двух форматах:
ТипФайлаТабличногоДокумента.MXL).ТипФайлаТабличногоДокумента.PDF).Поскольку значений XLS97, XLS или XLSX в мобильной версии перечисления просто не существует, платформа пытается обратиться к несуществующему свойству объекта и возвращает ошибку «Поле объекта не обнаружено (XLS97)» (или аналогичную для XLSX).
Ниже мы подробно рассмотрим альтернативные варианты решения этой задачи, которые позволят вашим пользователям работать с данными на мобильных устройствах.
Если конечной целью мобильного пользователя является исключительно просмотр сформированного отчета или отправка его клиенту (например, по электронной почте или через мессенджер) без необходимости последующего редактирования ячеек, то лучшим решением будет использование формата PDF.
Этот формат гарантирует сохранение всего исходного форматирования, шрифтов, цветов и структуры табличного документа. Рассмотрим, как изменить процедуру сохранения файла на мобильном клиенте:
&НаКлиенте
Процедура СохранитьВФайлPDF(ТабДок)
Каталог = КаталогВременныхФайлов();
Попытка
УдалитьФайлы(Каталог, "tmp*.pdf");
Исключение
// Игнорируем ошибку, если файлы заблокированы или отсутствуют
КонецПопытки;
Попытка
СоздатьКаталог(Каталог);
Имя = "Отчет_" + Формат(ТекущаяДата(), "ДФ=yyyy-MM-dd-чч-мм-сс") + ".pdf";
ИмяФайла = Каталог + Имя;
// Используем поддерживаемый на мобильной платформе формат PDF
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.PDF);
// Запускаем просмотрщик PDF, установленный на мобильном устройстве
ЗапуститьПриложение(ИмяФайла);
Исключение
Сообщить("Ошибка при сохранении PDF: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
При вызове метода ЗапуститьПриложение() операционная система мобильного устройства (Android или iOS) автоматически предложит открыть созданный PDF-файл в любом установленном приложении-просмотрщике.
Если вашему пользователю критически важно получить именно редактируемый файл Excel (XLSX) на своем мобильном устройстве, и при этом мобильное приложение работает в режиме онлайн-взаимодействия с центральной базой 1С (через HTTP-сервисы или Web-сервисы), то задачу формирования файла целесообразно перенести на сторону полноценного сервера.
Рассмотрим по шагам, как реализовать этот алгоритм:
ТабличныйДокумент и сохраняет его во временный файл в формате XLSX.ДвоичныеДанные и передает его обратно мобильному приложению в ответе на запрос..xlsx на мобильном устройстве и запускает внешнее приложение для его открытия.Давайте посмотрим на пример реализации серверного метода (например, в модуле HTTP-сервиса или общего модуля с флагом "Вызов сервера"):
&НаСервере
Функция СформироватьExcelНаСервере(ТекстЗапроса, СтруктураПараметров, СтруктураОтборов) Экспорт
// 1. Формируем табличный документ стандартными средствами сервера
ТабДок = СформироватьТабличныйДокумент(ТекстЗапроса, СтруктураПараметров, СтруктураОтборов);
// 2. Записываем во временный файл в формате XLSX
ИмяФайлаСервер = ПолучитьИмяВременногоФайла("xlsx");
ТабДок.Записать(ИмяФайлаСервер, ТипФайлаТабличногоДокумента.XLSX);
// 3. Считываем данные в двоичный формат и удаляем временный файл
ДанныеФайла = Новый ДвоичныеДанные(ИмяФайлаСервер);
Попытка
УдалитьФайлы(ИмяФайлаСервер);
Исключение
КонецПопытки;
Возврат ДанныеФайла;
КонецФункции
Теперь рассмотрим, как мобильный клиент принимает эти данные и сохраняет их в локальную файловую систему смартфона или планшета:
&НаКлиенте
Процедура ПолучитьОтчетВExcel()
// Вызываем серверную функцию для получения двоичных данных файла
ДанныеФайла = СформироватьExcelНаСервере(ПараметрыЗапроса);
Если ДанныеФайла = Неопределено Тогда
ВызватьИсключение "Не удалось сформировать файл на сервере.";
КонецЕсли;
// Определяем путь на мобильном устройстве
ПутьНаУстройстве = КаталогВременныхФайлов() + "Отчет.xlsx";
// Записываем файл на диск мобильного устройства
ДанныеФайла.Записать(ПутьНаУстройстве);
// Открываем файл в мобильном Excel (если он установлен на устройстве)
ЗапуститьПриложение(ПутьНаУстройстве);
КонецПроцедуры
Если ваше мобильное приложение работает полностью автономно (офлайн) и связи с центральным сервером нет, получить редактируемый табличный документ Excel стандартным методом Записать() не получится. В этом случае отличным выходом будет выгрузка данных в текстовый формат CSV (Comma-Separated Values), который без проблем открывается мобильным Microsoft Excel или Google Таблицами.
Для реализации этого метода нам необходимо выгрузить данные динамического списка в ТаблицуЗначений на мобильном сервере, обойти ее в цикле и записать данные в текстовый файл с разделителями.
Выясним важную деталь: для корректного отображения кириллицы в мобильном Excel текстовый файл CSV необходимо сохранять строго в кодировке UTF-8 с маркером BOM (Byte Order Mark). Если этого не сделать, вместо русских букв пользователь увидит нечитаемые символы.
Разберем по шагам программный код выгрузки данных СКД в таблицу значений и последующего сохранения в CSV:
&НаСервере
Функция ПолучитьТаблицуДанных(ТекстЗапроса, ОтборСписок, ПараметрыСписок)
// 1. Инициализируем Схему компоновки данных программно
СКД = Новый СхемаКомпоновкиДанных;
ИсточникДанных = СКД.ИсточникиДанных.Добавить;
ИсточникДанных.Имя = "ИсточникДанных";
ИсточникДанных.ТипИсточникаДанных = "Local";
НаборДанных = СКД.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанных.Имя = "НаборДанных1";
НаборДанных.Запрос = ТекстЗапроса;
НаборДанных.ИсточникДанных = "ИсточникДанных";
// Настраиваем вывод всех полей
Настройки = СКД.НастройкиПоУмолчанию;
Группировка = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
Группировка.Использование = Истина;
АвтоПоле = Группировка.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
АвтоПоле.Использование = Истина;
// Выполняем компоновку макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СКД, Настройки,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
// Инициализируем процессор компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// Выводим результат в Таблицу Значений (используем совет из Сообщения 18)
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ТаблицаРезультата = ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Возврат ТаблицаРезультата;
КонецФункции
&НаКлиенте
Процедура СохранитьВCSV(ТекстЗапроса, ОтборСписок, ПараметрыСписок)
// Получаем таблицу значений с данными
ТаблицаДанных = ПолучитьТаблицуДанных(ТекстЗапроса, ОтборСписок, ПараметрыСписок);
Каталог = КаталогВременныхФайлов();
ИмяФайла = Каталог + "Выгрузка_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".csv";
// Инициализируем объект ЗаписьТекста с явным указанием UTF-8 и флага записи BOM (Истина)
ЗаписьCSV = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8,,, Истина);
Разделитель = ";"; // Стандартный разделитель для русскоязычной локали Excel
// 2. Записываем заголовки колонок
СтрокаЗаголовков = "";
Для каждого Колонка Из ТаблицаДанных.Колонки Цикл
СтрокаЗаголовков = СтрокаЗаголовков + Колонка.Имя + Разделитель;
КонецЦикла;
ЗаписьCSV.ЗаписатьСтроку(СтрокаЗаголовков);
// 3. Записываем строки с данными
Для каждого СтрокаДанных Из ТаблицаДанных Цикл
ТекущаяСтрока = "";
Для каждого Колонка Из ТаблицаДанных.Колонки Цикл
ЗначениеПоля = СтрокаДанных[Колонка.Имя];
// Экранируем спецсимволы и преобразуем значение в строку
ТекстЗначения = Строка(ЗначениеПоля);
ТекстЗначения = СтрЗаменить(ТекстЗначения, """", """"""); // дублируем кавычки
Если СтрНайти(ТекстЗначения, Разделитель) > 0 Или СтрНайти(ТекстЗначения, Символы.ПС) > 0 Тогда
ТекстЗначения = """" + ТекстЗначения + """";
КонецЕсли;
ТекущаяСтрока = ТекущаяСтрока + ТекстЗначения + Разделитель;
КонецЦикла;
ЗаписьCSV.ЗаписатьСтроку(ТекущаяСтрока);
КонецЦикла;
ЗаписьCSV.Закрыть();
// Открываем готовый CSV файл на мобильном устройстве
ЗапуститьПриложение(ИмяФайла);
КонецПроцедуры
Этот способ полностью автономен, не требует соединения с интернетом и гарантирует, что пользователь сможет открыть структуру таблицы на любом современном смартфоне.
Для разработчиков, которым требуется создать полноценный файл формата .xlsx со сложной структурой, шрифтами и формулами в режиме офлайн прямо на мобильном устройстве, существует продвинутый метод. Как известно, современные файлы Excel с расширением .xlsx представляют собой обычные ZIP-архивы, содержащие набор файлов XML с разметкой данных.
Посмотрим, как выглядит концептуальная схема этого решения:
template.xlsx в конфигурацию в качестве двоичного макета.ЧтениеZipФайла.ЗаписьXML перезаписываем файл xl/worksheets/sheet1.xml, в который помещаем строки и ячейки с нашими данными.ЗаписьZipФайла и меняем расширение результирующего файла на .xlsx.Реализация этого метода требует написания сложного парсера XML, однако она полностью снимает зависимость от сервера и внешних библиотек конвертации, позволяя генерировать полноценные файлы Excel прямо на мобильной платформе 1С.
Подводя итог анализу проблемы, систематизируем рассмотренные решения, чтобы вы могли выбрать наиболее подходящий вариант для своего проекта:
Таким образом, обойти ограничение мобильной платформы 1С на запись файлов Excel не просто возможно, а существует множество вариантов реализации этой задачи под любые архитектурные требования вашего приложения.