При работе с системой 1С:Предприятие 8.3, особенно в режиме управляемого приложения, часто возникает задача по выгрузке данных из табличных частей документов или отчетов во внешний файл, например, в формат Excel. Эта потребность может быть продиктована необходимостью дальнейшей обработки данных сторонними средствами, отправки информации контрагентам или руководству в удобном виде. Однако простая выгрузка "как есть" не всегда подходит, и нередко требуется предоставить пользователю возможность выбора из нескольких предопределенных шаблонов или вариантов вывода. В этой статье мы подробно рассмотрим различные подходы к решению данной задачи, ориентируясь на управляемые формы и демонстрируя примеры кода.
Мы проанализируем, как можно реализовать функциональность экспорта в Excel, обеспечив при этом гибкость в выборе формата выгрузки — есть автоматическая выгрузка данных на основе СКД. Разберем как классические методы с использованием объекта
ТабличныйДокумент
Для выгрузки данных из 1С в Excel мы можем использовать несколько ключевых механизмов. Выбор конкретного метода зависит от требований к функционалу, сложности шаблонов и необходимости взаимодействия с файловой системой клиента.
ТабличныйДокумент
ТабличныйДокумент
НачатьПомещениеФайла
НачатьПолучениеФайла
Давайте рассмотрим каждый из этих подходов подробнее, уделяя внимание реализации выбора шаблона.
Этот метод является наиболее распространенным и безопасным для управляемых форм. Мы формируем данные в объект
ТабличныйДокумент
Прежде всего, нам необходимо получить данные (для этого можно использовать отбор СКД по табличной части) и программно "нарисовать" их в
ТабличныйДокумент
ТабличныйДокумент
Мы создадим функцию на сервере, которая будет отвечать за формирование
ТабличногоДокумента
// Пример функции на сервере, формирующей ТабличныйДокумент
&НаСервере
Функция СформироватьТабличныйДокументДляВыгрузки(ТабличнаяЧасть, ИмяШаблона)
ТабДок = Новый ТабличныйДокумент;
ТабДок.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ДОКУМЕНТА"; // Можно указать для сохранения настроек
// В зависимости от ИмяШаблона, мы можем изменять структуру вывода
Если ИмяШаблона = "Шаблон1" Тогда
// Пример простого вывода заголовка и данных
ОбластьЗаголовок = ТабДок.Области.Добавить("Заголовок");
ОбластьЗаголовок.Текст = "Заголовок выгрузки по Шаблону 1";
ТабДок.Вывести(ОбластьЗаголовок);
// Добавляем шапку таблицы
ОбластьШапка = ТабДок.Области.Добавить("ШапкаТаблицы");
ОбластьШапка.Текст = "Наименование | Количество | Цена | Сумма"; // Пример
ТабДок.Вывести(ОбластьШапка);
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
ОбластьСтрока = ТабДок.Области.Добавить("СтрокаДанных");
ОбластьСтрока.Текст = СтрокаТЧ.Номенклатура + " | " + СтрокаТЧ.Количество + " | " + СтрокаТЧ.Цена + " | " + СтрокаТЧ.Сумма;
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
ИначеЕсли ИмяШаблона = "Шаблон2" Тогда
// Здесь могла бы быть другая логика формирования
// Например, с другими полями или группировками
ОбластьЗаголовок = ТабДок.Области.Добавить("Заголовок2");
ОбластьЗаголовок.Текст = "Заголовок выгрузки по Шаблону 2 (расширенный)";
ТабДок.Вывести(ОбластьЗаголовок);
// ... другая логика формирования ТабличногоДокумента
Иначе
// Обработка по умолчанию или ошибка
Сообщить("Неизвестный шаблон: " + ИмяШаблона);
Возврат Неопределено;
КонецЕсли;
Возврат ТабДок;
КонецФункции
Для более сложных шаблонов, где необходимо использование макетов, мы можем использовать метод
ПолучитьМакет
ТабличныйДокумент
// Пример с использованием макета
&НаСервере
Функция СформироватьТабличныйДокументИзМакета(ТабличнаяЧасть, ИмяМакета)
Макет = ЭтотОбъект.ПолучитьМакет(ИмяМакета);
ТабДок = Новый ТабличныйДокумент;
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьЗаголовок.Параметры.ТекстЗаголовка = "Выгрузка данных";
ТабДок.Вывести(ОбластьЗаголовок);
ОбластьШапка = Макет.ПолучитьОбласть("ШапкаТаблицы");
ТабДок.Вывести(ОбластьШапка);
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ); // Заполняем параметры области из строки ТЧ
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
Возврат ТабДок;
КонецФункции
После того как
ТабличныйДокумент
// Пример серверной процедуры для сохранения ТабличногоДокумента
// и получения адреса временного хранилища
&НаСервере
Функция СохранитьТабличныйДокументВХранилище(ТабДок)
Если ТабДок = Неопределено Тогда
Возврат "";
КонецЕсли;
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx"); // Можно выбрать xlsx, xls, pdf
ТабДок.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.XLSX);
// Помещаем файл во временное хранилище и возвращаем его адрес
Возврат ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяВременногоФайла));
КонецФункции
На клиенте мы должны предоставить пользователю механизм для выбора шаблона выгрузки — удобнее через универсальная выгрузка из 1С в Excel. Это может быть реализовано с помощью команды на форме (как в примере Easy Peasy обмена), которая открывает форму выбора или выпадающий список.
// Пример обработчика команды на клиенте
&НаКлиенте
Процедура ВыгрузитьВExcel(Команда)
// Здесь мы можем предложить пользователю выбрать шаблон
// Например, через диалог или меню
СписокШаблонов = Новый СписокЗначений;
СписокШаблонов.Добавить("Шаблон1", "Стандартная выгрузка");
СписокШаблонов.Добавить("Шаблон2", "Расширенная выгрузка");
ВыбранныйШаблон = Неопределено;
Если СписокШаблонов.Количество() > 1 Тогда
// Если шаблонов несколько, предлагаем выбрать
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораШаблона", ЭтотОбъект);
ПоказатьВыборИзСписка(ОписаниеОповещения, СписокШаблонов, "Выберите шаблон выгрузки:");
Иначе
// Если шаблон один, используем его
ВыбранныйШаблон = СписокШаблонов[0];
ПослеВыбораШаблона(ВыбранныйШаблон, Неопределено);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораШаблона(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
Если ВыбранныйЭлемент = Неопределено Тогда
Возврат; // Пользователь отменил выбор
КонецЕсли;
// Получаем данные для выгрузки (например, табличную часть документа)
ТабличнаяЧастьДляВыгрузки = Объект.Товары; // Пример: табличная часть документа "Товары"
АдресФайла = СохранитьТабличныйДокументНаСервереИПолучитьАдрес(ТабличнаяЧастьДляВыгрузки, ВыбранныйЭлемент.Значение);
Если ПустаяСтрока(АдресФайла) Тогда
Сообщить("Не удалось сформировать файл для выгрузки.");
Возврат;
КонецЕсли;
// Начинаем загрузку файла на клиент
ИмяФайлаНаКлиенте = "Выгрузка_" + ВыбранныйЭлемент.Представление + "_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".xlsx";
НачатьПолучениеФайла(
Новый ОписаниеОповещения("ПослеЗагрузкиФайла", ЭтотОбъект, АдресФайла),
АдресФайла,
ИмяФайлаНаКлиенте,
Ложь,
РежимДиалогаВыбораФайла.Сохранение
);
КонецПроцедуры
// Вспомогательная процедура на клиенте, вызывающая серверные функции
&НаСервереБезКонтекста
Функция СохранитьТабличныйДокументНаСервереИПолучитьАдрес(ТабличнаяЧастьДокумента, ИмяШаблона)
ТабДок = СформироватьТабличныйДокументДляВыгрузки(ТабличнаяЧастьДокумента, ИмяШаблона);
Возврат СохранитьТабличныйДокументВХранилище(ТабДок);
КонецФункции
&НаКлиенте
Процедура ПослеЗагрузкиФайла(ИмяФайла, СтатусВозврата, ДополнительныеПараметры) Экспорт
Если СтатусВозврата Тогда
Сообщить("Файл '" + ИмяФайла + "' успешно сохранен.");
// Здесь мы можем предложить открыть файл
Вопрос = Новый ВопросДиалог(Новый ОписаниеОповещения("ОткрытьФайлВопросЗавершение", ЭтотОбъект, ИмяФайла), "Открыть сохраненный файл?", РежимДиалогаВопрос.ДаНет);
Иначе
Сообщить("Сохранение файла было отменено или произошла ошибка.");
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОткрытьФайлВопросЗавершение(Результат, ИмяФайла) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
ЗапуститьПриложение(ИмяФайла);
КонецЕсли;
КонецПроцедуры
Этот метод является наиболее предпочтительным для управляемых форм, поскольку он не требует установки COM-объектов на сервере и позволяет пользователю самому управлять местом сохранения файла.
Прямое управление Excel через COM-соединение позволяет нам использовать все возможности Excel: создавать листы, задавать формулы, форматировать ячейки, использовать встроенные функции 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, но его применение в управляемых формах следует тщательно обосновывать и проверять на совместимость с клиентским оборудованием и настройками.
Для более гибкого управления шаблонами выгрузки, особенно если их много и они требуют сложной логики формирования, мы можем вынести каждый шаблон в отдельную внешнюю обработку или внешний отчет. Это позволяет независимую разработку и обновление шаблонов без изменения основной конфигурации.
ТабличныйДокумент
Мы создадим отдельную внешнюю обработку "ШаблонВыгрузки1.epf" с процедурой экспорта. В основной форме документа мы будем вызывать эту обработку.
// Внешняя обработка (файл "ШаблонВыгрузки1.epf")
// Модуль объекта внешней обработки
Процедура ВыполнитьВыгрузкуВExcel(ДокументСсылка, ПутьКФайлуВыгрузки) Экспорт
// Здесь ДокументСсылка - это ссылка на документ, из которого мы выгружаем данные
// Например, ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
// ТабличнаяЧасть = ДокументОбъект.Товары;
// ... (логика формирования ТабличногоДокумента, возможно, из макета,
// специфичного для данной внешней обработки)
ТабДок = Новый ТабличныйДокумент;
// ... заполняем ТабДок данными из ДокументСсылка
ТабДок.Записать(ПутьКФайлуВыгрузки, ТипФайлаТабличногоДокумента.XLSX);
КонецПроцедуры
// В модуле формы документа, из которого вызывается выгрузка
&НаКлиенте
Процедура ВыгрузитьЧерезВнешнийШаблон(Команда)
// Открываем диалог выбора файла внешней обработки
ИмяФайлаВнешнейОбработки = "";
Если Не ВыбратьФайл(РежимДиалогаВыбораФайла.Открытие, ИмяФайлаВнешнейОбработки, , "Выберите файл шаблона выгрузки (.epf)", "Внешняя обработка (*.epf)|*.epf", 1) Тогда
Возврат;
КонецЕсли;
// Создаем временный файл для выгрузки
ИмяФайлаНаКлиенте = КаталогВременныхФайлов() + "ВыгрузкаЧерезШаблон_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".xlsx";
// Вызываем серверную процедуру для выполнения внешней обработки
ВыполнитьВнешнююОбработкуНаСервере(ИмяФайлаВнешнейОбработки, Объект.Ссылка, ИмяФайлаНаКлиенте);
// Предлагаем открыть или сохранить файл
// (аналогично "ПослеЗагрузкиФайла" из Решения 1)
НачатьПолучениеФайла(
Новый ОписаниеОповещения("ПослеЗагрузкиФайла", ЭтотОбъект, ИмяФайлаНаКлиенте),
ИмяФайлаНаКлиенте,
"ВыгрузкаПоШаблону.xlsx", // Предлагаемое имя для сохранения
Ложь,
РежимДиалогаВыбораФайла.Сохранение
);
КонецПроцедуры
&НаСервере
Процедура ВыполнитьВнешнююОбработкуНаСервере(ИмяФайлаОбработки, ДокументСсылка, ПутьКФайлуВыгрузки)
Попытка
ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ИмяФайлаОбработки);
ВнешняяОбработкаОбъект.ВыполнитьВыгрузкуВExcel(ДокументСсылка, ПутьКФайлуВыгрузки);
Исключение
Сообщить("Ошибка выполнения внешней обработки: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Этот подход наиболее гибок для поддержки множества различных шаблонов и может быть расширен для хранения внешних обработок в базе данных, что упрощает их обновление и доступность для пользователей.
Попытка ... Исключение
ПолучитьИмяВременногоФайла
УдалитьФайлы
ФоновыеЗадания
Мы рассмотрели различные подходы к программной выгрузке табличных частей документов в Excel с возможностью выбора шаблона в 1С 8.3 Управляемых формах. Каждый из методов имеет свои преимущества и недостатки, и выбор зависит от специфики вашей задачи и требований к системе. Наиболее универсальным и рекомендуемым является первый подход, основанный на
ТабличномДокументе