gifts2017

Сохранить табличный документ по умолчанию в Excel

Опубликовал Ризван Шихамматов (dagroma) в раздел Программирование - Практика программирования

Очень часто клиенты просили меня сделать им так, чтобы по нажатию элемента меню "Сохранить как" открывался диалог сохранения файла, в котором уже был бы выбран тип файла "ТаблицаExcel (*.xls)".

Посидел, подумал и решил немножко по-другому сделать.

Добавил в глобальный модуль функцию

Функция глСохранитьФайлExcel() Экспорт
    Перем ТекКонтекст;
    Перем ИмяФайла;
    Перем ИмяКаталога;
   
     ЗагрузитьВнешнююКомпоненту("FormEx.dll");
     глСервис    = СоздатьОбъект("Сервис");

     //получаем контекст активной формы
     Если глСервис.АктивныйКонтекст(ТекКонтекст) = 1 Тогда

        //проверяем является ли форма таблицой
        Если ТипЗначенияСтр(ТекКонтекст) = "Таблица" Тогда

            //активная таблица будет всегда первой в списке таблиц
            глСервис.СписокТаблиц().ПолучитьЗначение(1, ИмяФайла);

            ИмяФайла    = СокрЛП(СтрЗаменить(ИмяФайла, "*", ""));

            ИмяФайла    = СтрЗаменить(ИмяФайла, ":", "-");


          
  Если ФС.ВыбратьФайл(1, ИмяФайла, ИмяКаталога, "Сохранить как", "Таблицы Excel (*.xls)|*.xls") = 1 Тогда
                ТекКонтекст.Записать(ИмяКаталога + ИмяФайла, 1);
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
   
КонецФункции //глСохранитьФайлExcel()

Добавил в меню "Файл" элемент "Сохранить в Excel"(Объект - Задача, Команда - Задача.Выполнить, Формула - глСохранитьФайлExcel()) - и все, клиент доволен.

Для работы необходим formex.dll (можно взять по адресу dorex.ru)


См. также

Вознаграждение за ответ
Сумма: 0 $m
Добавили:
dima mozg (dimaskl) (0.30 $m)
Подписаться Добавить вознаграждение

Комментарии

1. Pari (Pari) 28.09.09 22:46
Есть штатный метод таблиц Записать(<ИмяФайла>,<ТипФайла>). Возможно есть причины, по которым в данном конкретном случае штатный метод хуже (или вообще не работает), а FormEx соответственно лучше. Но тогда хотелось бы увидеть пояснения на этот счет в описании.
2. Сергей (Che) Коцюра (CheBurator) 29.09.09 02:14
(1) штатный метод Записать() жестоко тупит на больших таблицах - причины этого известны и описаны. Решений всяких море, например, практически аналогичное сабжевому, но с исправлением диких тормозов при сохранении: http://www.infostart.ru/public/14186/
.
оптимальным же мне видится использование в сабже и упомянутой ссылке решения от Йоксель... быстро, качественно, плюс куча допвозможностей по сохранению разбиения страниц, параметров печати и пррочая...
3. Ризван Шихамматов (dagroma) 29.09.09 17:30
Задачи оптимизировать сохранение не было. Просто пользователю хотелось меньше нажимать кнопки мыши.
(1)Я не знаю как можно обратиться к уже открытой таблице штатными методами, поэтому использовал FormEx.
(2)А Йоксель я гляну.
4. Альтаир (Altair777) 29.09.09 17:36
(0) Может, в "Статьи" было бы лучше? Раз обработки все равно нет... :-)
5. Сергей (Che) Коцюра (CheBurator) 29.09.09 17:58
(4) не обязательно, код раскрывающий сущность в необходимом объеме - приведен.
(3) без формекса - только переделкой конфигурации и то без гарантий... ;-)
6. Альтаир (Altair777) 30.09.09 17:56
(0) Что-то у меня не получается.
Эта строка просто прелетает как фанерка :-)

Если ФС.ВыбратьФайл(1, ИмяФайла, ИмяКаталога, "Сохранить как", "Таблицы Excel (*.xls)|*.xls") = 1 Тогда

Из отладчика:
ИмяФайла = "ПЕЧАТЬ: Расходная накладная *"
ИмяКаталога =
7. Альтаир (Altair777) 30.09.09 18:00
Автор, перед строкой из (6) добавьте на всякий случай: ;-)

ИмяФайла=СтрЗаменить(ИмяФайла," *","");
ИмяФайла=СтрЗаменить(ИмяФайла,":","-");
8. Альтаир (Altair777) 30.09.09 18:03
+(7)
А еще лучше так....

Если Прав(ИмяФайла,2)=" *" Тогда
ИмяФайла=Лев(ИмяФайла,СтрДлина(ИмяФайла)-2);
КонецЕсли;
ИмяФайла=СтрЗаменить(ИмяФайла,":","-");
9. Ризван Шихамматов (dagroma) 30.09.09 23:46
(7)(8) Изначально у меня было
ИмяФайла = СокрЛП(СтрЗаменить(ИмяФайла, "*", ""));
Но я решил не навязывать свое мнение другим, а без этого кода я просто не проверял и не думал, что вылезут ошибки.
10. Ризван Шихамматов (dagroma) 30.09.09 23:48
11. GSoft. (GSoft) 01.10.09 10:05
а я пользуюсь вот такой процедурой

//_____________________________________________________________________________
//Функция открывает таблицу в MS Excel
//Таблица			- печатная форма 1С
//ИмяЛиста			- имя, которое будет присвоено листу книги MS Excel (если не задано, то остается "Sheet1")
//ОтображатьЯрлычки	- показывать/скрыть ярлычки листов в MS Excel
//ОтображатьСетку	- показывать/скрыть линии сетки в MS Excel
//УдалитьСтроки		- позволяет удалить указанное количество верхних строк таблицы
//УдалитьСтроки		- позволяет удалить указанное количество левых столбцов таблицы
Функция глОткрытьТаблицуВExcel(Таблица, ИмяЛиста = "", ОтображатьЯрлычки = 1, ОтображатьСетку = 1, УдалитьСтроки = 0, УдалитьСтолбцы = 0) Экспорт
	Перем Excel, ExcelWB, ExcelSh, ExcelPS, ИмяФайла, Рез, Зн, Зн1;
	
	Если ТипЗначенияСтр(Таблица) <> "Таблица" Тогда 
		Возврат 0; 
	КонецЕсли;    
	
	Попытка 
		Excel = СоздатьОбъект("Excel.Application") 
	Исключение 
		Сообщить("Не удалось открыть MS Excel","!"); 
		Возврат 0; 
	КонецПопытки;
	
	Пока 1=1 Цикл
		//Подберем уникальное имя для временного файла
		ИмяФайла = КаталогВременныхФайлов() + "1c" + СтрЗаменить(ТекущееВремя(), ":", "");
		Если (ФС.СуществуетФайл(ИмяФайла+".tmp") = 1) или (ФС.СуществуетФайл(ИмяФайла+".xls") = 1) Тогда 
			ФС.УдалитьФайл(ИмяФайла+".tmp"); 
			ФС.УдалитьФайл(ИмяФайла+".xls") 
		Иначе 
			Прервать; 
		КонецЕсли
	КонецЦикла;
	
	Таблица.Записать(ИмяФайла+".tmp", "XLS");
	
	Если ФС.СуществуетФайл(ИмяФайла+".tmp") = 0 Тогда 
		Сообщить("Ошибка записи файла """ + ИмяФайла + "tmp""","!"); 
		Excel = ""; 
		Возврат 0; 
	КонецЕсли;    
	
	Рез = 1;
	
	Попытка
		ExcelWB = Excel.Workbooks.Add(ИмяФайла+".tmp");	//Откроем временный файл в Excel в режиме шаблона (чтобы не блокировать файл)
		Попытка											//Если на клиентской машине не установлен принтер, обращение к настройкам страницы вызывает ошибку. Поэтому работаем в "Попытка ... КонецПопытки"
			ExcelPS = ExcelWB.Sheets(1).PageSetup;		//Исправим спецсимволы в колонтитулах
			Зн = ExcelPS.LeftHeader;	Зн1 = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Зн, "#P", "&P"), "#Q", "&N"), "#T", "&T"), "#D", "&D"); Если Зн <> Зн1 Тогда ExcelPS.LeftHeader	= Зн1 КонецЕсли;
			Зн = ExcelPS.CenterHeader;	Зн1 = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Зн, "#P", "&P"), "#Q", "&N"), "#T", "&T"), "#D", "&D"); Если Зн <> Зн1 Тогда ExcelPS.CenterHeader	= Зн1 КонецЕсли;
			Зн = ExcelPS.RightHeader;	Зн1 = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Зн, "#P", "&P"), "#Q", "&N"), "#T", "&T"), "#D", "&D"); Если Зн <> Зн1 Тогда ExcelPS.RightHeader	= Зн1 КонецЕсли;
			Зн = ExcelPS.LeftFooter;	Зн1 = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Зн, "#P", "&P"), "#Q", "&N"), "#T", "&T"), "#D", "&D"); Если Зн <> Зн1 Тогда ExcelPS.LeftFooter	= Зн1 КонецЕсли;
			Зн = ExcelPS.CenterFooter;	Зн1 = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Зн, "#P", "&P"), "#Q", "&N"), "#T", "&T"), "#D", "&D"); Если Зн <> Зн1 Тогда ExcelPS.CenterFooter	= Зн1 КонецЕсли;
			Зн = ExcelPS.RightFooter;	Зн1 = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Зн, "#P", "&P"), "#Q", "&N"), "#T", "&T"), "#D", "&D"); Если Зн <> Зн1 Тогда ExcelPS.RightFooter	= Зн1 КонецЕсли;
		Исключение 
		КонецПопытки;
		
		ExcelWB.SaveAs(ИмяФайла+".xls", -4143);			//Сохраним, чтобы обновить формат файла до текущего (xlNormal = -4143)
		ExcelWB.Close(0);								//Закроем книгу ...
		ExcelWB = Excel.Workbooks.Add(ИмяФайла+".xls");	//... и вновь откроем в режиме шаблона
		
		Попытка
			ExcelSh = ExcelWB.Sheets(1);
			
			Если ПустаяСтрока(ИмяЛиста) = 0 Тогда			//Зададим имя ярлычка
				ExcelSh.Name = ИмяЛиста
			КонецЕсли;
			
			Если ОтображатьЯрлычки = 1 Тогда				//Сделаем видимыми ярлычки листов
			    ExcelWB.Windows(1).DisplayWorkbookTabs = 1;
				ExcelWB.Windows(1).TabRatio = 0.6			//... и отодвинем горизонтальную полосу прокрутки от левого края
			КонецЕсли;
			
			Если ОтображатьСетку = 0 Тогда					//Скроем линии сетки
				ExcelWB.Windows(1).DisplayGridlines = 0
			КонецЕсли;
		
			Если УдалитьСтроки > 0 Тогда					//Удалим верхние строки
				ExcelSh.Range(ExcelSh.Rows(1), ExcelSh.Rows(УдалитьСтроки)).Delete()
			КонецЕсли;
			
			Если УдалитьСтолбцы > 0 Тогда					//Удалим левые столбцы
				ExcelSh.Range(ExcelSh.Columns(1), ExcelSh.Columns(УдалитьСтолбцы)).Delete()
			КонецЕсли;
		Исключение 
		КонецПопытки;
		
		ExcelWB.Saved = 0;
	Исключение
		Сообщить("Ошибка открытия файла в MS Excel","!"); Рез = 0
	КонецПопытки;
	
	Попытка 
		Excel.Visible = 1 
	Исключение 
	КонецПопытки;  
	
	ExcelWB = ""; ExcelSh = ""; ExcelPS = ""; Excel = "";
	ФС.УдалитьФайл(ИмяФайла+".tmp");
	ФС.УдалитьФайл(ИмяФайла+".xls");
	Возврат Рез
КонецФункции //глОткрытьТаблицуВExcel
...Показать Скрыть
12. Альтаир (Altair777) 01.10.09 10:21
(11) Интересно :-)
Только вот Пока 1=1 Цикл не нужно.
Все равно ведь при совпадении имени файла существующие удаляются.

(9) Очень показательно поведение ФС при запрещенных символах в имени файла.
С * оно не дает сохранить, а вот : воспринимает, похоже, как двоеточие перед буквой диска. И после вызова даже диалог не показывается.
Да и, вообще, я уже не раз замечал, что ФС может ничего не сделать, но и не вывести никакого сообщения по этому поводу.
Наверно, при разработке этой подсистемки кодеры 1С что-то откуда-то выдернули как зря и так же как зря и вставили.
13. GSoft. (GSoft) 01.10.09 10:30
мне в 11 что нравится - то что перенос идет в цветовой гамме 1С а не экселя, а они как известно не совпадают

кстати, насчет имен файлов не пробовал - формирую со штатно-крякозябровыми
14. Евгений Мигачев (Wicked) 01.10.09 21:59
(11) вы не будете против? если я добавлю ваш пример нa help1C.com
или добавьте сами :)
15. Игорь Костюк (foxey) 02.10.09 10:15
Добавил в меню "Файл" элемент "Сохранить в Excel"(Объект - Задача, Команда - Задача.Выполнить, Формула - глСохранитьФайлExcel()) - и все, клиент доволен.

Что-то недопонял... Объект - Задача - это где? Как вставить пункт в меню?
16. GSoft. (GSoft) 02.10.09 10:34
(14) я нет, а вот автор не знаю))) в свое время нашел данный код на просторах инета)))

добавьте с комментарием что автор неизвестен, и что готовы при условии того что он найдется изменить авторство
17. Альтаир (Altair777) 02.10.09 10:37
(15) В редактировании интерфейсов (меню)
Новая колонка, галочка "Системная", выбрать пункт "Файл"
18. Альтаир (Altair777) 02.10.09 10:53
Ой! Чуть не забыл "плюсик" поставить :-)
19. Евгений Мигачев (Wicked) 02.10.09 11:44
20. GSoft. (GSoft) 02.10.09 11:45
(19)
разделите код семерки и восьмерки - будет более читабельно и удобно
21. Дмитрий Дрейцер (MadDAD) 07.10.09 09:02
У меня работает успешно при использовании RWidjets вот такой код:

Процедура ПриПолученииКоманды(пКоманда, пЗаблокироватьКоманду) Экспорт
Сервис = СоздатьОбъект("Сервис");

Если (пКоманда = 57604) ИЛИ (пКоманда = 57603) Тогда
Конт = "";
Если Сервис.АктивныйКонтекст(Конт) = 0 Тогда
Возврат;
КонецЕсли;
Если ПустоеЗначение(Конт) = 1 Тогда
Возврат;
КонецЕсли;

Попытка
Если ТипЗначенияСтр(Конт) = "ГрупповойКонтекст" Тогда
Если ТипЗначенияСтр(Конт.Таблица) = "Таблица" Тогда
Конт = Конт.Таблица;
КонецЕсли;
КонецЕсли;
Исключение
КонецПопытки;

Если ТипЗначенияСтр(Конт) = "Таблица" Тогда
ИмяФайла="";
Попытка
Сервис.СписокТаблиц().ПолучитьЗначение(1,ИмяФайла);
Исключение
КонецПопытки;

пЗаблокироватьКоманду = 1;
//Формируем списки доступных форматов сохранения
сзСтандартнойОбработки = СоздатьОбъект("СписокЗначений");
сзСтандартнойОбработки.ДобавитьЗначение("MXL","Файл 1С");
сзСтандартнойОбработки.ДобавитьЗначение("HTML","Файл HTML");
сзСтандартнойОбработки.ДобавитьЗначение("TXT","Текст");

сзСохраненияЙоксель = СоздатьОбъект("СписокЗначений");
сзСохраненияЙоксель.ДобавитьЗначение("XLS","Файл Excel");

Таб = Конт;
ИмяФайла = ?(ПустоеЗначение(ИмяФайла) = 1,"Таблица1",ИмяФайла);

стрНедопустимыхСимволов = "/\*:"",<>.~'%&";
Позиция = СтрДлина(ИмяФайла);
Для НомерСимвола = 1 по СтрДлина(стрНедопустимыхСимволов) Цикл
ИмяФайла = СтрЗаменить(ИмяФайла,Сред(стрНедопустимыхСимволов,НомерСимвола,1)," ");
КонецЦикла;

Пока СтрЧислоВхождений(ИмяФайла," ") <> 0 цикл
ИмяФайла = СтрЗаменить(ИмяФайла," "," ");
КонецЦикла;


//ИмяФайла = Лев(ИмяФайла,Позиция);
Каталог = "";

//Формируем строку выбора формата файла.
строкаВыбораФормата="";
Для НомерВарианта = 1 по 2 Цикл
Если НомерВарианта = 1 тогда //Перебор списков вариантов сохранения
ТекущийВариант = сзСохраненияЙоксель;
Иначе
ТекущийВариант = сзСтандартнойОбработки;
КонецЕсли;

Для Номер = 1 по ТекущийВариант.РазмерСписка() Цикл // Теперь формируем строку вида "Файл Excel (*.xls)|*.xls| Файл 1C (*.mxl)|*.mxl|"
ОписаниеФормата = "";
ФорматСохранения = ТекущийВариант.ПолучитьЗначение(Номер,ОписаниеФормата);
строкаВыбораФормата = строкаВыбораФормата + Шаблон("[ОписаниеФормата] (*.[Нрег(ФорматСохранения)])|*.[Нрег(ФорматСохранения)]|");
КонецЦикла;
КонецЦикла;
ИмяФайла = Лев(ИмяФайла,20);
//Выбор файла. Если "отмена" тогда возвращаемся
ИмяФайлаОК = 0;
УдалятьСуществующий = 0;
Пока ИмяФайлаОК = 0 цикл
Если ФС.ВыбратьФайл(1,ИмяФайла,Каталог,"Выберите путь сохранения файла",строкаВыбораФормата,"xls") = 0 Тогда
Возврат;
КонецЕсли;

//Определяем расширение файла
КоличествоТочекВИмени = СтрЧислоВхождений(ИмяФайла,".");
Расширение = ИмяФайла;
Для НомерТочки = 1 по КоличествоТочекВИмени Цикл
Расширение = Прав(Расширение,СтрДлина(Расширение)-Найти(Расширение,"."))
КонецЦикла;

//Формат файла - это его раширение
ИмяФайла = Лев(ИмяФайла, СтрДлина(ИмяФайла) - СтрДлина(Расширение) - 1);
ФорматСохранения = Врег(Расширение);
//Формируем путь сохранения
ПутьСохранения = Каталог + ИмяФайла+"."+Расширение;

Если ФС.СуществуетФайл(ПутьСохранения) = 0 Тогда
ИмяФайлаОК = 1;
Иначе
Если Вопрос(""+ПутьСохранения+" уже существует.
|Заменить?","Да+Нет") = "Да" Тогда
УдалятьСуществующий = 1;
ИмяФайлаОК = 1;
Иначе
ИмяФайлаОК = 0;
КонецЕсли;
КонецЕсли;
КонецЦикла;

//Определяемся с варинтом сохранения
Если сзСтандартнойОбработки.Принадлежит(ФорматСохранения) = 1 Тогда //Стандартное сохранение в html, moxel или текст
Таб.Записать(ПутьСохранения,Лев(ФорматСохранения,3));
ИначеЕсли сзСохраненияЙоксель.Принадлежит(ФорматСохранения) = 1 Тогда //в Excel нужно сохранять через йоксель
Док = СоздатьОбъект("ТабличныйДокумент");
Попытка
Док.ЗагрузитьИзТаблицы(Таб);
Док.Записать(ПутьСохранения,1);
Исключение
Таб.Записать(ПутьСохранения,1);;
КонецПопытки;

Для номерПопытки = 1 по 3 Цикл
Если УдалятьСуществующий = 1 Тогда
ФС.УдалитьФайл(ПутьСохранения);
УдалятьСуществующий = 0;
КонецЕсли;

Если ФС.СуществуетФайл(ПутьСохранения) = 0 Тогда
Док.Записать(ПутьСохранения,1);
Иначе
Прервать;
КонецЕсли;
КонецЦикла;

Если ФС.СуществуетФайл(ПутьСохранения) = 0 Тогда
Сообщить("Ошибка: не удалось сохранить файл. Обратитесь к разработчику.","!");
КонецЕсли;

Иначе
Сообщить("Ошибка: Формат сохранения не идентифицирован.","!");
Сообщить("Ошибка: не удалось сохранить файл. Обратитесь к разработчику.","!");
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
22. Сергей (Che) Коцюра (CheBurator) 13.11.09 04:00
ну вы накрутили блин.. давно уже сделано все...
aleks_cons; +1 Ответить
23. Богдан Мельницкий (melnycky) 26.05.10 14:02
Спасибо большое, пригодилось!
24. Марина Чирина (chmv) 05.06.13 09:04
а как проверить табличный документ или нет без dll?
25. Марина Чирина (chmv) 05.06.13 09:27
можно ди тоже самое написать без dll
26. Ризван Шихамматов (dagroma) 05.06.13 16:32
(25)Я такой возможности не нашел.
27. Марина Чирина (chmv) 06.06.13 11:24
ЖАЛЬ. А библеотеку надо регистрировать?
28. Ризван Шихамматов (dagroma) 06.06.13 14:57
29. dima mozg (dimaskl) 19.09.13 09:56
Программно сохранить файл Excel в формате 2003 года, надо написать так Книга.SaveAs(ПутьДляЗаписиФайла, -4143);

Синтаксис команды «SaveAs» во втором параметре разрешает указать формат сохраняемого файла.
Числовое значение фрмата файла Excel 2003: FileFormatNum = -4143
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа