Как загрузить заказы из Excel в 1С, если файл находится на клиентском компьютере, а 1С работает на сервере?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При разработке расширений или обработок для 1С, часто возникает задача загрузки данных из внешних файлов, таких как Excel. Однако, в клиент-серверной архитектуре 1С мы можем столкнуться с распространенной проблемой: серверный процесс 1С не имеет прямого доступа к файлам, расположенным на локальном диске клиентского компьютера. Это приводит к ошибке "Каталог не обнаружен", когда мы пытаемся прочитать файл по пути, выбранному на клиенте, но обработка файла происходит на сервере. Давайте подробно разберем, почему это происходит, и какие существуют эффективные способы решения этой задачи.

Понимание архитектуры клиент-серверного взаимодействия в 1С

Прежде чем перейти к решениям, давайте проанализируем корневую причину возникшей проблемы. Система 1С:Предприятие в клиент-серверном режиме состоит как минимум из трех частей:

  1. Клиентское приложение (толстый, тонкий клиент или веб-клиент): Это приложение, которое запущено на компьютере пользователя. Оно отвечает за взаимодействие с пользователем, отображение форм, выполнение клиентского кода.
  2. Сервер 1С:Предприятия (или кластер серверов): Это серверный процесс, который непосредственно взаимодействует с базой данных, выполняет основные бизнес-логики, проводит документы, формирует отчеты, а также исполняет серверный код.
  3. Сервер базы данных: Хранит данные информационной базы.

Когда мы используем функции, такие как ДиалогВыбораФайла, для выбора файла, это действие выполняется на клиентском компьютере, и возвращается путь к файлу на этом же клиентском компьютере. Однако, когда мы вызываем серверную процедуру (например, помеченную директивой &НаСервере или &НаСервереБезКонтекста) и передаем ей этот локальный путь, серверный процесс пытается найти файл по этому пути на своем диске, а не на диске клиента. Поскольку файл там отсутствует, мы получаем ошибку "Каталог не обнаружен".

Таким образом, наша задача заключается в том, чтобы безопасно и эффективно переместить или передать содержимое файла с клиентского компьютера на сервер для последующей обработки. Рассмотрим несколько способов решения этой задачи.

Решение 1: Использование временного хранилища (рекомендуемый подход)

Этот метод является наиболее безопасным, гибким и рекомендованным для передачи двоичных данных (в том числе файлов) между клиентом и сервером в системе 1С. Временное хранилище позволяет сохранить данные на сервере (или в кластере серверов) по уникальному адресу, который затем можно использовать для доступа к этим данным из серверного кода.

Шаг 1: Выбор файла на клиенте и помещение во временное хранилище

На первом этапе мы должны предоставить пользователю возможность выбрать файл на его локальном компьютере, а затем поместить содержимое этого файла во временное хранилище 1С. Это делается полностью на клиентской стороне.

  1. Мы используем объект ДиалогВыбораФайла, чтобы пользователь выбрал необходимый Excel-файл.
  2. Затем, вместо того чтобы передавать путь к файлу на сервер, мы используем функцию НачатьПомещениеФайла. Эта функция асинхронно помещает выбранный файл во временное хранилище и по завершении вызывает указанную процедуру-обработчик на клиенте, передавая ей адрес файла во временном хранилище. Также можно использовать синхронную функцию ПоместитьВоВременноеХранилище, если это допустимо для пользовательского опыта.

Давайте посмотрим на пример клиентского кода:


&НаКлиенте
ПеременнаяФормы_ИмяФайла = ""; // Переменная для хранения имени выбранного файла
ПеременнаяФормы_АдресХранения = ""; // Переменная для хранения адреса файла во временном хранилище

Процедура ИмяФайлаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку выбора
    
    // Создаем описание оповещения для процедуры, которая будет вызвана после помещения файла
    Описание = Новый ОписаниеОповещения("ЗакончитьВыборФайла", ЭтотОбъект);
    
    // Начинаем помещение файла во временное хранилище.
    // Третий параметр - "ИмяФайла", если не указан, берется из диалога
    // Четвертый параметр - "ПомещатьВоВременноеХранилище" (Истина - по умолчанию)
    // Пятый параметр - "УникальныйИдентификатор" (можно оставить пустым или указать)
    НачатьПомещениеФайла(Описание,,,Истина, УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ЗакончитьВыборФайла(Результат, Адрес, Имя, ДопПараметры) Экспорт
    // Эта процедура будет вызвана после того, как файл будет помещен во временное хранилище.
    // Результат - Истина, если файл успешно выбран и помещен.
    // Адрес - адрес файла во временном хранилище.
    // Имя - исходное имя файла.
    
    Если Результат Тогда
        ПеременнаяФормы_ИмяФайла = Имя; // Сохраняем имя файла для отображения пользователю
        ПеременнаяФормы_АдресХранения = Адрес; // Сохраняем адрес хранилища для передачи на сервер
        Сообщить("Файл '" + Имя + "' успешно помещен во временное хранилище. Адрес: " + Адрес);
    Иначе
        Предупреждение("Файл не выбран или произошла ошибка при помещении во временное хранилище.");
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьЗагрузку(Команда)
    Если ПеременнаяФормы_АдресХранения = "" Тогда
        Предупреждение("Файл для загрузки не выбран!");
        Возврат;
    КонецЕсли;
    
    // Спрашиваем пользователя, действительно ли он хочет выполнить загрузку
    Оповещение = Новый ОписаниеОповещения("НачатьВыполнениеЗагрузки", ЭтаФорма);
    ПоказатьВопрос(Оповещение, "Выполнить загрузку данных из файла """ + ПеременнаяФормы_ИмяФайла + """ ?", РежимДиалогаВопрос.ДаНет, , , "Начало загрузки");
КонецПроцедуры

&НаКлиенте
Процедура НачатьВыполнениеЗагрузки(Результат, Параметры) Экспорт
    Если НЕ Результат = КодВозвратаДиалога.Да Тогда
        Возврат; // Пользователь отказался от загрузки
    КонецЕсли;
    
    // Вызываем серверную функцию для выполнения загрузки, передавая адрес временного хранилища
    РезультатЗагрузки = ВыполнитьЗагрузкуНаСервере(ПеременнаяФормы_АдресХранения);
    
    Если ТипЗнч(РезультатЗагрузки) = Тип("Строка") Тогда
        // Если серверная функция вернула строку, это, вероятно, сообщение об ошибке
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = РезультатЗагрузки;
        Сообщение.Поле = "ИмяФайла"; // Можно привязать сообщение к полю на форме
        Сообщение.Сообщить();
    Иначе
        Сообщить("Загрузка данных успешно завершена!");
    КонецЕсли;
КонецПроцедуры

Шаг 2: Получение файла из временного хранилища на сервере и его обработка

После того как файл помещен во временное хранилище, его адрес передается на сервер. На сервере мы можем получить двоичные данные файла и работать с ними.

  1. На серверной стороне мы получаем адрес временного хранилища. Мы должны убедиться, что это действительно адрес временного хранилища, используя функцию ЭтоАдресВременногоХранилища.
  2. С помощью функции ПолучитьИзВременногоХранилища мы извлекаем двоичные данные файла.
  3. Полученные двоичные данные мы можем записать во временный файл на сервере. Для этого сначала получаем уникальное имя для временного файла с помощью ПолучитьИмяВременногоФайла, а затем используем метод Записать() объекта ДвоичныеДанные.
  4. После того как файл записан на сервере, мы можем использовать стандартные объекты 1С, такие как ТабличныйДокумент, для его чтения и обработки.
  5. Крайне важно: После завершения обработки временный файл на сервере следует удалить с помощью функции УдалитьФайлы, чтобы не засорять файловую систему сервера.

Посмотрим на пример серверного кода:


&НаСервереБезКонтекста
Функция ВыполнитьЗагрузкуНаСервере(АдресХранения)
    // Проверяем, является ли переданный адрес адресом временного хранилища
    Если Не ЭтоАдресВременногоХранилища(АдресХранения) Тогда
        Возврат "Ошибка: Передан некорректный адрес временного хранилища.";
    КонецЕсли;
    
    Попытка
        // Получаем двоичные данные файла из временного хранилища
        ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранения);
        
        Если ДвоичныеДанные = Неопределено Тогда
            Возврат "Ошибка: Не удалось получить данные из временного хранилища по адресу: " + АдресХранения;
        КонецЕсли;

        // Генерируем уникальное имя для временного файла на сервере.
        // Предполагаем, что это Excel-файл, поэтому расширение ".xlsx" или ".xls".
        // В данном примере используем ".xls" как общее для Excel.
        ИмяФайлаНаСервере = ПолучитьИмяВременногоФайла(".xlsx"); 
        
        // Записываем двоичные данные во временный файл на сервере
        ДвоичныеДанные.Записать(ИмяФайлаНаСервере);
        
        // Создаем объект ТабличныйДокумент для чтения Excel-файла
        ТабличныйДокумент = Новый ТабличныйДокумент;
        // Читаем данные из файла
        ТабличныйДокумент.Прочитать(ИмяФайлаНаСервере, СпособЧтенияЗначенийТабличногоДокумента.Значение);
        
        // После прочтения файла, он больше не нужен, удаляем его
        УдалитьФайлы(ИмяФайлаНаСервере);
        
        // Проверяем, удалось ли прочитать области листа
        Если ТабличныйДокумент.Области.Количество = 0 Тогда
            Возврат "Ошибка чтения файла: Файл Excel пуст или не содержит данных.";
        КонецЕсли;
        
        // Начинаем обработку данных из ТабличногоДокумента
        // Здесь можно добавить логику парсинга Excel-файла и создания документов в 1С
        // Пример обработки (на основе кода автора):
        x = 2; // Начальная строка для чтения данных (предполагаем, что первая строка - заголовок)
        ТаблицаСтрок = Новый ТаблицаЗначений;
        ТаблицаСтрок.Колонки.Добавить("НоменклатураН");
        ТаблицаСтрок.Колонки.Добавить("Количество");

        Пока ТабличныйДокумент.Область("R" + Строка(x) + "C1").Текст <> "" Цикл // Читаем строки, пока есть данные в первой колонке
            СтрокаИзExcel = Новый Структура;
            Попытка
                Количество = Число(СокрЛП(ТабличныйДокумент.Область("R" + Строка(x) + "C2").Текст));
            Исключение
                Количество = 0;
            КонецПопытки;
            
            Если Количество > 0 Тогда
                ПерваяКолонка = СокрЛП(ТабличныйДокумент.Область("R" + Строка(x) + "C1").Текст);
                НоваяСтрокаТаблицы = ТаблицаСтрок.Добавить();
                НоваяСтрокаТаблицы.НоменклатураН = ПерваяКолонка;
                НоваяСтрокаТаблицы.Количество = Количество;
            КонецЕсли;
            x = x + 1;
        КонецЦикла;
        
        // Теперь у нас есть ТаблицаСтрок с данными, которые можно использовать для создания документов.
        // Пример: создание ЗаказовКлиента
        // ... Логика создания документов "ЗаказКлиента" на основе ТаблицаСтрок ...
        // Например:
        Для Каждого СтрокаТЗ Из ТаблицаСтрок Цикл
            // Создаем новый документ "ЗаказКлиента"
            НовыйЗаказ = Документы.ЗаказКлиента.СоздатьДокумент();
            НовыйЗаказ.Дата = ТекущаяДата();
            // ... Заполняем остальные реквизиты документа ...
            НовыйЗаказ.Организация = Справочники.Организации.НайтиПоНаименованию("НашаОрганизация"); // Пример
            НовыйЗаказ.Партнер = Справочники.Партнеры.НайтиПоНаименованию("КлиентИзExcel"); // Пример

            // Добавляем строку в табличную часть "Товары"
            НоваяСтрокаТовары = НовыйЗаказ.Товары.Добавить();
            НоваяСтрокаТовары.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию(СтрокаТЗ.НоменклатураН);
            НоваяСтрокаТовары.Количество = СтрокаТЗ.Количество;
            НоваяСтрокаТовары.Цена = 100; // Пример
            НоваяСтроваТовары.Сумма = НоваяСтроваТовары.Количество * НоваяСтроваТовары.Цена;
            
            // Записываем документ
            НовыйЗаказ.Записать(РежимЗаписиДокумента.Проведение);
        КонецЦикла;

        Возврат "Данные успешно загружены и документы созданы!";
        
    Исключение
        // В случае ошибки, удаляем временный файл, если он был создан
        Если ЗначениеЗаполнено(ИмяФайлаНаСервере) И ФайлСуществует(ИмяФайлаНаСервере) Тогда
            УдалитьФайлы(ИмяФайлаНаСервере);
        КонецЕсли;
        Возврат "Произошла ошибка при загрузке или обработке файла: " + ОписаниеОшибки();
    КонецПопытки;
КонецФункции

Преимущества временного хранилища:

  1. Безопасность: Данные хранятся на сервере 1С во временном хранилище, доступ к которому строго контролируется системой. Это гораздо безопаснее, чем использовать общие сетевые папки.
  2. Надежность: Не требует дополнительных настроек прав доступа или сетевых ресурсов. Работает "из коробки" в любой конфигурации 1С.
  3. Масштабируемость: Подходит для работы в кластере серверов 1С.
  4. Чистота: После использования данные из временного хранилища и временные файлы на сервере могут быть автоматически удалены или удалены программно.

Решение 2: Чтение данных на клиенте и передача их на сервер

Этот подход предполагает, что весь Excel-файл будет прочитан и разобран на клиентской стороне, а затем на сервер будет передан не сам файл, а уже готовая структура данных (например, таблица значений или массив структур). Серверная часть будет работать уже с этими структурированными данными, а не с файлом.

Принцип работы:

  1. На клиенте пользователь выбирает файл Excel с помощью ДиалогВыбораФайла.
  2. Клиентский код непосредственно читает Excel-файл в объект ТабличныйДокумент (или использует COM-объект Excel, если это допустимо).
  3. Данные из ТабличныйДокумент парсятся и преобразуются в удобную для передачи структуру, например, ТаблицаЗначений или Массив из Структур.
  4. Эта структурированная таблица значений или массив передается в серверную процедуру в качестве параметра.
  5. Серверная процедура получает уже готовые данные и занимается только их записью в информационную базу.

Преимущества:

Недостатки:

Давайте рассмотрим пример реализации:


&НаКлиенте
Процедура MAD_ВыбратьПосле(Команда)
    Режим = РежимДиалогаВыбораФайла.Открытие;
    ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
    ДиалогОткрытияФайла.ПолноеИмяФайла = "";
    // Можно настроить фильтр для файлов Excel
    // ДиалогОткрытияФайла.Фильтр = НСтр("ru = 'Ексель'; en = 'Excel'") + "(*.xlsx)|*.xlsx" + "(*.xls)|*.xls";
    ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
    ДиалогОткрытияФайла.Заголовок = "Выберите файл Excel";
    
    Если ДиалогОткрытияФайла.Выбрать() Тогда
        ИмяВыбранногоФайла = ДиалогОткрытияФайла.ПолноеИмяФайла;
        Сообщить("Выбран файл: " + ИмяВыбранногоФайла);
        
        Попытка
            // Читаем Excel-файл в ТабличныйДокумент на клиенте
            ТабДок = Новый ТабличныйДокумент;
            ТабДок.Прочитать(ИмяВыбранногоФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
            
            // Создаем ТаблицуЗначений для передачи на сервер
            ТаблицаДанныхДляСервера = Новый ТаблицаЗначений;
            ТаблицаДанныхДляСервера.Колонки.Добавить("НоменклатураН", Новый ОписаниеТипов("Строка"));
            ТаблицаДанныхДляСервера.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
            
            x = 2; // Начальная строка для чтения данных
            Пока ТабДок.Область("R" + Строка(x) + "C1").Текст <> "" Цикл
                Количество = 0;
                Попытка
                    Количество = Число(СокрЛП(ТабДок.Область("R" + Строка(x) + "C2").Текст));
                Исключение
                    // Ошибка преобразования, количество остается 0
                КонецПопытки;
                
                Если Количество > 0 Тогда
                    НоваяСтрока = ТаблицаДанныхДляСервера.Добавить();
                    НоваяСтрока.НоменклатураН = СокрЛП(ТабДок.Область("R" + Строка(x) + "C1").Текст);
                    НоваяСтрока.Количество = Количество;
                КонецЕсли;
                x = x + 1;
            КонецЦикла;
            
            // Вызываем серверную функцию для обработки ТаблицыЗначений
            РезультатОбработки = ОбработатьДанныеСервере(ТаблицаДанныхДляСервера);
            
            Если ТипЗнч(РезультатОбработки) = Тип("Строка") Тогда
                Сообщить("Ошибка на сервере: " + РезультатОбработки, СтатусСообщения.Внимание);
            Иначе
                Сообщить("Данные успешно обработаны на сервере!");
            КонецЕсли;

        Исключение
            Сообщить("Ошибка при чтении или обработке файла на клиенте: " + ОписаниеОшибки(), СтатусСообщения.Внимание);
        КонецПопытки;
        
    Иначе
        Предупреждение("Файл не выбран!");
    КонецЕсли;
КонецПроцедуры

&НаСервере
Функция ОбработатьДанныеСервере(ТаблицаДанных)
    Попытка
        Если ТаблицаДанных.Количество() = 0 Тогда
            Возврат "Таблица данных пуста, нет ничего для обработки.";
        КонецЕсли;
        
        // Здесь мы получаем ТаблицуЗначений и работаем с ней уже на сервере
        Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
            // ... Логика создания документов "ЗаказКлиента" на основе СтрокаДанных ...
            НовыйЗаказ = Документы.ЗаказКлиента.СоздатьДокумент();
            НовыйЗаказ.Дата = ТекущаяДата();
            // ... Заполняем реквизиты ...
            НовыйЗаказ.Организация = Справочники.Организации.НайтиПоНаименованию("НашаОрганизация"); // Пример
            НовыйЗаказ.Партнер = Справочники.Партнеры.НайтиПоНаименованию("КлиентИзExcel"); // Пример

            НоваяСтрокаТовары = НовыйЗаказ.Товары.Добавить();
            НоваяСтрокаТовары.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию(СтрокаДанных.НоменклатураН);
            НоваяСтрокаТовары.Количество = СтрокаДанных.Количество;
            НоваяСтроваТовары.Цена = 100; // Пример
            НоваяСтроваТовары.Сумма = НоваяСтроваТовары.Количество * НоваяСтроваТовары.Цена;
            
            НовыйЗаказ.Записать(РежимЗаписиДокумента.Проведение);
        КонецЦикла;
        
        Возврат Истина; // Успех
    Исключение
        Возврат "Ошибка при обработке данных на сервере: " + ОписаниеОшибки();
    КонецПопытки;
КонецФункции

Решение 3: Копирование файла в общую (расшаренную) папку на сервере (менее предпочтительный подход)

Этот подход является наиболее прямолинейным, но он имеет существенные недостатки, связанные с безопасностью и администрированием. Суть метода заключается в том, чтобы после выбора файла на клиенте, программно скопировать его в сетевую папку, которая доступна серверу 1С.

Принцип работы:

  1. На клиенте пользователь выбирает файл Excel.
  2. Клиентская процедура копирует этот файл из его локального расположения в заранее настроенную сетевую (расшаренную) папку, доступную серверу 1С.
  3. Серверная процедура затем обращается к файлу по сетевому пути к этой расшаренной папке и обрабатывает его.
  4. После обработки, файл из расшаренной папки желательно удалить.

Важные моменты для реализации:

Давайте посмотрим на пример клиентского кода:


&НаКлиенте
Процедура MAD_ВыбратьПосле(Команда)
    Режим = РежимДиалогаВыбораФайла.Открытие;
    ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
    ДиалогОткрытияФайла.ПолноеИмяФайла = "";
    ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
    ДиалогОткрытияФайла.Заголовок = "Выберите файл";
    
    Если ДиалогОткрытияФайла.Выбрать Тогда
        ИмяФайлаНаКлиенте = ДиалогОткрытияФайла.ПолноеИмяФайла;
        Сообщить("Выбран файл: " + ИмяФайлаНаКлиенте);
        
        // Определяем путь к расшаренной папке на сервере.
        // ЭТОТ ПУТЬ ДОЛЖЕН БЫТЬ ДОСТУПЕН КАК КЛИЕНТУ (ДЛЯ ЗАПИСИ), ТАК И СЕРВЕРУ (ДЛЯ ЧТЕНИЯ И ЗАПИСИ)
        ПутьКРасшареннойПапкеНаСервере = "\\ИмяВашегоСервера\ИмяОбщейПапкиДляЗагрузки\"; // Укажите реальный UNC-путь!
        
        // Получаем только имя файла из полного пути
        ИмяФайлаБезПути = Новый Файл(ИмяФайлаНаКлиенте).Имя;
        
        // Формируем полный путь для нового файла в расшаренной папке
        ПутьНаСервереДляКопирования = ПутьКРасшареннойПапкеНаСервере + ИмяФайлаБезПути;
        
        Попытка
            // Копируем файл с клиента в расшаренную папку на сервере
            КопироватьФайл(ИмяФайлаНаКлиенте, ПутьНаСервереДляКопирования);
            Сообщить("Файл успешно скопирован на сервер в: " + ПутьНаСервереДляКопирования);
            
            // Теперь вызываем серверную процедуру, передавая ей путь к файлу в расшаренной папке
            РезультатЗагрузки = MAD_ВыбратьПослеНаСервере(ПутьНаСервереДляКопирования);
            
            Если ТипЗнч(РезультатЗагрузки) = Тип("Строка") Тогда
                 Сообщить("Ошибка на сервере: " + РезультатЗагрузки, СтатусСообщения.Внимание);
            Иначе
                 Сообщить("Данные успешно загружены и документы созданы!");
            КонецЕсли;

        Исключение
            Сообщить("Ошибка при копировании файла или обработке на сервере: " + ОписаниеОшибки(), СтатусСообщения.Внимание);
        КонецПопытки;
        
    Иначе
        Предупреждение("Файл не выбран!");
    КонецЕсли;
КонецПроцедуры

// Серверная процедура, которая теперь читает файл из расшаренной папки
&НаСервере
Процедура MAD_ВыбратьПослеНаСервере(ИмяФайлаНаСервере)
    ТабДок = Новый ТабличныйДокумент;
    Попытка
        // Сервер теперь видит этот путь, так как он сетевой и доступен
        ТабДок.Прочитать(ИмяФайлаНаСервере, СпособЧтенияЗначенийТабличногоДокумента.Значение);
    Исключение
        Сообщить("Ошибка при вызове метода контекста (Прочитать): " + ОписаниеОшибки(), СтатусСообщения.Внимание);
        Возврат;
    КонецПопытки;

    x = 2; // начальная строка
    ТаблицаДанныхДляСоздания = Новый ТаблицаЗначений;
    ТаблицаДанныхДляСоздания.Колонки.Добавить("НоменклатураН");
    ТаблицаДанныхДляСоздания.Колонки.Добавить("Количество");

    Пока ТабДок.Область("R" + Строка(x) + "C1").Текст <> "" Цикл //будем читать строки пока есть данные в первой колонке
        Количество = 0;
        Попытка
            Количество = Число(СокрЛП(ТабДок.Область("R" + Строка(x) + "C2").Текст));
        Исключение
            Количество = 0;
        КонецПопытки;
        
        Если Количество > 0 Тогда
            НоваяСтрока = ТаблицаДанныхДляСоздания.Добавить();
            НоваяСтрока.НоменклатураН = СокрЛП(ТабДок.Область("R" + Строка(x) + "C1").Текст);
            НоваяСтрока.Количество = Количество;
        КонецЕсли;
        x = x + 1;
    КонецЦикла;

    // ... Логика создания документов "ЗаказКлиента" на основе ТаблицаДанныхДляСоздания ...
    // Например:
    Для Каждого СтрокаТЗ Из ТаблицаДанныхДляСоздания Цикл
        НовыйЗаказ = Документы.ЗаказКлиента.СоздатьДокумент();
        НовыйЗаказ.Дата = ТекущаяДата();
        НовыйЗаказ.Организация = Справочники.Организации.НайтиПоНаименованию("НашаОрганизация"); 
        НовыйЗаказ.Партнер = Справочники.Партнеры.НайтиПоНаименованию("КлиентИзExcel");

        НоваяСтрокаТовары = НовыйЗаказ.Товары.Добавить();
        НоваяСтрокаТовары.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию(СтрокаТЗ.НоменклатураН);
        НоваяСтроваТовары.Количество = СтрокаТЗ.Количество;
        НоваяСтроваТовары.Цена = 100; 
        НоваяСтроваТовары.Сумма = НоваяСтроваТовары.Количество * НоваяСтроваТовары.Цена;
        
        НовыйЗаказ.Записать(РежимЗаписиДокумента.Проведение);
    КонецЦикла;

    // После обработки, можно удалить файл из расшаренной папки
    Попытка
        УдалитьФайлы(ИмяФайлаНаСервере);
        Сообщить("Временный файл '" + ИмяФайлаНаСервере + "' успешно удален с сервера.");
    Исключение
        Сообщить("Предупреждение: Не удалось удалить временный файл '" + ИмяФайлаНаСервере + "'. " + ОписаниеОшибки(), СтатусСообщения.Внимание);
    КонецПопытки;
КонецПроцедуры

Недостатки этого подхода:

Детали реализации и важные нюансы

Независимо от выбранного подхода, при работе с файлами в клиент-серверном режиме 1С, всегда следует учитывать следующие моменты:

  1. Разделение контекстов: Мы должны четко понимать, какой код выполняется на клиенте (директива &НаКлиенте) и какой на сервере (&НаСервере или &НаСервереБезКонтекста). Функции для работы с пользовательским интерфейсом (например, Сообщить, Предупреждение, ПоказатьВопрос), а также с локальными файлами клиента (ДиалогВыбораФайла, Файл) доступны только на клиенте. Функции для работы с базой данных, серверными файлами и временным хранилищем доступны только на сервере.
  2. Обработка ошибок: Всегда используйте блоки Попытка...Исключение...КонецПопытки при работе с файловой системой, сетевыми ресурсами или конвертацией данных. Это позволит корректно обрабатывать ситуации, когда файл не найден, поврежден, имеет некорректный формат или возникли проблемы с правами доступа.
  3. Удаление временных файлов: Если вы создаете временные файлы на сервере (как в случае с временным хранилищем или копированием в расшаренную папку), обязательно удаляйте их после обработки с помощью функции УдалитьФайлы(). Это предотвратит засорение файловой системы сервера и потенциальные проблемы с производительностью.
  4. Оповещения пользователя: Предоставляйте пользователю четкую обратную связь о ходе загрузки, особенно для больших файлов. Используйте Сообщить(), Предупреждение(), ПоказатьВопрос(), а также индикаторы выполнения, если процесс длительный.
  5. Типы файлов Excel: Учитывайте различия между форматами .xls (старый формат Excel) и .xlsx (новый формат Office Open XML). Объект ТабличныйДокумент в 1С обычно хорошо работает с обоими форматами, но при создании временных файлов убедитесь, что расширение соответствует содержимому.

Заключение

Загрузка заказов из Excel с клиентского компьютера в клиент-серверной архитектуре 1С — это стандартная задача, которая требует понимания принципов взаимодействия клиента и сервера. Мы рассмотрели три основных подхода:

  1. Использование временного хранилища: Наиболее безопасный, надежный и рекомендуемый способ, не требующий дополнительных настроек на уровне операционной системы.
  2. Чтение данных на клиенте и передача их на сервер: Подходит, если необходимо обработать файл на клиенте или передать только часть данных, но имеет ограничения для веб-клиента и больших файлов.
  3. Копирование файла в общую папку на сервере: Самый простой с точки зрения идеи, но наименее предпочтительный из-за потенциальных проблем с безопасностью, администрированием и надежностью.

Основываясь на рекомендациях 1С и опыте разработки, мы советуем отдавать предпочтение методу с использованием временного хранилища. Этот подход обеспечивает наилучший баланс между функциональностью, безопасностью и надежностью, что критически важно для промышленных решений.

Выбирая подходящий метод, всегда оценивайте конкретные требования вашего проекта, объем данных, среду выполнения (тонкий/веб-клиент) и существующие политики безопасности вашей организации.

← На главную