OpenOffice automation - глюк при закрытии приложения

  1. 8 г. назад

    столкнулся со странным эффектом - если открываю через automation bridge (также известный как Desktop) xls-файл, который уже открыт другим приложением на изменение (или даже в самом OpenOffice) - файл открывается, данные все читаются, никаких ошибок не выскакивает, но далее, после того, как все нужные данные считаны, и пришла пора закрывать OpenOffice, получаем следующую шнягу при выполнении Desktop.Terminate();

    [automation bridge] : com.sun.star.lang.IllegalArgumentException: URL seems to be an unsupported one.

    все ссылки в сети, которые я искал через гугл, приводили меня к проблемам в имени файла (не сконвертированы пробелы и т.п.), но у меня с именем файла всё нормально, и loadComponentFromURL отрабатывает нормально, все данные считываются.

    как должно быть реализовано по-кошерному, чтобы не выкидывало исключение?
    (вариант с игнором исключений от Desktop.Terminate() не предлагать - это не совсем кошерно)

  2. А чем тебе это не нравится?

    функция ПривестиФайлКУРЛ(ПутьКФайлу)
    
        ПутьКФайлу = СтрЗаменить(ПутьКФайлу," ","%20");
        ПутьКФайлу = СтрЗаменить(ПутьКФайлу,"\","/");
        Возврат "file:/" + "/localhost/" + ПутьКФайлу;
    
    Конецфункции
    Ответы: (10)
  3. А, ну да... есть это...

  4. Вот с Инфостарта, немного допилено. Может чего полезного найдешь:

    Функция ЗагрузитьТЗизФайла(ПутьКФайлу,текЛист=0,Знач endCol=0) Экспорт
    
    	//OpenOffice Calc//
    	Попытка
    	        ServiceManager = Новый COMОбъект("com.sun.star.ServiceManager");
    	Исключение
    	        Предупреждение(ОписаниеОшибки() + Символы.ПС + "программа OpenOffice\LibreOffice не установлена на данном компьютере!");
    	Возврат Неопределено;
    	КонецПопытки;
    	Desktop = ServiceManager.createInstance("com.sun.star.frame.Desktop");
    	Свойства = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
    	Свойства.Name = "AsTemplate";
    	Свойства.Value = Истина;
    	Args = Новый COMSafeArray("VT_VARIANT", 2);
    	Args.SetValue(0, Свойства);
    	Свойства1 = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
    	Свойства1.Name = "Hidden";
    	Свойства1.Value = Истина;
    	Args.SetValue(1,Свойства1);
    	Попытка
    		Document = Desktop.LoadComponentFromURL(ПривестиФайлКУРЛ(ПутьКФайлу), "_blank", 0, Args);
    	Исключение
    		ServiceManager = Неопределено;
    	КонецПопытки;
    	Sheets = Document.getSheets();
    	Если Sheets.Count<текЛист Тогда
    		Сообщить("Количество страниц в файле меньше, чем запрошено");
    		ServiceManager = Неопределено;
    		Возврат Неопределено;
    	КонецЕсли;
    	Sheet = Sheets.getByIndex(текЛист-1);
    	Курсор   = Sheet.createCursor();
    	Курсор.gotoEndOfUsedArea(Истина);
    	endCol   = Курсор.Columns.Count - 1;
    	endRow  = Курсор.Rows.Count - 1;
    	begCol = 0;
    	begRow = 0;
    	нКол = 0;
    	локТабЗнач = Новый ТаблицаЗначений;
    	локТабЗнач.Колонки.Очистить();
        КС = Новый КвалификаторыСтроки(50);
        Массив = Новый Массив;
        Массив.Добавить(Тип("Строка"));
        ОписаниеТиповСтрока = Новый ОписаниеТипов(Массив, , КС);
    	Пока нКол <= endCol Цикл
    	    ИмяКол = "К"+Строка(нкол+1);
    	    локТабЗнач.Колонки.Добавить(ИмяКол,ОписаниеТиповСтрока);
    	    нКол = нКол + 1;
    	КонецЦикла;
    	Range = Sheet.getCellRangeByPosition(begCol, begRow, endCol, endRow);
    	МассивКом = Новый COMSafeArray("VT_VARIANT", Range.Columns.Count, Range.Rows.Count);
    	МассивКом = Range.getDataArray();
    	тмпПростойМассив = МассивКом.Выгрузить();
    	Для каждого массив из тмпПростойМассив Цикл
    	     ит = 0;
    	     НовСтрока = локТабЗНач.Добавить();
    	     Для каждого ЭлементМассива из массив цикл
    	           НовСтрока[ит] = ЭлементМассива;
    	           ит = ит + 1;
    	     КонецЦикла;
    	КонецЦикла;
    	Document.Close(True);
    	Document = Неопределено; 
    	
    	ServiceManager = Неопределено;
    	Возврат локТабЗнач;
    
    КонецФункции
    Ответы: (4)
  5. (3) это всё уже изучено и освоено.

    короче, отладка показала, что виноват не опенофис, а 1сина.
    подробности позже

  6. исключение вываливается, всё-таки, не на Desktop.Terminate(); а на loadComponentFromURL()

    Ответы: (6)
  7. (5) а накой тебе Terminate?
    Document.Close(True);
    Document=Неопределено;
    Фсьо, даже
    ServiceManager = Неопределено; не в обязы.

    Ответы: (8)
  8. итак, причина в следующем:

    когда опенофис открываем файл, он рядом создаёт файл блокировки с именем типа
    .~lock.ИмяИсходногоФайла#

    что в случае, например, с файлом example.xls даёт имя
    .~lock.example.xls#

    задача 1с-обработки загрузка данных из всех xls-файлов в указанной папке.
    перебор был реализован при помощи штатных функций 1с 7
    ФС.НайтиПервыйФайл()
    ФС.НайтиСледующийФайл()
    поиском по маске "*.xls"

    так вот, внимание, теперь самый изюм:
    тупая 1сина считает файл с именем ".~lock.example.xls#" соответствующим маске "*.xls"

    соответственно, обработка пыталась стянуть данные и из этого служебного файла.

    занавес

    Ответы: (9)
  9. (6) мне как-то Terminate() ближе

  10. (7) ну а чего не так? "*.xls" прекрсно помещается в "*.xls#".
    А Терминатор как мне видится прибивает модуль в памяти.

    Ответы: (11)
  11. alex_shkut А чем тебе это не нравится?

    вот, как раз, и выявились слабые места этого решения. многие служебные символы не учитываются.

    правильный вариант:

    FileProvider=ServiceManager.createInstance("com.sun.star.ucb.FileContentProvider");
    URL=FileProvider.getFileURLFromSystemPath("",ИмяФайла);
    
  12. alex_shkut ну а чего не так?

    я против. указанное имя файла не соответствует маске "*.xls"

  13. кстати, лень проверять, может, это даже и не 1сина тупая, а сама винда

    Ответы: (13)
  14. (12) ну дык добавь проверку на lock в имени файла, если уж так некошерно в попытку завернуть

    Ответы: (14)
  15. (13) да теперь-то понятно. просто не ожидал такой подлянки

    Ответы: (15)
  16. (14) это еще не подлянка, хуже бывает, когда вроде и не "держит" файл никто (unlocker-ом смотрю, им же после снимаю), а дискриптор взведен, хрен откроешь. (на от семерки до 8,1 виндов наблюдалось, навертели что-то они там, или я тупой, на каком-то форуме советовали паузы делать, я их не понял).

    Ответы: (16) (17)
  17. (15) Может все-таки Терминатор?

  18. (15) на хр я такое тоже иногда встречал

  19. 14.09.2015 16:50:28 отредактировано smaharbA

    77 или 8.х ?

    "*.xls|*.xlsx" не канает ?

    Ответы: (19)
  20. smaharbA 77 или 8.х ?

    глюк конкретно воспроизводится на 7.7, на 8 не проверял

    smaharbA "*.xls|*.xlsx" не канает ?

    нет

    Ответы: (20)
  21. 14.09.2015 17:53:32 отредактировано smaharbA

    (19) проверил на 2012 с маской "*.xls" - xls# в выборку не попал, хотя помню что то такое в 77, что попадают файлы с совпадающим началом расширения, а по сабжу - открывать в режиме чтения ?

    Ответы: (21)
  22. smaharbA открывать в режиме чтения ?

    да без разницы, в каком режиме открывает automation, затык был в том, что если кто-то (другой пользователь) открыл xls-файл из нашей папки опенофисом, то в этой папке создавался файл блокировки xls#, который, по мнению 1с 7.7, подходит к маске *.xls

    Ответы: (22)
  23. (21) Знаю как обернуть ситуацию без фильтра на решетку, но теперь нет смысла.

или зарегистрируйтесь чтобы ответить!