На просторах интернета есть целая масса различных алгоритмов, написанных для любой версии 1С. Я же искал самый простой способ, который не использует внешних модулей (не относящихся к встроенным функциям 1С и MS Excel).
Как оказалось, есть несколько проблем при сохранении файла XLS штатными средствами. Самая основная из них - быстродействие. При сохранении больших MXL отчетов в файле XLS, экспорт происходит достаточно долго. Но в моем случае это не очень важно, так как отчеты небольшие, а компьютер мощный. Даже если придется сохранять отчет, в котором больше 1000 строк, работа все равно будет выполнена менее, чем за 10 минут.
Основная идея предложенного решения заключается в следующем: для каждой новой MXL таблицы создаем временный файл, который используется как буфер для копирования таблицы на новый лист результирующего XLS файла. Временный XLS файл сохраняется штатными средствами. Результирующий файл создается через OLE технологию, с использованием функций объекта Excel.
Ниже приведен код для платформы 1С 7.7, сохраняющий несколько MXL таблиц на отдельные листы XLS файла:
//******************************************************************************
//Функция генерирует имя временного XLS файла, используя имя файла приемника
//
Функция ВременныйXLSфайл(Знач ВремФайл)
Возврат СтрЗаменить(ВремФайл,".xls","_temp.xls");
КонецФункции //ВременныйXLSфайл()
//******************************************************************************
//Процедура копирует лист из XLS файла источника в XLS файл приемника
// Excel - глобальная переменная, используемая для связи с EXCEL
//
Процедура СкопироватьСтраницуЭксель( ИмяФайлаИсточника, ИмяФайлаПриемника, ИмяСтраницы = "", ВсегоЛистов)
//Создаем объект Excel.Application
Попытка
Excel = СоздатьОбъект("Excel.Application");
Исключение
Сообщить("ОШИБКА:"+ОписаниеОшибки());
Возврат;
КонецПопытки;
РабочаяКнига = Excel.WorkBooks;
//Открываем временный файл
Попытка
КнигаИсточник = РабочаяКнига.Open(ИмяФайлаИсточника);
Исключение
Сообщить("Не удалось открыть файл источник " + ИмяФайлаИсточника+". " + ОписаниеОшибки());
Возврат;
КонецПопытки;
//Открываем рузультирующий файл
Если ФС.СуществуетФайл(ИмяФайлаПриемника)=1 Тогда
КнигаПриемник = РабочаяКнига.Open(ИмяФайлаПриемника);
Иначе
КнигаПриемник = РабочаяКнига.Add();
КонецЕсли;
//Приступаем к копированию листа с данными из временного файла
Если ИмяСтраницы = "" Тогда
ИмяСтраницы = "Лист Х";
КонецЕсли;
Состояние("Копирование данных - "+ИмяСтраницы+". Ожидайте...");
Для Инд = 1 По КнигаИсточник.Worksheets.Count Цикл
ЛистПриемник = КнигаПриемник.Sheets(1);
КнигаИсточник.Sheets().Copy(ЛистПриемник);
Имя = КнигаПриемник.Sheets(1);
Имя.Name = ИмяСтраницы;
КонецЦикла;
//Сохранение изменений в результирующем файле
Если ФС.СуществуетФайл(ИмяФайлаПриемника)=1 Тогда
Попытка
КнигаПриемник.Save();
Исключение
Сообщить("Не удалось сохранить файл приемник " + ИмяФайлаПриемника+". " + ОписаниеОшибки());
КонецПопытки
Иначе
Попытка
КнигаПриемник.SaveAs(ИмяФайлаПриемника);
Исключение
Сообщить("Не удалось сохранить файл приемник " + ИмяФайлаПриемника+". " + ОписаниеОшибки());
КонецПопытки
Конецесли;
ВсегоЛистов = КнигаПриемник.Worksheets.Count;
Excel.Quit();
Excel = ПолучитьПустоеЗначение();
КонецПроцедуры //СкопироватьСтраницуЭксель()
//******************************************************************************
// СохранитьРезультирующийXLS()
// Создаёт XLS-файл с несколькими листами
// Параметры
// ИмяФайла - Полное имя выходного файла
// ТабMXL - Список значений, в котором:
// Представление - Имя листа
// Значение - Таблица MXL
// ТекФайл - Короткое имя результирующего файла
//
Процедура СохранитьРезультирующийXLS(ИмяФайла, ТабMXL, ТекФайл = "")
Перем ВремФайл, мЛист, Ключ, СкопированоЛистов, ВсегоЛистов;
Если (ПустоеЗначение(ТабMXL)=1)
ИЛИ (ТипЗначения(ТабMXL)<>100) Тогда
Возврат;
ИначеЕсли (ТабMXL.РазмерСписка()=0) Тогда
Возврат;
КонецЕсли;
ВремФайл = ВременныйXLSфайл(ИмяФайла);
Если ФС.СуществуетФайл(ВремФайл)=1 Тогда
ФС.УдалитьФайл(ВремФайл);
КонецЕсли;
Excel = ПолучитьПустоеЗначение();
Попытка
Excel = СоздатьОбъект("Excel.Application");
Исключение
Сообщить("ОШИБКА: "+ОписаниеОшибки());
Возврат;
КонецПопытки;
//Отключаем вывод предупреждений Excel и его появление на экране
Excel.DisplayAlerts = 0;
Excel.ScreenUpdating = 0;
Excel.EnableEvents = 0;
Excel.Visible = 0;
//Выберем предпочтительный формат Excel файла
Если Число(Excel.Application.Version) >= 12 Тогда
ИмяФайла = СтрЗаменить(ИмяФайла, ".xls", ".xlsx");
ТекФайл = СтрЗаменить(ТекФайл, ".xls", ".xlsx");
КонецЕсли;
Excel.Quit();
Excel = ПолучитьПустоеЗначение();
Если ФС.СуществуетФайл(ИмяФайла)=1 Тогда
ФС.УдалитьФайл(ИмяФайла);
КонецЕсли;
//Приступаем к разбору списка значений с таблицами MXL
ВсегоЛистов = 0; СкопированоЛистов = 0;
Для мЛист = -ТабMXL.РазмерСписка() по -1 Цикл
Ключ = "Лист "+мЛист;
// Сохраняем таблицу во временный файл
ТабДок = ТабMXL.ПолучитьЗначение(-мЛист,Ключ);
Состояние("Экспорт данных - "+Ключ+". Ожидайте...");
Попытка
ТабДок.Записать(ВремФайл,1);
Исключение
Сообщить("ОШИБКА: "+ОписаниеОшибки());
Возврат;
КонецПопытки;
//Копируем на новый лист файла приемника таблицу из временного файла
Если ФС.СуществуетФайл(ВремФайл)=1 Тогда
СкопироватьСтраницуЭксель(ВремФайл, ИмяФайла, Ключ, ВсегоЛистов);
ФС.УдалитьФайл(ВремФайл);
СкопированоЛистов = СкопированоЛистов + 1;
КонецЕсли;
КонецЦикла;
//Удаляем пустые листы, которые автоматически создает EXCEL для нового файла
Если (СкопированоЛистов > 0)И(СкопированоЛистов < ВсегоЛистов)И(ФС.СуществуетФайл(ИмяФайла)=1) Тогда
Если (ПустоеЗначение(Excel)=0) Тогда
Excel.Application.Quit();
Excel.Quit();
КонецЕсли;
Попытка
Excel = СоздатьОбъект("Excel.Application");
Исключение
Сообщить("ОШИБКА: "+ОписаниеОшибки());
Возврат;
КонецПопытки;
РабочаяКнига = Excel.WorkBooks;
Попытка
КнигаПриемник = РабочаяКнига.Open(ИмяФайла);
Исключение
Сообщить("Не удалось открыть файл источник " + ИмяФайла+". " + ОписаниеОшибки());
Возврат;
КонецПопытки;
УдаленоЛистов = 0;
Пока (СкопированоЛистов < КнигаПриемник.Worksheets.Count) Цикл
КнигаПриемник.Worksheets(КнигаПриемник.Worksheets.Count).Delete();
УдаленоЛистов = УдаленоЛистов + 1;
КонецЦикла;
Если УдаленоЛистов > 0 Тогда
Попытка
КнигаПриемник.Save();
Исключение
Сообщить("Не удалось сохранить файл приемник " + ИмяФайла+". " + ОписаниеОшибки());
КонецПопытки
КонецЕсли;
Excel.Quit();
Excel = ПолучитьПустоеЗначение();
КонецЕсли;
//Возвращаем исходное состояние Excel после работы
Попытка
Excel = СоздатьОбъект("Excel.Application");
Исключение
Сообщить("ОШИБКА: "+ОписаниеОшибки());
Возврат;
КонецПопытки;
Excel.DisplayAlerts = 1;
Excel.ScreenUpdating = 1;
Excel.EnableEvents = 1;
Excel.Visible = 1;
Excel.Quit();
Excel = ПолучитьПустоеЗначение();
КонецПроцедуры // СохранитьРезультирующийXLS()
Таким образом, у нас всего 2 процедуры и 1 функция для решения задачи. Основная процедура, которая принимает имя будущего XLS файла и список значений с таблицами MXL:
//******************************************************************************
// СохранитьРезультирующийXLS()
// Создаёт XLS-файл с несколькими листами
// Параметры
// ИмяФайла - Полное имя выходного файла
// ТабMXL - Список значений, в котором:
// Представление - Имя листа
// Значение - Таблица MXL
// ТекФайл - Короткое имя результирующего файла
//
Процедура СохранитьРезультирующийXLS(ИмяФайла, ТабMXL, ТекФайл = "")