Общий модуль для разработки несложных отчетов в формате OpenOffice

Программирование - Практика программирования

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

Один мой клиент решил отказаться от использования MS Офиса и перейти на бесплатный Libre Office. Все бы ничего, но половина печатных форм 1С была сделана в Ворде. И, естественно, все резко перестало работать. Документации по ОО в сети много, но изучать ее лучше в спокойной обстановке, а не тогда, когда все рушится и ничего не работает. А в 99% случаев от всей мощи языка ОО нужны какие-то крохи - открыть текстовый документ, присвоить значения переменным, может быть, где-то слегка подправить текст. Проблема в том, что все эти крохи раскиданы по разным источникам или закопаны в тысячестраничных манускриптах. Данный модуль позволит все это сделать, не углубляясь в тонкости языка ОО. 

Внизу приведен пример использования данного модуля.

#Область ЭкспортныеПроцедурыИФункции

Функция ОткрытьДокументКакФайл(ИмяФайла, ЗапускатьСкрытно=Ложь) Экспорт
	
	ОткрыватьКакШаблон = Ложь;
	возврат ОткрытьДокумент(ИмяФайла, ОткрыватьКакШаблон, ЗапускатьСкрытно);
	
КонецФункции

Функция ОткрытьДокументКакШаблон(ИмяФайла, ЗапускатьСкрытно=Ложь) Экспорт
	
	ОткрыватьКакШаблон = Истина;
	возврат ОткрытьДокумент(ИмяФайла, ОткрыватьКакШаблон, ЗапускатьСкрытно);
	
КонецФункции

Функция ОтобразитьДокументНаЭкране(Документ) Экспорт
	
	Документ.getCurrentController().getFrame().getContainerWindow().setVisible(true);
	
КонецФункции

Функция ПеременныеДокумента(Документ) Экспорт
	
	возврат Документ.getTextFieldMasters();
	
КонецФункции

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

Процедура УстановитьЗначениеПеременнойДокумента(ПеременныеДокумента, ИмяПеременной, Значение) Экспорт
	
	Переменная = ПолучитьПеременнуюДокумента(ПеременныеДокумента, ИмяПеременной);
	
	Если Переменная = Неопределено Тогда
		возврат;
	КонецЕсли;
		
	Попытка
		
		Переменная.Content = Значение;
		
	Исключение
		ЗаписьЖурналаРегистрации("Работа с OpenOffice", 
			УровеньЖурналаРегистрации.Ошибка,,,
			"Не смог установить значение переменной "+ИмяПеременной + " = "+Строка(Значение)
			+Символы.ВК
				+ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

Процедура УстановитьЗначениеПеременнойДокументаСПроверкойСуществования(ПеременныеДокумента, ИмяПеременной, Значение) Экспорт
	
	Если ПеременнаяСуществует(ПеременныеДокумента, ИмяПеременной) Тогда
		УстановитьЗначениеПеременнойДокумента(ПеременныеДокумента, ИмяПеременной, Значение);
	КонецЕсли;
	
КонецПроцедуры

Функция ТаблицыДокумента(Документ) Экспорт
	
	возврат Документ.getTextTables();
	
КонецФункции

Процедура УстановитьТекстВЗакладку(Документ, ИмяЗакладки, Текст) Экспорт
	
	Закладка = ПолучитьЗакладку(Документ, ИмяЗакладки);
	Якорь = ПолучитьЯкорь(Закладка);
	Якорь.setString(Текст);
	
КонецПроцедуры

Процедура УстановитьЦветФонаЗакладки(Документ, ИмяЗакладки, Цвет) Экспорт
	
	Закладка = ПолучитьЗакладку(Документ, ИмяЗакладки);
	
	Якорь = ПолучитьЯкорь(Закладка);
	Курсор = ПолучитьКурсор(Документ);
	Курсор.gotoRange(Якорь, 0);
	
	Курсор.setPropertyValue("CharBackColor", Цвет);
	
КонецПроцедуры

#КонецОбласти

#Область Служебные

Функция СоздатьМенеджерСервиса()
    
    Попытка
        // Инициализация основного СОМОбъекта типа com.sun.star.ServiceManager (LibreOffice/OpenOffice).            
        МенеджерСервиса = Новый COMОбъект("com.sun.star.ServiceManager");
	Исключение
		ЗаписьЖурналаРегистрации("Работа с OpenOffice", 
			УровеньЖурналаРегистрации.Ошибка,,, 
			"Не смог создать менеджер сервиса"
				+Символы.ВК
				+ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
        МенеджерСервиса = Неопределено;
		ВызватьИсключение;
    КонецПопытки;
    
    Возврат МенеджерСервиса;
    
КонецФункции

Функция СоздатьЭкземплярРабочегоСтола(МенеджерСервиса)
    
    Попытка
        ЭкземплярРабочегоСтола = МенеджерСервиса.CreateInstance("com.sun.star.frame.Desktop");
    Исключение
		ЗаписьЖурналаРегистрации("Работа с OpenOffice", 
			УровеньЖурналаРегистрации.Ошибка,,, 
			"Не смог создать экземпляр рабочего стола"
				+Символы.ВК
				+ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
        ЭкземплярРабочегоСтола = Неопределено;        
		ВызватьИсключение;
    КонецПопытки;
    
    Возврат ЭкземплярРабочегоСтола;
    
КонецФункции

Функция ОткрытьДокумент(ИмяФайла, ОткрыватьКакШаблон, ЗапускатьСкрытно)
	
	МенеджерСервиса = СоздатьМенеджерСервиса();
	Если МенеджерСервиса = Неопределено Тогда
		возврат Неопределено;
	КонецЕсли;
	
	ЭкземплярРабочегоСтола = СоздатьЭкземплярРабочегоСтола(МенеджерСервиса);
	Если ЭкземплярРабочегоСтола = Неопределено Тогда
		возврат Неопределено;
	КонецЕсли;
	
	URL = ПреобразоватьИмяФайла_в_URL(ИмяФайла);
	
	Попытка
		
		МассивСвойств = Новый Массив;
		
       	Свойство = МенеджерСервиса.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
		Если ОткрыватьКакШаблон Тогда
        	Свойство.Name  = "AsTemplate";
		Иначе
        	Свойство.Name  = "AsFile";
		КонецЕсли;
       	Свойство.Value = Истина;
		
		МассивСвойств.Добавить(Свойство);
		
		Если ЗапускатьСкрытно Тогда
			Свойство = МенеджерСервиса.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
			Свойство.Name  = "Hidden";// Запускать скрытно. Реализовано в LibreOffice 3.6.
			Свойство.Value = Истина;
			
			МассивСвойств.Добавить(Свойство);
		КонецЕсли;
        
		Параметры = Новый COMSafeArray(МассивСвойств, "VT_VARIANT", МассивСвойств.Количество());
        
        Документ = ЭкземплярРабочегоСтола.LoadComponentFromURL(URL, "_blank", 0, Параметры);
		
	Исключение
		
		ЗаписьЖурналаРегистрации("Работа с OpenOffice", 
			УровеньЖурналаРегистрации.Ошибка,,, 
			"Не смог открыть документ "+URL
				+Символы.ВК
				+ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
        Документ = Неопределено;
		ВызватьИсключение;
		
    КонецПопытки;
    
    Возврат Документ;
    
КонецФункции

Функция ПолучитьПеременнуюДокумента(ПеременныеДокумента, ИмяПеременной)
	
	Попытка
		
		ПолноеИмяПеременной = ПолноеИмяПеременной(ИмяПеременной);
		Переменная = ПеременныеДокумента.getByName(ПолноеИмяПеременной);	
		
	Исключение
		ЗаписьЖурналаРегистрации("Работа с OpenOffice", 
			УровеньЖурналаРегистрации.Ошибка,,,
			"В документе нет переменной "+ИмяПеременной
			+Символы.ВК
				+ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		Переменная = Неопределено;
		ВызватьИсключение;
	КонецПопытки;
	
	возврат Переменная;
	
КонецФункции

Функция ПолноеИмяПеременной(ИмяПеременной)
	
	возврат "com.sun.star.text.FieldMaster.User."+ИмяПеременной;
	
КонецФункции

Функция ПеременнаяСуществует(ПеременныеДокумента, ИмяПеременной)
	
	ПолноеИмяПеременной = ПолноеИмяПеременной(ИмяПеременной);
	возврат ПеременныеДокумента.hasbyname(ПолноеИмяПеременной);
	
КонецФункции

функция ПреобразоватьИмяФайла_в_URL(ИмяФайла)
	
	URL = ИмяФайла;
    URL = СтрЗаменить(URL," ","%20");
    URL = СтрЗаменить(URL,"\","/");
	URL = "file://localhost/" + URL;
	
    Возврат URL;
    
Конецфункции

Функция ПолучитьЗакладку(Документ, ИмяЗакладки)
	
	ЗакладкиДокумента = Документ.getBookmarks();
	Закладка = ЗакладкиДокумента.getByName(ИмяЗакладки);
	
	возврат Закладка;
	
КонецФункции

Функция ПолучитьЯкорь(Закладка)
	
	Якорь = Закладка.getAnchor();
	возврат Якорь;
	
КонецФункции

Функция ПолучитьКурсор(Документ)
	
	Контроллер = Документ.CurrentController;
	Курсор = Контроллер.getViewCursor();
	
	возврат Курсор;
	
КонецФункции

#КонецОбласти

Пример использования:

	ДвоичныеДанные = ПолучитьМакет("Договор");//файл odt помещен в макет с типом "двоичные данные"
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("odt");
	ДвоичныеДанные.Записать(ИмяВременногоФайла);
	
	ЗапускатьСкрытно = Ложь;
	Документ = ПроцедурыOpenOffice.ОткрытьДокументКакШаблон(ИмяВременногоФайла, ЗапускатьСкрытно);
	
	ПеременныеДокумента = ПроцедурыOpenOffice.ПеременныеДокумента(Документ);
	ПроцедурыOpenOffice.УстановитьЗначениеПеременнойДокумента(ПеременныеДокумента, "НомерДоговора", "12-ПФ");
	ПроцедурыOpenOffice.УстановитьЗначениеПеременнойДокумента(ПеременныеДокумента, "Руководитель", "Иванов П.М.");
	
	Если ПредоплатаНеНужна Тогда
		ИмяЗакладки = "Предоплата";
		ПроцедурыOpenOffice.УстановитьТекстВЗакладку(Документ, ИмяЗакладки, "");
	КонецЕсли;
	
	Если НужноВыделитьЦветомРазделОсобыеУсловия Тогда
		ИмяЗакладки = "ОсобыеУсловия";
		ПроцедурыOpenOffice.УстановитьЦветФонаЗакладки(Документ, ИмяЗакладки, 4000);
	КонецЕсли;
	
	ПроцедурыOpenOffice.ОтобразитьДокументНаЭкране(Документ);

См. также

Комментарии
1. Сергей Ожерельев (Поручик) 3561 14.06.17 20:52 Сейчас в теме
Нормально. Года три назад я делал набор процедур, расширяющий БСП для работы с Word или OpenOffice. Здесь не выкладывал, оставил на своём сайте. Если интересно, гуглим Процедуры для работы с офисными документами в конфигурациях на БСП версий 2.X 1С Предприятия 8.2/8.3
2. Сергей Лесовой (Synoecium) 96 15.06.17 07:23 Сейчас в теме
Что-то я запутался, на картинке LibreOffice, в статье речь идет о OpenOffice. Или методы работают в обоих пакетах? Если так, тогда стоит это указать в заголовке или в статье.
3. Сергей Ожерельев (Поручик) 3561 15.06.17 09:05 Сейчас в теме
(2) Методы везде одинаковы, основа ведь одна.
CSiER; ipoloskov; +2 Ответить
4. q_i 316 15.06.17 16:21 Сейчас в теме
Имхо, писать ошибки в журнал регистрации избыточно. Достаточно повторно сгенерировать исключение с информативным текстом ошибки. Вызывающая сторона сама разберётся что делать с этим исключением.
5. Игорь Полосков (ipoloskov) 42 15.06.17 16:32 Сейчас в теме
(4) тогда вообще попытка-исключение не нужна
6. q_i 316 15.06.17 17:11 Сейчас в теме
(5) Если устраивает сообщение об ошибке, генерируемое 1c/OOo, то не нужна. Если хочется чтобы текст ошибки был более информативным, то нужно сгенерировать свое исключение (собственно, Вы это и делаете, только текст ошибки пишете в журнал, а не передаете параметром в ВызватьИсключение).
Оставьте свое сообщение