Ситуация такая. У меня был внешний отчет для формирования эксель таблицы, он у меня находился в стандартной кнопке "Отчеты" и работал прям как надо, но мне сказали сделать так чтобы он открывался по кнопке. Тут и начались проблемы, я в итоге нашел способ открытия через создание команды в отчете и указание ссылки? на эту команду в кнопке, но при таком способе начала открываться именно форма, хотя по идее должно открываться просто окно с выбором пути куда сохранить эксельку. Можете подсказать как мне миновать открытие формы или в каком направлении правильнее двигаться?

--------------------------------------------------------------------------
Вот код который находится в форме отчета.

```1c
    &НаСервере
    Функция ПолучитьДанныеНаСервере(Ссылка)

    Запрос = Новый Запрос("
    |ВЫБРАТЬ
    | ЦеныНоменклатурыПоставщиковСрезПоследних.Цена КАК Цена,
    | СделкиСКлиентамиТовары.Номенклатура КАК Номенклатура,
    | СделкиСКлиентамиТовары.Номенклатура.Артикул КАК НоменклатураАртикул,
    | СделкиСКлиентамиТовары.МодельКонкурента КАК МодельКонкурента,
    | СделкиСКлиентамиТовары.ЦенаКонкурента КАК ЦенаКонкурента,
    | СделкиСКлиентамиТовары.ПриУсловииСкидкиКонечномуПотребителюНеМенееОтРРЦ КАК ПриУсловииСкидкиКонечномуПотребителюНеМенееОтРРЦ,
    | СделкиСКлиентамиТовары.Количество КАК Количество,
    | СделкиСКлиентамиТовары.Сумма КАК Сумма,
    | КурсыВалют.Курс КАК Курс,
    | СделкиСКлиентамиТовары.ПредоставленаСкидкаОтРРЦ КАК ПредоставленаСкидкаОтРРЦ
    |ИЗ
    | Справочник.СделкиСКлиентами.Товары КАК СделкиСКлиентамиТовары
    | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатурыПоставщиков.СрезПоследних(&ДатаСреза, Валюта = &Валюта) КАК ЦеныНоменклатурыПоставщиковСрезПоследних
    | ПО (СделкиСКлиентамиТовары.Номенклатура = ЦеныНоменклатурыПоставщиковСрезПоследних.Номенклатура)
    | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(&ДатаСреза, Валюта = &Валюта) КАК КурсыВалют
    | ПО (КурсыВалют.Валюта = КурсыВалют.Валюта)
    |ГДЕ
    | СделкиСКлиентамиТовары.Ссылка = &Ссылка");

    Запрос.УстановитьПараметр("ДатаСреза", ТекущаяДатаСеанса());
    Запрос.УстановитьПараметр("Номенклатура", "СтрокаНоменклатура");
    Запрос.УстановитьПараметр("Валюта", ПсевдоПредопределенные_3с.Получить("Справочники.Валюты.CNY"));
    Запрос.УстановитьПараметр("Ссылка", Ссылка);

    РезультатЗапроса = Запрос.Выполнить();
    ТЗ = РезультатЗапроса.Выгрузить();

    СтруктураДанных = Новый Массив;
    Для каждого СтрокаТаблицы Из ТЗ Цикл
    СтруктураСтрока = Новый Структура;
    СтруктураСтрока.Вставить("Цена", СтрокаТаблицы.Цена);
    СтруктураСтрока.Вставить("Курс", СтрокаТаблицы.Курс);
    СтруктураСтрока.Вставить("Номенклатура", СтрокаТаблицы.Номенклатура);
    СтруктураСтрока.Вставить("НоменклатураАртикул", СтрокаТаблицы.НоменклатураАртикул);
    СтруктураСтрока.Вставить("Количество", СтрокаТаблицы.Количество);
    СтруктураСтрока.Вставить("МодельКонкурента", СтрокаТаблицы.МодельКонкурента);
    СтруктураСтрока.Вставить("ЦенаКонкурента", СтрокаТаблицы.ЦенаКонкурента);
    СтруктураСтрока.Вставить("ПриУсловииСкидкиКонечномуПотребителюНеМенееОтРРЦ", СтрокаТаблицы.ПриУсловииСкидкиКонечномуПотребителюНеМенееОтРРЦ);
    СтруктураСтрока.Вставить("Сумма", СтрокаТаблицы.Сумма);
    СтруктураСтрока.Вставить("ПредоставленаСкидкаОтРРЦ", СтрокаТаблицы.ПредоставленаСкидкаОтРРЦ);

    СтруктураДанных.Добавить(СтруктураСтрока);
    КонецЦикла;

    Возврат СтруктураДанных;
    КонецФункции

    &НаКлиенте
    Процедура ВыгрузитьВExcel(Команда)

    ВывестиЗаполненныйМакет(ПроектСсылка);
    КонецПроцедуры

    &НаКлиенте
    Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт

    ВывестиЗаполненныйМакет(ОбъектыНазначенияМассив[0]);

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

    &НаКлиенте
    Процедура ВывестиЗаполненныйМакет(Ссылка)
    Если Не ПроверитьЗаполнение() Тогда
    Возврат;
    КонецЕсли;

    // Если база серверная, то есть вероятность, что на сервере НЕ установлен Excel. Поэтому всю работу с Excel выполняем только на клиенте
    Попытка
    АдресВХранилище = ПолучитьДанныеМакета("МакетОтчетаМаржинальности");
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВХранилище);

    ИмяФайлаПолное = ПолучитьИмяВременногоФайла("xlsx");
    ДвоичныеДанные.Записать(ИмяФайлаПолное);
    Исключение
    Сообщить(ОписаниеОшибки());
    КонецПопытки;

    Попытка
    Excel = Новый COMОбъект("Excel.Application");
    Исключение
    Сообщить("Ошибка при попытке создать объект "MS Excel"!
    |Возможно приложение "MS Excel" не установлено или установлено неправильно.", СтатусСообщения.Внимание);
    КонецПопытки;

    Книга = Excel.WorkBooks.Open(ИмяФайлаПолное);
    Лист1 = Книга.WorkSheets(1);

    НомерСтроки = 4;

    ПустыеСтроки = 5;
    КонецНоменклатур = ПсевдоПредопределенные_3с.Получить("ЛимитНоменклатурОтчетаМаржинальности") + 3;

    СтруктураДанных = ПолучитьДанныеНаСервере(Ссылка);

    Для каждого ЭлементСтруктуры Из СтруктураДанных Цикл

    Лист1.Cells(НомерСтроки, 2).Value = Строка(ЭлементСтруктуры.Номенклатура);
    Лист1.Cells(НомерСтроки, 3).Value = Строка(ЭлементСтруктуры.НоменклатураАртикул);
    Лист1.Cells(НомерСтроки, 4).Value = Строка(ЭлементСтруктуры.Количество);
    Лист1.Cells(НомерСтроки, 5).Value = строка(Формат(ЭлементСтруктуры.Сумма, "ЧГ=0"));
    Лист1.Cells(НомерСтроки, 6).Value = Строка(ЭлементСтруктуры.Цена);
    Лист1.Cells(НомерСтроки, 7).Value = Строка(Формат(ЭлементСтруктуры.Курс, "ЧРД=."));
    //Лист1.Cells(НомерСтроки, 8).Value = строка(ЭлементСтруктуры.);
    Лист1.Cells(НомерСтроки, 13).Value = строка(Формат(ЭлементСтруктуры.ПриУсловииСкидкиКонечномуПотребителюНеМенееОтРРЦ, "ЧФ=Ч%"));
    Лист1.Cells(НомерСтроки, 15).Value = строка(Формат(ЭлементСтруктуры.ЦенаКонкурента, "ЧГ=0"));
    Лист1.Cells(НомерСтроки, 17).Value = строка("Бренд:" + ЭлементСтруктуры.МодельКонкурента);
    Лист1.Cells(НомерСтроки, 23).Value = строка(Формат(ЭлементСтруктуры.ПредоставленаСкидкаОтРРЦ, "ЧФ=Ч%"));

    НомерСтроки = НомерСтроки + 1;

    КонецЦикла;

    Если НомерСтроки <= КонецНоменклатур Тогда
    Для ИндексСтроки = НомерСтроки по КонецНоменклатур Цикл
    Лист1.Rows(НомерСтроки).Delete();
    КонецЦикла;
    КонецЕсли;

    Excel.DisplayAlerts = Ложь;

    //Диалог выбора пути сохранения
    Режим = РежимДиалогаВыбораФайла.Сохранение;
    ДиалогСохраненияФайла = Новый ДиалогВыбораФайла(Режим);
    ДиалогСохраненияФайла.ПолноеИмяФайла = "ОтчетМаржинальности";
    Фильтр = "Файлы Microsoft Excel(*.xlsx)|*.xlsx";
    ДиалогСохраненияФайла.Фильтр = Фильтр;
    ДиалогСохраненияФайла.МножественныйВыбор = Ложь;
    ДиалогСохраненияФайла.Заголовок = "Выберите файл";
    Если ДиалогСохраненияФайла.Выбрать() Тогда
    ПутьКФайлу = ДиалогСохраненияФайла.ПолноеИмяФайла;
    КонецЕсли;
    Книга.SaveAs(ДиалогСохраненияФайла.ПолноеИмяФайла);
    Excel.Quit();
    Возврат;

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

    &НаСервере
    Функция ПолучитьДанныеМакета(ИмяМакета)
    ОбработкаОбъект = РеквизитФормыВЗначение("Отчет");
    Макет = ОбработкаОбъект.ПолучитьМакет(ИмяМакета);
    Возврат ПоместитьВоВременноеХранилище(Макет, Новый УникальныйИдентификатор());
    КонецФункции
```

--------------------------------------------------------------------------
Вот который находится в модуле объекта отчета

```1c
    Функция СведенияОВнешнейОбработке() Экспорт
    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
    ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиОтчет();
    ПараметрыРегистрации.Наименование = НСтр("ru='Анализ маржинальности'");
    ПараметрыРегистрации.БезопасныйРежим = Ложь;
    ПараметрыРегистрации.Версия = "1.0";
    ПараметрыРегистрации.Информация = НСтр("ru='Анализ маржинальности'");

    //ПараметрыРегистрации.Назначение.Добавить("Справочник.*");

    Команда = ПараметрыРегистрации.Команды.Добавить();
    Команда.Идентификатор = "Анализ маржинальности";
    Команда.Представление = "Анализ маржинальности";
    Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();

    Возврат ПараметрыРегистрации;
    КонецФункции
```

--------------------------------------------------------------------------
 Вот код который находится в модуле команды

```1c
    &НаКлиенте
    Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    //Вставить содержимое обработчика.
    ПараметрыФормы = Новый Структура("СформироватьПриОткрытии", Истина);
    ОткрытьФорму("Отчет.ОтчетМаржинальности.Форма", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник, ПараметрыВыполненияКоманды.Уникальность, ПараметрыВыполненияКоманды.Окно);
    КонецПроцедуры
```
---
Что мешает сделать так?

```1c
    &НаКлиенте
    Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    Форма = ПолучитьФорму("Отчет.ОтчетМаржинальности.Форма");
    Форма.ЭкспортныйМетодМодуляФормы();
    КонецПроцедуры
```
---
Можете подсказатьДа, но нет.
---
Код приведите в читаемый вид с помощью тегов CODE.
---
Сори забыл что так можно делать
---
Есть такая полезная штука, как модуль объекта (не путать с модулем формы). Вот его и надо задействовать, тогда форма будет не нужна.
---
и выгрузка перестанет работать, потому что на сервере может быть не установлен EXCEL :)
---
А может и заработает, если установлен. И не обязательно он там нужен, чтобы выгрузить табличку. Но это уже будет следующий вопрос. :-)
---
А может и заработает
"Программиздим на авось. Недорого."
---
Все такие умные... Что же такие бедные? (с)
---
Точно перестанет, у нас на сервере он не установлен
---
в таком случае ничего переделывать не нужно, пусть и дальше работает
---
Ну вот а дело то и в том что не совсем как надо( Когда это был внешний отчет, все работало отлично, но мне нужно именно заставить его отрабатывать по кнопке. И я вот никак не могу найти способа это сделать(
---
Причем тут внешний или не внешний? У внешнего что ли кнопка другого цвета была?
---
Просто честно не знаю, как отчет миновал форму будучи внешним. Он просто сразу переходил к выгрузке и все было ок. Когда я начал работать с ним внутри конфигурации все что у меня получилось, это добавить команду в отчет и добавить как глобальную команду к кнопке. И в таком случае как я понял может отрабатывать только открытие формы, которое мне не нужно. А другие способы я заставить работать не смог(
---
Просто честно не знаю, как отчет миновал форму будучи внешним. Он просто сразу переходил к выгрузке и все было ок. А открыть код и посмотреть?
---
Что мешает сделать так?

```1c
    &НаКлиенте
    Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    Форма = ПолучитьФорму("Отчет.ОтчетМаржинальности.Форма");
    Форма.ЭкспортныйМетодМодуляФормы();
    КонецПроцедуры
```
---
А ты точно тот же самый человек, который в соседней теме за правильность обращения к области табличного документа кода бился?
---
что не так?
---
Ну, хотя бы то, что не на каждом клиенте может быть Офис. Хотя, если раньше это никого не смущало, то да, пойдет.
---
ТС, вроде как, четко обозначил, что на сервере EXCEL может быть не установлен и все происходит на клиенте. Такой вариант работы полностью устраивает ТС. Так понимаю, все ситуации с неустановленным EXCEL на машинах пользователей решаются по мере их возникновения.
---
Если вы намякиваете на то, что негоже пользоваться Excel через COM, когда есть нативный способ формирования *.xls(х)?
Да, есть, но он сильно тормозной по сравнению, если правильно обращаться с Excel.
Если нет достаточной квалификации обращения с Excel, то нативный способ - единственный способ формирования *.xls(х) со всеми вытекающими из этого минусами.
---
Действительно, не додумался. Сильно благодарен, сейчас все работает прям как надо)
---
Отдельную кнопочку вы же сами "нарисовали"?
---
Да, но это по большей части заглушка пока.