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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Мы проанализируем, как можно реализовать функциональность экспорта в Excel, обеспечив при этом гибкость в выборе формата выгрузки — есть автоматическая выгрузка данных на основе СКД. Разберем как классические методы с использованием объекта


ТабличныйДокумент
и технологии COM, так и более современные подходы, адаптированные под архитектуру управляемого приложения и работу с файлами на стороне клиента.

Основные подходы к экспорту в Excel в 1С

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

  1. Использование объекта
    
    ТабличныйДокумент
    
    :
    Этот объект является универсальным инструментом для формирования любых печатных форм и отчетов в 1С. Он позволяет программно создавать сложную структуру с заголовками, подвалами, картинками, объединением ячеек и различными стилями. Полученный
    
    ТабличныйДокумент
    
    затем можно сохранить в различных форматах, включая XLS, XLSX, HTML, PDF.
  2. Взаимодействие с внешними приложениями через COM: Для расширенного контроля над процессом экспорта и использования всех возможностей Excel (например, макросов, сложных формул, специфического форматирования) мы можем напрямую управлять приложением Microsoft Excel через COM-соединение. Этот подход дает максимальную гибкость, но имеет свои особенности при работе в клиент-серверной архитектуре управляемых форм.
  3. Использование функционала управляемых форм для работы с файлами: В управляемых формах прямое COM-соединение с Excel на сервере или клиенте (без специальных настроек) не всегда возможно или желательно. Вместо этого мы используем специальные методы для сохранения и открытия файлов, такие как
    
    НачатьПомещениеФайла
    
    и
    
    НачатьПолучениеФайла
    
    , которые обеспечивают безопасное взаимодействие между клиентом и сервером.

Давайте рассмотрим каждый из этих подходов подробнее, уделяя внимание реализации выбора шаблона.

Решение 1: Выгрузка через ТабличныйДокумент с последующим сохранением в файл Excel и открытие на клиенте

Этот метод является наиболее распространенным и безопасным для управляемых форм. Мы формируем данные в объект


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

Шаг 1: Формирование ТабличногоДокумента

Прежде всего, нам необходимо получить данные (для этого можно использовать отбор СКД по табличной части) и программно "нарисовать" их в


ТабличныйДокумент
. Предположим, у нас есть процедура, которая принимает табличную часть документа и формирует

ТабличныйДокумент
.

Мы создадим функцию на сервере, которая будет отвечать за формирование


ТабличногоДокумента
(подобным образом строится и выгрузка журнала регистрации в Excel с группировкой). Важно учесть, что мы можем иметь несколько таких функций или одну универсальную, которая принимает параметр с идентификатором шаблона выгрузки.


// Пример функции на сервере, формирующей ТабличныйДокумент
&НаСервере
Функция СформироватьТабличныйДокументДляВыгрузки(ТабличнаяЧасть, ИмяШаблона)

    ТабДок = Новый ТабличныйДокумент;
    ТабДок.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ДОКУМЕНТА"; // Можно указать для сохранения настроек
    
    // В зависимости от ИмяШаблона, мы можем изменять структуру вывода
    Если ИмяШаблона = "Шаблон1" Тогда
        // Пример простого вывода заголовка и данных
        ОбластьЗаголовок = ТабДок.Области.Добавить("Заголовок");
        ОбластьЗаголовок.Текст = "Заголовок выгрузки по Шаблону 1";
        ТабДок.Вывести(ОбластьЗаголовок);

        // Добавляем шапку таблицы
        ОбластьШапка = ТабДок.Области.Добавить("ШапкаТаблицы");
        ОбластьШапка.Текст = "Наименование | Количество | Цена | Сумма"; // Пример
        ТабДок.Вывести(ОбластьШапка);

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

    Возврат ТабДок;
КонецФункции

Для более сложных шаблонов, где необходимо использование макетов, мы можем использовать метод


ПолучитьМакет
и выводить области из макета в

ТабличныйДокумент
. Это позволяет дизайнеру работать с макетом визуально (подробнее в материале редактирование печатных форм), а программисту – программно заполнять его данными.


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

Шаг 2: Сохранение ТабличногоДокумента и передача файла клиенту

После того как


ТабличныйДокумент
сформирован на сервере, нам нужно сохранить его во временный файл и передать путь к этому файлу (или сам файл) на клиент для открытия.


// Пример серверной процедуры для сохранения ТабличногоДокумента
// и получения адреса временного хранилища
&НаСервере
Функция СохранитьТабличныйДокументВХранилище(ТабДок)
    Если ТабДок = Неопределено Тогда
        Возврат "";
    КонецЕсли;

    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx"); // Можно выбрать xlsx, xls, pdf
    ТабДок.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.XLSX);

    // Помещаем файл во временное хранилище и возвращаем его адрес
    Возврат ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяВременногоФайла));
КонецФункции

Шаг 3: Действия на клиенте – выбор шаблона и открытие файла

На клиенте мы должны предоставить пользователю механизм для выбора шаблона выгрузки — удобнее через универсальная выгрузка из 1С в Excel. Это может быть реализовано с помощью команды на форме (как в примере Easy Peasy обмена), которая открывает форму выбора или выпадающий список.


// Пример обработчика команды на клиенте
&НаКлиенте
Процедура ВыгрузитьВExcel(Команда)
    // Здесь мы можем предложить пользователю выбрать шаблон
    // Например, через диалог или меню
    СписокШаблонов = Новый СписокЗначений;
    СписокШаблонов.Добавить("Шаблон1", "Стандартная выгрузка");
    СписокШаблонов.Добавить("Шаблон2", "Расширенная выгрузка");
    
    ВыбранныйШаблон = Неопределено;
    Если СписокШаблонов.Количество() > 1 Тогда
        // Если шаблонов несколько, предлагаем выбрать
        ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораШаблона", ЭтотОбъект);
        ПоказатьВыборИзСписка(ОписаниеОповещения, СписокШаблонов, "Выберите шаблон выгрузки:");
    Иначе
        // Если шаблон один, используем его
        ВыбранныйШаблон = СписокШаблонов[0];
        ПослеВыбораШаблона(ВыбранныйШаблон, Неопределено);
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораШаблона(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЭлемент = Неопределено Тогда
        Возврат; // Пользователь отменил выбор
    КонецЕсли;

    // Получаем данные для выгрузки (например, табличную часть документа)
    ТабличнаяЧастьДляВыгрузки = Объект.Товары; // Пример: табличная часть документа "Товары"

    АдресФайла = СохранитьТабличныйДокументНаСервереИПолучитьАдрес(ТабличнаяЧастьДляВыгрузки, ВыбранныйЭлемент.Значение);

    Если ПустаяСтрока(АдресФайла) Тогда
        Сообщить("Не удалось сформировать файл для выгрузки.");
        Возврат;
    КонецЕсли;

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

КонецПроцедуры

// Вспомогательная процедура на клиенте, вызывающая серверные функции
&НаСервереБезКонтекста
Функция СохранитьТабличныйДокументНаСервереИПолучитьАдрес(ТабличнаяЧастьДокумента, ИмяШаблона)
    ТабДок = СформироватьТабличныйДокументДляВыгрузки(ТабличнаяЧастьДокумента, ИмяШаблона);
    Возврат СохранитьТабличныйДокументВХранилище(ТабДок);
КонецФункции

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

&НаКлиенте
Процедура ОткрытьФайлВопросЗавершение(Результат, ИмяФайла) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        ЗапуститьПриложение(ИмяФайла);
    КонецЕсли;
КонецПроцедуры

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

Решение 2: Использование COM-соединения для прямого управления Excel (Сложный сценарий для УФ)

Прямое управление Excel через COM-соединение позволяет нам использовать все возможности Excel: создавать листы, задавать формулы, форматировать ячейки, использовать встроенные функции Excel и даже запускать макросы. Однако в управляемых формах это может быть затруднено:

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

Тем не менее, если мы уверены в условиях работы (например, это всегда будет толстый клиент или тонкий клиент с определенными настройками), мы можем рассмотреть этот подход.

Шаг 1: Формирование ТабличногоДокумента (аналогично предыдущему решению)

Мы по-прежнему формируем данные в


ТабличныйДокумент
, поскольку это удобный и унифицированный способ подготовки данных внутри 1С.

Шаг 2: Передача ТабличногоДокумента на клиент и экспорт через COM

На сервере мы формируем


ТабличныйДокумент
и сохраняем его во временный файл, а затем передаем его двоичные данные или адрес во временном хранилище на клиент. На клиенте мы уже работаем с COM-объектом Excel.


// Серверная функция для формирования ТабличногоДокумента
// (аналогична СформироватьТабличныйДокументДляВыгрузки)

// Клиентская процедура для экспорта через COM
&НаКлиенте
Процедура ВыгрузитьВExcelЧерезCOM(Команда)
    // ... (Выбор шаблона, как в предыдущем решении)
    ВыбранныйШаблон = "Шаблон1"; // Для примера
    
    ТабличнаяЧастьДляВыгрузки = Объект.Товары;
    
    // Получаем двоичные данные ТабличногоДокумента с сервера
    ДвоичныеДанныеТабДок = ПолучитьДвоичныеДанныеТабличногоДокументаНаСервере(ТабличнаяЧастьДляВыгрузки, ВыбранныйШаблон);

    Если ДвоичныеДанныеТабДок = Неопределено Тогда
        Сообщить("Не удалось сформировать данные для выгрузки.");
        Возврат;
    КонецЕсли;
    
    // Сохраняем двоичные данные во временный файл на клиенте
    ИмяВременногоФайлаНаКлиенте = КаталогВременныхФайлов() + "Временный_ТабДок.xlsx";
    ДвоичныеДанныеТабДок.Записать(ИмяВременногоФайлаНаКлиенте);

    Попытка
        Excel = Новый COMОбъект("Excel.Application");
        Excel.Visible = Истина; // Сделать Excel видимым
        
        РабочаяКнига = Excel.Workbooks.Open(ИмяВременногоФайлаНаКлиенте);
        РабочийЛист = РабочаяКнига.Sheets(1);
        
        // Здесь мы можем применять специфическое форматирование Excel
        // Например, изменить ширину столбцов, применить стили
        РабочийЛист.Columns("A:D").AutoFit();
        РабочийЛист.Range("A1").Font.Bold = Истина;
        
        // Можно сохранить файл под другим именем или в другое место
        ИмяФайлаДляСохранения = "";
        Если ВыбратьФайл(РежимДиалогаВыбораФайла.Сохранение, ИмяФайлаДляСохранения, , "Сохранить файл", "Файлы Excel (*.xlsx)|*.xlsx", 1) Тогда
            РабочаяКнига.SaveAs(ИмяФайлаДляСохранения);
            Сообщить("Файл успешно сохранен: " + ИмяФайлаДляСохранения);
        КонецЕсли;
        
        РабочаяКнига.Close(Ложь); // Закрыть книгу без сохранения, если уже сохранили
        Excel.Quit(); // Закрыть приложение Excel
        
    Исключение
        Сообщить("Ошибка при работе с Excel через COM: " + ОписаниеОшибки());
        Если Excel <> Неопределено Тогда
            Excel.Quit();
        КонецЕсли;
    КонецПопытки;
    
    // Удаляем временный файл
    УдалитьФайлы(ИмяВременногоФайлаНаКлиенте);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьДвоичныеДанныеТабличногоДокументаНаСервере(ТабличнаяЧастьДокумента, ИмяШаблона)
    ТабДок = СформироватьТабличныйДокументДляВыгрузки(ТабличнаяЧастьДокумента, ИмяШаблона);
    Если ТабДок = Неопределено Тогда
        Возврат Неопределено;
    КонецЕсли;

    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
    ТабДок.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.XLSX);

    Возврат Новый ДвоичныеДанные(ИмяВременногоФайла);
КонецФункции

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

Решение 3: Управление шаблонами выгрузки через внешние обработки или отчеты

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

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

  1. Хранение шаблонов: Шаблоны могут храниться в виде макетов внутри внешних обработок/отчетов, или же сами обработки могут быть файлами Excel с макросами, которые заполняются данными, переданными из 1С.
  2. Выбор шаблона: Пользователь выбирает нужный шаблон из списка доступных внешних обработок/отчетов.
  3. Запуск обработки/отчета: Выбранная внешняя обработка/отчет запускается, ей передаются необходимые данные (например, ссылка на документ, табличная часть).
  4. Формирование файла: Внешняя обработка/отчет формирует
    
    ТабличныйДокумент
    
    или напрямую работает с Excel через COM (если это внешний отчет/обработка, то COM может быть более приемлем на стороне клиента, так как обработка запускается непосредственно на машине пользователя) и возвращает путь к файлу или его двоичные данные.

Пример реализации (фрагменты):

Мы создадим отдельную внешнюю обработку "ШаблонВыгрузки1.epf" с процедурой экспорта. В основной форме документа мы будем вызывать эту обработку.


// Внешняя обработка (файл "ШаблонВыгрузки1.epf")
// Модуль объекта внешней обработки
Процедура ВыполнитьВыгрузкуВExcel(ДокументСсылка, ПутьКФайлуВыгрузки) Экспорт
    // Здесь ДокументСсылка - это ссылка на документ, из которого мы выгружаем данные
    // Например, ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
    // ТабличнаяЧасть = ДокументОбъект.Товары;

    // ... (логика формирования ТабличногоДокумента, возможно, из макета,
    // специфичного для данной внешней обработки)

    ТабДок = Новый ТабличныйДокумент;
    // ... заполняем ТабДок данными из ДокументСсылка
    ТабДок.Записать(ПутьКФайлуВыгрузки, ТипФайлаТабличногоДокумента.XLSX);
    
КонецПроцедуры

// В модуле формы документа, из которого вызывается выгрузка
&НаКлиенте
Процедура ВыгрузитьЧерезВнешнийШаблон(Команда)
    // Открываем диалог выбора файла внешней обработки
    ИмяФайлаВнешнейОбработки = "";
    Если Не ВыбратьФайл(РежимДиалогаВыбораФайла.Открытие, ИмяФайлаВнешнейОбработки, , "Выберите файл шаблона выгрузки (.epf)", "Внешняя обработка (*.epf)|*.epf", 1) Тогда
        Возврат;
    КонецЕсли;

    // Создаем временный файл для выгрузки
    ИмяФайлаНаКлиенте = КаталогВременныхФайлов() + "ВыгрузкаЧерезШаблон_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".xlsx";

    // Вызываем серверную процедуру для выполнения внешней обработки
    ВыполнитьВнешнююОбработкуНаСервере(ИмяФайлаВнешнейОбработки, Объект.Ссылка, ИмяФайлаНаКлиенте);

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

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

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

Важные моменты и практические советы

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

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


ТабличномДокументе
и стандартных средствах управляемых форм для работы с файлами, так как он обеспечивает наилучшую совместимость и безопасность в большинстве сценариев использования.

← На главную