Помогите экспортировать файлы из OLE-объектов на диск

Статус
Закрыто для дальнейших ответов.

Celts

New member
02.04.2013
4
0
#1
Есть задача, которую ни как не получается решить. Есть база Босс-референт. В ней к документам прикреплены файлы doc, exl, pdf и т.д. Необходимо выгрузить все файлы на диск.
Как экспортировать если файл был добавлен как вложение, разобрался (на скрине, файл с непонятным именем).

<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Код"</div></div><div class="sp-body"><div class="sp-content">doc = dc.GetFirstDocument
Foreach item In doc.Items
If (item.name = "$FILE")
obj = doc.GetAttachment(item.values(0))
obj.ExtractFile(spath+"\"+item.values(0))
EndIf
endforeach

Но агент не работает, если документы word были созданы из шаблона которые уже былы в Lotus (на скрине файл с именем "Документ").
Если док. создали из шаблона то появляется поле $OLEOBJINFO, в котором по-видимому и хранится документ. Но как его от туда вытащить не хватает ума… как только уже не пробовал. :mellow:

p.s. Lotus изучаю пару дней, если вдруг не так спросил, тапками плииз не кидайте :rolleyes:
 

Вложения

A

alexas

#2
Set rtitem=doc.GetfirstItem("Body_ГдеИтемЛежит")
Set obj=rtitem.EmbeddedObjects(0) если он там один лежит
. . . .
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 586
272
#4
все что ОЛЕ - надо использовать само приложение! для получения файла
 

Celts

New member
02.04.2013
4
0
#6
все что ОЛЕ - надо использовать само приложение! для получения файла
Как это сделать? Как получить файл через "само приложение". Из справки не пойму какой метод надо вызвать. :mellow:

Set rtitem=doc.GetfirstItem("DBody_body")
Set obj=rtitem.EmbeddedObjects
. . . .
Данный метод позволяет выгрузить только файлы которые не через OLE.

Заметил также что поле $File хранится RichText по видимому как раз файл, но как их объединить и выгрузить...
 

savl

Lotus team
28.10.2011
2 136
105
#7
так... может это и не подойдет или не очень оптимально, но можно попробовать так:
1. перебираем все EmbObjects в RT-поле.
2. Если это не OLE, то можно сохранить через ExtractFile
3. Если это OLE, то получаем класс.
Если можно обратиться через COM, то через активированное приложение:
Set handleV = notesEmbeddedObject.Activate( show )
можно попробовать его сохранить.
Ну а если нет возможности, то почти ручная работа.
Что-то вроде такого:
Код:
Set rtitem = doc.GetFirstItem( "Body" )
If ( rtitem.Type = RICHTEXT ) Then
Forall o In rtitem.EmbeddedObjects
If ( o.Type = EMBED_ATTACHMENT ) Then
Call o.ExtractFile( "c:\samples\" & o.Source )
'	 Call o.Remove
Call doc.Save( False, True )
Else
className = o.Class ' Получаем класс приложения, через которое создан объект
Select case className
case "XXX": 
' To do
case "XXY": 
' To do
case "XXZ": 
' To do
End Select
End If
End Forall
End If
С MS Office можно активировать приложение без отображения на экране и с помощью COM сохранить на диск.
 

Celts

New member
02.04.2013
4
0
#8
В Lotus нету механизма который позволяет получить OLE документ и простым способом сохранить файл на диске?
Мне необходимо выполнить эту операцию один раз, для переноса эл. документов в другую СЭД.

p.s. может быть я иду сложно дорогой, может есть другой способ получения файлов из базы?
 

savl

Lotus team
28.10.2011
2 136
105
#9
ExtractFile работает только с аттачами, OLE как заметил lmike, надо открывать через приложения.
Google может еще что-то знает, но другой инфы у меня пока нет.
 
A

alexas

#10
Imike и savl правы
На самом деле ничего сложного нет, но нужен word на компе.
вот работа с Word в Вашем случае:
Код:
Set object=Nothing 'на всякий случай, вдруг с object работали до того и не почикали
Set object=rtitem.EmbeddedObjects(0) 'первый в rtitem или выберите нужный 
Print "Инициализация " & object.Class & " ..."
'=======================================
Set worddoc=object.Activate(False)'Активация пориложения ворда
If worddoc Is Nothing Then
Print object.Class +"не инициализирован, возможно он не установлен."
Exit Sub
End If
Set word=worddoc.Application
Call word.documents(1).activate	'Активация документа
Set WordDoc = word.activedocument 'получить активный документ
'сохраняем документ как
WordDoc .SaveAs "c:\DDD.doc"
'все закрываем и уничтожаем
'Word (без запроса на сохранение)
Word.Quit(0)
Set worddoc= Nothing
Set object= Nothing
достанется объект, откроется в Word в темную и сохранится
 

savl

Lotus team
28.10.2011
2 136
105
#11
Может Lotus CAPI: NSFNoteExtractOLE2Object

Еще что-то тут, но толком не понял

Ну и мое решение, но уже написанное:
It's not elegant, and the problem with excel and office files is the macros. If macros exist, then a messagebox opens and asks if you want to enable macros, but only if you set the activate (true). Otherwise it just will not create the object for security reasons.
Also, you have to create the filename for the object.. i.e. is the object a worksheet, word document, visio drawing. To figure out the possibilities and add to the select case, you need to get a sampling and open the document, right click on it to get the object type string and then create another select case statement in this agent, with the appropriate filename and extension.

Embedded objects don't recognize images.. i.e. .jpg, .gif unless they are attached, and not embedded.

When an OLE object is embedded, the only thing Notes (or other applications) store is the program that created it, so it can open the program. It does not save the original filename. Therefore the program must be installed for this code to work, and the saved files are generically named: Word Document, Excel Worksheet, Visio Drawing.. not much help if you want to associate the object with a particular email thread. You could possible create the name from the email properties.. i.e. username, subject.

But what you're going to get is disconnected and out of context files. For example, how would I know if Excelworksheet 2005-11-9.xls is the Acme Quote Request? If it were me, I would simply print the email threads to PDF. Acrobat does this rather well, and you get indexing and context, plus bookmarks.

---------
Another way is to install DAMO on the current Notes Server, and have the users use Outlook to access their Notes Email Database and then copy those to Exchange, or use a Microsoft Exchange migration tool to move the emails to Exchange.
----------------------

Agent Information
Name: Detach and Remove Embedded
Last Modification: 12/10/2006 07:17:06 PM
Comment: [Not Assigned]
Shared Agent: Yes
Type: LotusScript
State: Enabled
Trigger: Manually From Actions Menu
Acts On: Selected documents


LotusScript Code:
Код:
Option Public
Option Declare
Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim collection As NotesDocumentCollection	 
Set db = session.currentdatabase
Set collection = db.UnprocessedDocuments
Dim detachfolder As String
Dim fileExt As String
Dim filename As String
Dim thisName As String
Dim oleobj As Variant
detachfolder = "c:\Temp"
Dim rtitem As Variant
Dim filecount As Integer
Dim Processed As Integer
FileCount = 0
If collection.Count < 1 Then
Msgbox "Sorry, there were no documents selected",,"Nothing Selected"
Exit Sub
End If
Set doc = collection.GetFirstDocument
While Not doc Is Nothing
Filename = ""
Set rtitem = doc.GetFirstItem( "Body" )
If ( rtitem.Type = RICHTEXT ) Then
Forall o In rtitem.EmbeddedObjects						
If o.Type = EMBED_ATTACHMENT Then
thisName = o.Name							 
Filename = detachFolder + "\" + o.name + "_" + Cstr(fileCount + 1)
Print "Processing: " + filename
If okToSave(filename) Then
Call o.ExtractFile (Filename )
Call o.Remove
rtItem.addnewline(1)
rtItem.appendText "Embedded file removed to: " + Filename
rtItem.addnewline(1)
rtItem.appendText "Removed on: " + Format(Now) + " by " + session.commonusername
If doc.HasItem("FileExportError") Then
doc.RemoveItem("FileExportError")
End If
Call doc.Save( True, False, False )
fileCount = fileCount + 1									
Else
Msgbox "Problem saving: " + filename,,"Unable to Save"
doc.FileExportError = "PROCESS MANUALLY"
doc.save True, False, False
End If
End If
If o.Type = EMBED_OBJECT Then
thisName = o.name
Select Case Lcase(o.name)
Case Lcase("Microsoft Office Excel Worksheet")									
Filename =DetachFolder + "\ExcelWorksheet" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".xls"
Case Lcase("Microsoft Word Document")
Filename =DetachFolder + "\WordDocument" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".doc"
Case Lcase("Microsoft Visio Drawing")
Filename =DetachFolder + "\Visio Drawing" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".vsd"
Case Else
Filename =DetachFolder + "\Unknown File" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".rtf"
End Select	 
Print "Processing: " + filename
If Len(filename)> 1 Then
If okToSave(filename) Then										 
On Error Goto Handle_Error
Set oleObj = o.Activate (False)			
If Not oleObj Is Nothing Then
Call oleObj.SaveAs(fileName)
Msgbox "File Saved as: " + filename,,o.name
Call oleObj.Close	 
fileCount = fileCount + 1
rtItem.addnewline(1)
rtItem.appendText "Embedded File saved to: " + FileName
rtItem.addnewline(1)
rtItem.appendText "Saved to Disk on: " + Format(Now) + " by " + session.commonusername
If doc.HasItem("FileExportError") Then
doc.RemoveItem("FileExportError")
End If
Call doc.Save( True, False, False )
Else
Msgbox "Unable to open File: " + filename + " you may have to process this manually",,"File Save Failed"
doc.FileExportError = "PROCESS MANUALLY"
doc.save True, False, False
End If			
Else
Msgbox "Problem saving: " + filename,,"Unable to Save"
End If
End If
End If						
End Forall			
End If			
Processed = Processed + filecount
fileCount = 0
Set doc = collection.GetNextDocument(doc)
Wend
Msgbox "Finished processing: " + Cstr(Processed) + " files" + Chr(13) + _
"Please check: " + detachFolder + " for the files",,"Finished"
Exit Sub
Handle_Error:
On Error Goto 0
Msgbox "Sorry, there was an error processing this request: " + thisName + _
" Error: " + Error$ + "-" + Str(Err),,"Error processing File"
Resume Next
Exit Sub
End Sub
Sub Terminate
End Sub
Function okToSave(strPath As String) As Boolean
Dim tmpFile As String
Dim result As Boolean
result = False
If strPath="" Then Exit Function
On Error Goto NoFile_Error	 
tmpFile = Dir$(strPath)
If Len(tmpFile)<>0 Then result = True
OktoSave = False
If result Then
Dim ans As Integer
ans = Msgbox ("The File: " + strPath + " already exists. Did you want to overwrite it?",36,"File already exists")
If ans = 6 Then
Kill strPath
OktoSave = True
Exit Function				 
End If
Else
OKToSave = True
End If
Exit Function
NoFile_Error:
Err = 0
result = False
Exit Function
И еще:

If you open the notes document, and right click on the OLE object and select properties, a properties dialog box will pop up. The "I" tab will show you the exact object origin, i.e. "Microsoft Office Excel Worksheet".

The code I posted resolves three common OLE types, with a fourth case else, which it labels as "unknown":

Select Case Lcase(o.name)
Case Lcase("Microsoft Office Excel Worksheet")
Filename =DetachFolder + "\ExcelWorksheet" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".xls"
Case Lcase("Microsoft Word Document")
Filename =DetachFolder + "\WordDocument" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".doc"
Case Lcase("Microsoft Visio Drawing")
Filename =DetachFolder + "\Visio Drawing" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".vsd"

'THIS IS WHEN THE OBJECT NAME DOESN'T MEET THE ABOVE NAMES... IT SAVES TO A RICH TEXT FILE.
Case Else
Filename =DetachFolder + "\Unknown File" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".rtf"
End Select


-------
What this means is that the embedded object didn't match the exact wordage of what I initially trapped for:
Microsoft Office Excel Worksheet,
Microsoft Word Document,
Microsoft Visio Drawing

And since it had SOME information in the OLE properties, it resolved it to "unknown file.rtf" which would associate it on your system as a Microsoft word document.


You need to open the document and right click on those two objects, get the object names and add the appropriate "case" statement to the code with the appropriate filename. for instance:


If the object properties for the OLE file is: "Excel Worksheet" then add:

Case Lcase("Microsoft Office Excel Worksheet")
Filename =DetachFolder + "\ExcelWorksheet" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".xls"
Case Lcase("Microsoft Word Document")
Filename =DetachFolder + "\WordDocument" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".doc"
Case Lcase("Microsoft Visio Drawing")
Filename =DetachFolder + "\Visio Drawing" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".vsd"
Case lcase("Excel Worksheet")
Filename =DetachFolder + "\ExcelWorksheet" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".xls"

---------------
Or

----------
Case Lcase("Microsoft Office Excel Worksheet"),lcase("Excel Worksheet")
Filename =DetachFolder + "\ExcelWorksheet" + Format(doc.Created, "yyyy-mm-dd") + "_" + Cstr(fileCount +1) + ".xls"

---------------

The Object property name may vary according to the software version release, and you may have other embedded documents from other programs. I added the case else statement so you can track them down and add them to your code during testing until you finally roll it out on the real thing.

Your final version may include several dozen object names. But give me a few hours, and perhaps I can create another agent that will poll all the types in the view for you.
End Function
Жаль так со встроенным PDF так не получится, но такого я еще не встречал.
 
Статус
Закрыто для дальнейших ответов.