Работа ООо с адинес

Автор smaharbA, 28 апреля 2011, 18:24

0 Пользователи и 1 гость просматривают эту тему.

smaharbA

Давно уже обуздан ООо для работы с адинес по схеме сервера автоматизации, но из года в год, из поста в пост, из вики в вики тянется один и тот же код (методика) придуманная когда то под воздействием алкоголя (это доподлинно известно)
Тогда же была изменена метода в том же самом состоянии...
И в тоже самое время на плаву появилась метода нативной работы с ООо из адинес, может быть будет далее.

//*******************************************
Функция ПолучитьОбертку()
Скрипт=СоздатьОбъект("MSScriptControl.ScriptControl");
Скрипт.language="javascript";
//<-- Подготовим нужные методы
Скрипт.Eval("
|Новый=function(x,y){new x(y)};
|ПрототипМассива=Array.prototype;
|ПрототипМассива.ПолучитьЗначение=function(x){return this[x-1]};
|ПрототипМассива.УстановитьЗначение=function(x,y){this[x-1]=y;return this[x-1]};
|ПрототипМассива.РазмерМассива=function(){return this.length};
|УстановитьБулево=function(x){x.Value=Boolean(x.Value)};
|Массив=new Array();
|;");
// Внедрение объекта Скрипта в самого себя, для сохранности контекста
    Скрипт.AddObject("Скрипт",Скрипт);
// Все подготовке -->
Возврат Скрипт.Eval("this");
КонецФункции // ПолучитьОбертку(Это)

//*******************************************
Процедура Сформировать()
Перем Имя,Путь,Это,Скрипт;
Если ФС.ВыбратьФайл(0,Имя,Путь,"","Файлы офиса|*.ods;*.xls;*.odt;*.doc","*")=0 Тогда
Возврат;
КонецЕсли;
Файл=Путь+Имя;
Это=ПолучитьОбертку();
Сообщить(Это);
Массив=Это.Массив;
//УРЛ="file:///"+Это.encodeURI(СтрЗаменить(Файл,"\","/"));
СервисМанагер=СоздатьОбъект("com.sun.star.ServiceManager");
Обновлялка=СервисМанагер.createInstance("com.sun.star.reflection.CoreReflection");
Проводник=СервисМанагер.createInstance("com.sun.star.ucb.FileContentProvider");
УРЛ=Проводник.getFileURLFromSystemPath("",Файл);
Сообщить(УРЛ);
Обновлялка.forName("com.sun.star.beans.PropertyValue").createObject(Массив);
Сообщить(Массив.РазмерМассива(0));
Параметр=Массив.ПолучитьЗначение(1);
Параметр.Name="Hidden";
Параметр.Value=1;//Если 0 или любое пустое значение то Ложь, иначе Истина
//Сообщить(Параметр.Value);
Это.УстановитьБулево(Параметр);
Сообщить(Параметр.Value);
Десктоп = СервисМанагер.createInstance("com.sun.star.frame.Desktop");
    //Док = Десктоп.LoadComponentFromURL("private:factory/scalc", "_blank", 0, Массив );
    Док = Десктоп.LoadComponentFromURL(УРЛ, "_blank", 0, Массив );
Листы=Док.getSheets();
Лист=Листы.getByIndex(0);
Курсор=Лист.createCursor();
Курсор.gotoStartOfUsedArea(0);
Курсор.gotoEndOfUsedArea(-1);
Адреса=Курсор.getRangeAddress();
Диапазон=Лист.getCellRangeByPosition(Адреса.StartColumn,Адреса.StartRow,Адреса.EndColumn,Адреса.EndRow);
Поиск=Диапазон.createSearchDescriptor();
Поиск.SearchRegularExpression = -1;
Поиск.SearchString = ".+";
Рез=Диапазон.findAll(Поиск);
Всего=Рез.getCount();
Начало=Рез.getByIndex(0).getRangeAddress();
Конец=Рез.getByIndex(Всего-1).getRangeAddress();
ДиапазонДанных=Диапазон.getSpreadsheet().getCellRangeByPosition(Начало.StartColumn, Начало.StartRow,Конец.EndColumn,Конец.EndRow);
Для С=1 По ДиапазонДанных.getRows().getCount() Цикл
Стр="";
Для К=1 По ДиапазонДанных.getColumns().getCount() Цикл
Стр=Стр+"; "+ДиапазонДанных.getCellByPosition(К-1,С-1).getText().String();
КонецЦикла;
Сообщить(Стр);
КонецЦикла;
Десктоп.Terminate();
//createSearchDescriptor
КонецПроцедуры
Я конечно далек от мысли... (с)

smaharbA

Продолжим о баранах, с восьмеркой никогда не работал, по просьбам трудящихся сделал более универсальный метод (восьмерка довольно вольно общается с ком-объектами, хотя для работы с ООо ей не нужна обертка - в примере только для универсальности решения как для 7.7 так и для 8.х)
Переделать на семерку не составит труда, выкинув две функции и заменив строчку Параметр=Новый Массив(...

(Про нативный метод - пока не оформлен в примере, но как сказано выше - метода на плаву, ибо сам не пользую чудовище ООо)

//*******************************************
Функция Разм(Массив)
    Возврат Массив.Количество();
КонецФункции

Функция СоздатьОбъект(Стр="")
    Возврат Новый COMОбъект(Стр);
КонецФункции
//*******************************************
Функция ПолучитьОбертку()
    ХТМЛ = СоздатьОбъект("htmlfile");
    ХТМЛ.Open("text/html");
    //<-- Подготовим нужные методы

    ХТМЛ.Write("<html><head><script>
    |var ХТМЛ;
    |Новый=function(x,y){new x(y)};
    |ПрототипМассива=Array.prototype;
    |ПолучитьЗначение=function(x,y){return x[y-1]};
    |УстановитьЗначение=function(x,y,z){x[y-1]=z;return x[y-1]};
    |РазмерМассива=function(x){return x.length};
    |УстановитьБулево=function(x){x.Value=Boolean(x.Value)};
    |Массив=new Array();
    |НовыйМассив=function(x){return new Array(x)};
    |</script></head><body></body></html>");
    Док=ХТМЛ.documentElement.document;
    // Внедрение объекта Скрипта в самого себя, для сохранности контекста
    Док.script.ХТМЛ=ХТМЛ;
    // Все подготовке -->
    Возврат Док.script;
КонецФункции    // ПолучитьОбертку(Это)

Функция ОпенОфис(Файл="")
    Параметр=Новый Массив(3);//Число на единицу больше чем нужно параметров для совместимости
    Это=ПолучитьОбертку();
    Шел=СоздатьОбъект("Shell.Explorer");
    ФСО=СоздатьОбъект("Scripting.FileSystemObject");
    РелизПрограммы=СокрЛП(ФСО.GetFileVersion(Шел.fullname()));
    //УРЛ="file:///"+Это.encodeURI(СтрЗаменить(Файл,"\","/"));
    СервисМанагер=СоздатьОбъект("com.sun.star.ServiceManager");
    Обновлялка=СервисМанагер.createInstance("com.sun.star.reflection.CoreReflection");
    Проводник=СервисМанагер.createInstance("com.sun.star.ucb.FileContentProvider");
    УРЛ=Проводник.getFileURLFromSystemPath("",Файл);
    Сообщить(УРЛ);
    Массив=Это.НовыйМассив(Разм(Параметр)-1);
    Для Сч=1 По Разм(Параметр)-1 Цикл
        Параметр[Сч]=Это.НовыйМассив(1);
        Обновлялка.forName("com.sun.star.beans.PropertyValue").createObject(Параметр[Сч]);
        Если Лев(РелизПрограммы,1)="7" Тогда
            Параметр[Сч]=Это.ПолучитьЗначение(Параметр[Сч],1);
        КонецЕсли;
        Это.УстановитьЗначение(Массив,Сч,Параметр[Сч]);
    КонецЦикла;

    Параметр[1].Name="Hidden";
    Параметр[1].Value=0;//Если 0 или любое пустое значение то Ложь, иначе Истина
    Это.УстановитьБулево(Параметр[1]);

    Параметр[2].Name="Password";
    Параметр[2].Value="123";
   
    Для Сч=1 По Это.РазмерМассива(Массив) Цикл
        Сообщить(Это.ПолучитьЗначение(Массив,Сч).Value);
    КонецЦикла;
    Десктоп = СервисМанагер.createInstance("com.sun.star.frame.Desktop");
    //Док = Десктоп.LoadComponentFromURL("private:factory/scalc", "_blank", 0, Массив );
    Док = Десктоп.LoadComponentFromURL(УРЛ, "_blank", 0, Массив );
    Листы=Док.getSheets();
    Лист=Листы.getByIndex(0);
    Курсор=Лист.createCursor();
    Курсор.gotoStartOfUsedArea(0);
    Курсор.gotoEndOfUsedArea(-1);
    Адреса=Курсор.getRangeAddress();
    Диапазон=Лист.getCellRangeByPosition(Адреса.StartColumn,Адреса.StartRow,Адреса.EndColumn,Адреса.EndRow);
    Поиск=Диапазон.createSearchDescriptor();
    Поиск.SearchRegularExpression = -1;
    Поиск.SearchString = ".+";
    Рез=Диапазон.findAll(Поиск);
    Всего=Рез.getCount();
    Начало=Рез.getByIndex(0).getRangeAddress();
    Конец=Рез.getByIndex(Всего-1).getRangeAddress();
    ДиапазонДанных=Диапазон.getSpreadsheet().getCellRangeByPosition(Начало.StartColumn, Начало.StartRow,Конец.EndColumn,Конец.EndRow);
    Для С=1 По ДиапазонДанных.getRows().getCount() Цикл
        Стр="";
        Для К=1 По ДиапазонДанных.getColumns().getCount() Цикл
            Стр=Стр+"; "+ДиапазонДанных.getCellByPosition(К-1,С-1).getText().String();
        КонецЦикла;
        Сообщить(Стр);
    КонецЦикла;
    Десктоп.Terminate();
КонецФункции

//*******************************************
Процедура Сформировать()
    Перем Имя,Путь;
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Диалог.Заголовок = "Выберите файл";
    Диалог.ПолноеИмяФайла = "";
    Диалог.ПредварительныйПросмотр = Истина;
    Диалог.Фильтр = "Файлы офиса|*.ods;*.xls;*.odt;*.doc";
    Если Не Диалог.Выбрать() Тогда
        Возврат;
    КонецЕсли;
    ОпенОфис(Диалог.ПолноеИмяФайла);
КонецПроцедуры

Процедура КнопкаВыполнитьНажатие(Кнопка)
    Сформировать();
    // Вставить содержимое обработчика.
КонецПроцедуры
Я конечно далек от мысли... (с)

JohnSUN

Да ладно, подождем с восьмёркой... Пока и семёрочных конфигураций, живых и бодрых, хороших и плохих навалом... Так что код не пропадет.

Хотелось бы особо отметить благотворное влияние алкоголя на лаконичность и прозрачность кода.
[offtopic on]
Своими глазами видел, как человек, "слегка основательно" нагрузившись спиртом во время ночного дежурства, забрел в перфораторную, набил стопку карт где-то в двести пятьдесят (корзина для мусора осталась чистой, НИ ОДНОЙ бракованной карты!), дотащил ее до считки и запустил совершенно безукоризненную "O4KO" - безглючную версию никогда раньше не существовавшей программы для игры в очко... При этом человек по прежнему не мигал и изъяснялся междометиями...
[offtopic off]

Ну, хорошо... Этот код в разных вариациях действительно бродит по инету...
А как насчет "зайти с тылу"? Ну, конкретный пример: открываем Калк, чего-то с ним (не с 1С, а именно с Калком) делаем, и лист заполняется, например, содержимым справочника Валюты. Само собой, к базе цепляемся честно - и логин, и пароль у нас есть.
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

smaharbA

#3
есть пайтон в адинес он понимает стандартный ввод, вот и вся премудрость "нативного" использования
то есть, что то вроде (конечно обернуто лучше в wsc, а не как тут в пакетник, и конечно обуниверсаливание кода для вин и лин)

@echo off
set python=%programfiles%\OpenOffice.org 3\Basis\program\python-core-2.6.1\bin\python.exe
set pythonooo=%programfiles%\OpenOffice.org 3\program\python.exe
for /f %%i in ('call "%pythonooo%" -c "import os; print '\n'.join(os.environ.keys())"') do (
for /f "delims=" %%a in ('call "%pythonooo%" -c "import os; print os.environ['%%~i']"') do (
set "%%~i=%%~a"
)
)

set port=2002
set soffice=%programfiles%\OpenOffice.org 3\program\soffice.exe
start "" /min "%soffice%" "-accept=socket,host=localhost,port=%port%;urp;" -writer

:next_netstat
ping -n 1 127.0.0.1 > nul
netstat -an -p tcp | findstr "LIST" | findstr /r /c:":%port%[\t ]" 2>nul || goto next_netstat

(
echo import uno
echo local = uno.getComponentContext^^^(^^^)
echo res = local.ServiceManager.createInstanceWithContext^^^("com.sun.star.bridge.UnoUrlResolver", local^^^)
echo ctx = res.resolve^^^("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext"^^^)
echo sm = ctx.ServiceManager
echo desktop = sm.createInstanceWithContext^^^("com.sun.star.frame.Desktop", ctx^^^)
echo a = []
echo doc = desktop.getCurrentComponent^^^(^^^)
echo p = uno.createUnoStruct^("com.sun.star.beans.PropertyValue"^^^)
echo a.append^^^(p^^^)
echo a.append^^^(p^^^)
echo a[0].Name = "Pages"
echo a[1].Name = "Wait"
echo a[1].Value = True
echo uno.invoke^^^(doc,'print', ^^^(tuple^^^(a^^^),^^^)^^^)
) | "%python%" -
Я конечно далек от мысли... (с)

smaharbA

Есть еще вариант, втюхать библиотеку pycom и uno вместе с минимумом пайтона в систему/wine и уже она вернет полноценный UNO в адинес со всеми втекающими (соответственно, тогда в линуксе ООо будет использоваться нативный), в варианте выше так же может использоваться нативный ООо линукса
Я конечно далек от мысли... (с)