В практике разработки на платформе 1С:Предприятие 8 часто возникает классическая задача: пользователь выбирает файл на своем локальном компьютере, а обработка этого файла должна происходить на сервере. Новичков часто сбивает с толку тот факт, что сервер «не видит» файловую систему пользователя напрямую. В этой статье мы подробно разберем, как правильно организовать передачу данных между клиентом и сервером и какие инструменты для этого предоставляет современная платформа.
Рассмотрим ситуацию: вы получили путь к файлу на клиенте, например, "C:\Users\Admin\Desktop\data.xlsx". Если вы передадите эту строку в серверную процедуру и попытаетесь открыть файл, система выдаст ошибку «Файл не найден». Это происходит потому, что сервер ищет этот путь на своем локальном диске или в своей сетевой среде, где такого файла не существует. Чтобы решить эту задачу, нам необходимо физически переместить данные файла во Временное хранилище.
Проанализируем самый современный и правильный подход. Мы не передаем «путь», мы передаем «содержимое». Разберем этот процесс по шагам:
Посмотрим на пример кода, реализующий эту схему:
&НаКлиенте
Процедура ВыбратьИЗагрузитьФайл(Команда)
// Описываем параметры выбора файла
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Файлы Excel (*.xlsx)|*.xlsx";
Если Диалог.Выбрать() Тогда
ВыбранныйФайл = Диалог.ПолноеИмяФайла;
// Помещаем файл во временное хранилище
АдресХранилища = "";
Результат = ПоместитьФайл(АдресХранилища, ВыбранныйФайл, , Ложь);
Если Результат Тогда
// Передаем управление серверу, отправляя только адрес
ОбработатьФайлНаСервере(АдресХранилища);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ОбработатьФайлНаСервере(АдресХранилища)
// Извлекаем двоичные данные из хранилища
ДанныеФайла = ПолучитьИзВременногоХранилища(АдресХранилища);
// Создаем временное имя файла на стороне сервера
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ДанныеФайла.Записать(ИмяВременногоФайла);
// Теперь сервер может работать с локальной копией файла
// [Здесь логика обработки, например, чтение через COM или ТабДок]
// После обработки не забываем удалить временный файл
УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры
Если задача заключается в чтении данных из Excel, часто используется COMОбъект. Выясним причину популярности этого метода: он позволяет гибко управлять листами, форматированием и формулами. Однако помните, что для его работы на сервере (или клиенте) должен быть установлен Microsoft Office.
Разберем пример кода, который открывает книгу и ищет последнюю заполненную строку. Это критически важный момент, так как стандартные методы не всегда корректно определяют конец данных.
&НаКлиенте
Процедура ЧтениеExcelЧерезCOM(ПутьКФайлу)
Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.Visible = Ложь;
Excel.DisplayAlerts = Ложь;
Книга = Excel.Workbooks.Open(ПутьКФайлу);
Лист = Книга.Sheets(1);
// Использование SpecialCells(11) позволяет найти последнюю ячейку
// Это аналог нажатия Ctrl+End в Excel
ПоследняяСтрока = Лист.Cells(1, 1).SpecialCells(11).Row;
Для НомерСтроки = 1 По ПоследняяСтрока Цикл
Значение = Лист.Cells(НомерСтроки, 1).Value;
Сообщить("Строка " + НомерСтроки + ": " + Значение);
КонецЦикла;
Книга.Close(Ложь);
Excel.Quit();
Исключение
Сообщить("Ошибка при работе с Excel: " + ОписаниеОшибки());
Если Excel <> Неопределено Тогда
Excel.Quit();
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Проанализируем ситуацию, упомянутую на форуме: какой метод лучше для поиска последней строки? Существует несколько подходов:
SpecialCells, может включать пустые ячейки с форматированием.Лист.Cells.Find("*", , , , 1, 2).Row. Этот метод ищет реальное содержимое в ячейках.Рассмотрим более производительный и кроссплатформенный вариант. Начиная с версии 8.3, 1С умеет читать файлы .xlsx напрямую через ТабличныйДокумент. Это работает значительно быстрее, чем COM, и не требует установленного Microsoft Office (что крайне важно для серверов на Linux).
Выясним, как это реализовать на сервере:
&НаСервере
Процедура ПрочитатьExcelНативно(АдресХранилища)
ТабДок = Новый ТабличныйДокумент;
Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
// Чтение напрямую из потока (двоичных данных)
ЧтениеДанных = Новый ЧтениеДанных(Данные);
ТабДок.Прочитать(ЧтениеДанных, СпособЧтенияЗначенийТабличногоДокумента.Значение);
КоличествоСтрок = ТабДок.ВысотаТаблицы;
КоличествоКолонок = ТабДок.ШиринаТаблицы;
Для Стр = 1 По КоличествоСтрок Цикл
Для Кол = 1 По КоличествоКолонок Цикл
ТекстЯчейки = ТабДок.Область(Стр, Кол).Текст;
// Обработка данных...
КонецЦикла;
КонецЦикла;
КонецПроцедуры
При реализации загрузки файлов следует учитывать несколько важных моментов:
USR1CV8), есть права на чтение этой сетевой папки.НачатьПомещениеФайлаНаСервер.АдресХранилища в фоновое задание, чтобы пользователь мог продолжать работу, пока сервер обрабатывает данные.Таким образом, мы выяснили, что наиболее универсальным и стабильным способом является передача данных через Временное хранилище с последующей обработкой на сервере либо встроенными средствами 1С (через ТабличныйДокумент), либо через COMОбъект, если требуется специфический функционал Excel.