System.__ComObject in LotusNotes in VB.net when extracting Attachments - vb.net

I want to access a Lotus Notes Database and get attachments from documents in it.
I can open the DB and doc and loop through all items.
The problem is, I can not use the items as NotesRichTextItem and therefore not check if there are any item.EmbeddedObject.
I guess it is a problem with declaration of the items.
In general: If I debug using VS2010, doc and the database and NotesSession have the "value" System.__ComObject and "type" is the Domino.Notes Object it should be.
e.g. doc in WATCH:
Name VALUE TYPE
doc {System.__ComObject} Domino.NotesDocument
but if I use the doc.GetType() command the result is
doc.GetType() = {Name = "__ComObject" FullName = "System.__ComObject"}
Since I do not know if my doc.item is a NotesRichTextItem, I define it as an object and want to check afterwards is type. Which I can't since the return value of the functions is as above for doc, too.
Here is the complete code I use currently, I loaded the Lotus Domino reference from the COM section.
Public Sub OpenDocumentLN()
Try
Dim ns As New Domino.NotesSession
Dim db As Domino.NotesDatabase
Dim doc As Domino.NotesDocument
Dim view As Domino.NotesView
If Not (ns Is Nothing) Then
ns.Initialize()
db = ns.GetDatabase("", sLotusNotesPath & sLotusNotesDB, False)
If Not (db Is Nothing) Then
view = db.GetView(sLotusView)
doc = view.GetFirstDocument
While Not doc Is Nothing
Dim lnNextDoc As Domino.NotesDocument = view.GetNextDocument(doc)
For Each item As Domino.NotesItem In doc.Items
Dim rtItem As Object = doc.GetFirstItem(item.Name)
If rtItem Is Nothing Then Continue For
If Not rtItem.GetType() = GetType(Domino.NotesRichTextItem) Then Continue For
' NEVER reach this part of the code since the IF clause prevents it due to the type problem
If rtItem.EmbeddedObjects Is Nothing Then Continue For
For Each o As Domino.NotesEmbeddedObject In rtItem.EmbeddedObjects
o.ExtractFile(sLotusExportPath & o.Source)
Next
Next
doc = lnNextDoc
End While
End If
db = Nothing
ns = Nothing
End If
Catch ex As Exception
End Try
End Sub
How can I use my rtitem as a NotesRichTextItem so I can handle it appropiate? And why are all objects are treated als ComObjects?

Related

OpenXML: Losing Custom Document Property After Editing Word Document

Using DocumentFormat.OpenXML, I am trying to add a custom property to a Word document and then later read the property. The following code "appears" to do just that:
Dim os As OpenSettings = New OpenSettings() With {
.AutoSave = False
}
Dim propVal As String = "Test Value"
Using doc As WordprocessingDocument = WordprocessingDocument.Open(filename, True, os)
Dim cPart As CustomFilePropertiesPart = doc.CustomFilePropertiesPart
If cPart Is Nothing Then
cPart = doc.AddCustomFilePropertiesPart
cPart.Properties = New DocumentFormat.OpenXml.CustomProperties.Properties()
End If
Dim cPart As CustomFilePropertiesPart = doc.CustomFilePropertiesPart
Dim cProps As Properties = cPart.Properties
For Each prop As CustomDocumentProperty In cProps
If prop.Name = "TranscriptID" Then
prop.Remove()
Exit For
End If
Next
Dim newProp As CustomDocumentProperty = New CustomDocumentProperty() With {
.Name = "TranscriptID"
}
newProp.VTBString = New VTBString(propVal)
newProp.FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
cProps.AppendChild(newProp)
Dim pid As Integer = 2
For Each item As CustomDocumentProperty In cProps
item.PropertyId = pid
pid += 1
Next
cProps.Save()
End Using
This code is modeled after code found here:
https://learn.microsoft.com/en-us/office/open-xml/how-to-set-a-custom-property-in-a-word-processing-document
It appears to work in this scenario:
Execute code from above.
Execute code from above again.
At #2 I expect to find the CustomFilePropertiesPart and the property value and my expectation is met.
The problem appears in this scenario:
Execute code from above.
Open document using Microsoft Word, save and close.
Execute code from above again.
What happens in this scenario is that the CustomFilePropertiesPart is missing, whereas it should be found. It is as if Microsoft Word does not successfully read this object, so when the document is save, the object is lost. This suggests to me that there is something that there is something wrong with my code. If you can see what it is, or if you have a comparable working example that I could compare it with, I would appreciate hearing from you. I feel like I correctly followed the Microsoft example, but obviously I did not and I am having trouble seeing where I departed. Thanks.
OK, I found this wonderful tool called the Office Productivity Tool. It has a code generation feature, so I was able to compare what I was doing with what Word does. Basically the problem was with setting the property value. This snippet does the trick:
Dim cProps As Properties = cPart.Properties
Dim val As DocumentFormat.OpenXml.VariantTypes.VTLPWSTR = New DocumentFormat.OpenXml.VariantTypes.VTLPWSTR
val.Text = tr.ID.ToString
Dim newProp As CustomDocumentProperty = New CustomDocumentProperty() With {
.Name = "TranscriptID",
.FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
}
newProp.Append(val)
cProps.AppendChild(newProp)

Lotusscript save base64 encoded string to file (DLL)

[EDIT] I believe i left out my original problem. To me it seems like the issue resides in passing the content of the decoded MIMEEntity to a stream, which i'd like to write out to a file. No matter how i attempt it, i can not get lotus script to write the binary data to the file. If anyone has any helpful opinion/suggestion/etc.., I'd be more then grateful!
[ORIGINAL]
I have the following code
Dim a As String
a = "TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" & _
"AAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1v" & _
...
...
Dim session As New NotesSession
Dim stream As NotesStream
Dim doc As NotesDocument
Dim body As NotesMimeEntity
Dim db As NotesDatabase
Set session = New NotesSession
'Create stream and display properties
Set stream = session.CreateStream
'check if the file exists
If Not stream.Open("C:\\Notes\\update.dll") Then
'if the file doesnot exist then create one and add a time stamp to it
Dim fileNum As Integer
fileNum% = Freefile()
Open "/ww414/notes/ebcdicfile.txt" For Output As fileNum%
Close fileNum%
'this should have created the file. see if it existis now
If Not stream.Open("C:\\Notes\\update.dll") Then
'if the file has not been created yet then let the user know of the error that blocks the operation
Messagebox("Log file Is inaccessible")
End If
End If
Dim b As NotesStream
Set b = session.CreateStream
Call b.WriteText(a)
'==========================================================
'update file with the b64 decoded content
Set db = session.CurrentDatabase
Set doc = db.CreateDocument
session.ConvertMime = False
Set body = doc.CreateMIMEEntity
Call body.SetContentFromText(b, "", ENC_BASE64)
Call body.DecodeContent
content = body.ContentAsText
Call stream.WriteText(content)
'close stream/file open in memory
Call stream.Close()
The problem is, the file gets created, but when it comes to the content, it simply puts a few bytes in it (instead of the 14kb of actual file data)
I have checked a bunch of forums and possible solutions, but none of them seem to work.
For instance:
https://www.nsftools.com/tips/Base64v14.lss
http://www-10.lotus.com/ldd/nd6forum.nsf/e5f5333619f2996885256a220009508f/a8bb2c21c99f9c4d852571ee005cede9?OpenDocument
https://ghads.wordpress.com/2008/10/17/vbscript-readwrite-binary-encodedecode-base64/
So, the solution was even simpler as i thought.
This was a huge help, as the root cause of my issue seemed to be the writing out the binary content to the disk. And that was due to creating the file the wrong way! While the file got created it couldn't output the content properly (for some "Lotus reasons"..)
Either way, taking a coffee break and starting everything from zero helped a lot! The code that worked (for future ref. if someone would need to get such a thing working):
Sub Initialize
Dim a As String
a ="BASE64 ENCODED STRING(In my case it was a DLL)"
Dim session As New NotesSession
Dim stream As NotesStream
Dim doc As NotesDocument
Dim body As NotesMimeEntity
Dim db As NotesDatabase
Set session = New NotesSession
Set stream = session.CreateStream
Dim b As NotesStream
Set b = session.CreateStream
Call b.WriteText(a, EOL_NONE)
Set db = session.CurrentDatabase
Set doc = db.CreateDocument
session.ConvertMime = False
Set mime = doc.CreateMIMEEntity
Call mime.SetContentFromText(b, "application/octet-stream", ENC_BASE64)
Call mime.DecodeContent
If Not(mime Is Nothing) Then
Set stream = session.CreateStream
pathname$ = "c:\temp\test.dll"
If Not stream.Open(pathname$, "binary") Then
Messagebox pathname$,, "Open failed"
Goto ExitSub
End If
Call mime.GetContentAsBytes(stream)
Call stream.Close
Else
Messagebox "Not MIME",, doc.GetItemValue("Subject")(0)
End If
ExitSub:
session.ConvertMIME = True ' Restore conversion
End Sub

NotesDocument.save() causing loss of rich text formatting

I have following code in an lotusscript agent that removes attachments from NotesDocuments. But NotesDocument.save() causes loss of rich text formatting (font, color). Is there any way to retain the formatting?
Sub removeAttachments_v2(doc As NotesDocument)
Dim session As NotesSession
Dim rtitem As Variant
Dim filename As String
Dim ans As Variant
Set session = New NotesSession
Dim richstyle As NotesRichTextStyle
Set richstyle = session.CreateRichTextStyle
richstyle.NotesColor = COLOR_BLUE
If doc.HasEmbedded Then
Set rtitem = doc.getfirstitem("Body")
If (rtitem.type = RICHTEXT) Then
ForAll object In rtitem.EmbeddedObjects
If (object.Type = EMBED_ATTACHMENT) Then
filename = object.source
Call object.remove
Call rtitem.AddNewLine( 2 )
Call rtitem.AppendStyle(richstyle)
Call rtitem.AppendText( "Attachemnt removed: " & filename )
Call doc.Save( True, True , True )
End If
End ForAll
End If
End If
End sub
Edit1: Initialize function
Sub Initialize
Dim db As New NotesDatabase("","")
Dim col As NotesDocumentCollection
Dim doc As NotesDocument
Call db.Open("", "C:\this\is\db\dir\test.nsf")
Set col = db.Alldocuments
Set doc = col.Getfirstdocument()
While Not ( doc Is Nothing )
Call RemoveAttachments_v2(doc)
Call doc.Save(False, False, False)
Set doc = col.GetNextDocument( doc )
Wend
End Sub
Despite of the fact, that you save the document for every attachment I cannot find any reason, why this should happen. I just copied your code in an agent, and it removes the attachments as desired and appends the text in blue...
No formatting is lost...
The error has to be somewhere else in your code, probably in the calling function.
OLD ANSWER (wrong due to own tests, just kept here as history):
The Problem here most probably is: you defined rtitem as Variant. And
getfirstitem gets you a NotesItem instead of a NotesRichtextItem, so
when saving, it is converted to a "plain Text" item.
Most probably you used Variant instead of NotesRichtextItem, because
there are Mime- mails where defining the variable as NotesRichtextItem
will cause an "Type Missmatch" or similar error. As long as you do not
write anything back this is OK.
As Mime Mails need complete different handling to achieve your goal,
you should first fix the code for pure NotesRichtextItems by using the
right type, and then write another code- branch for handling Mime-
items

Cannot Close Down MS Word From .NET

I have the following snippet of code. It works (opens all the Word documents in a directory and then closes them down)...but it doesn't clean up after itself when I totally exit the program.
By this I mean that if I look at the TaskManager once I exit the VB.NET application I see the WINWORD.EXE even though it did not exist before I opened the application.
Here's the declarations I have:
Dim WordApp As Microsoft.Office.Interop.Word.Application
Dim aDoc As Microsoft.Office.Interop.Word.Document
Dim missing As Object = System.Reflection.Missing.Value
Dim nullobj As Object = System.Reflection.Missing.Value
Dim MYreadOnly As Object = False
Dim isVisible As Object = False
And here's the code:
Private Sub cmdGenerate_Click(sender As System.Object, e As System.EventArgs) Handles cmdGenerateKeywords.Click
Dim xmldoc As New XmlDataDocument()
Dim xmlnode As XmlNodeList
Dim i As Integer
Dim fs As FileStream
WordApp = New Microsoft.Office.Interop.Word.Application
WordApp.Visible = False
For Each f As FileInfo In New DirectoryInfo(txtFolderName.Text).GetFiles("*.docx")
' Open the document that was chosen by the dialog
aDoc = WordApp.Documents.Open(f.FullName, missing, [MYreadOnly], _
missing, missing, missing, missing, missing, missing, missing, _
missing, isVisible)
'aDoc.Close()
aDoc = Nothing
Next
'Close the Word Document
'aDoc.Close(nullobj, nullobj, nullobj)
WordApp.Application.Quit()
WordApp = Nothing
End Sub
As you can tell I've commented and uncommented various statements in regards to closing down Word documents and the Word Application itself. Nothing I have tried seems to be able to get rid of that pesky WINWORD.EXE
Something seems to have a lock and will not let it close down? Is that it?
Run explicitly Garbage Collector, as is shown in this article:
// Clean up the unmanaged Word COM resources by forcing a garbage
// collection as soon as the calling function is off the stack (at
// which point these objects are no longer rooted).
GC.Collect();
GC.WaitForPendingFinalizers();
// GC needs to be called twice in order to get the Finalizers called
// - the first time in, it simply makes a list of what is to be
// finalized, the second time in, it actually is finalizing. Only
// then will the object do its automatic ReleaseComObject.
GC.Collect();
GC.WaitForPendingFinalizers();
Despite link above, my experience is that run once is enough. But second call doesn't throw an error, so do it this way.
fs.Close()
fs.Dispose()
http://msdn.microsoft.com/en-us/library/system.io.filestream.dispose.aspx
This releases your resources. Might allow other close methods to work. I read through the code twice and do not see you using "fs" anywhere like I would expect.

How to do Mailmerge in Openoffice using Vb.net

Its 5th Question and apart of one I didn't get response from the experts....
Hope this time I will get the helping hand.
I want to do mailmerge in openoffice using Vb.net and I am totally new with openoffice.
I searched on net for some help to understand how to use openoffice with vb.net but all I get is half info.....So can you please help me and give me code for mailmerge in vb.net for openoffice.
Well i have list of workers in DB and there is this facility that if they want to mail to all or some of the workers then they can do it.I have completed this task using Microsoft Office now as a Add in we are providing the facility to perform the same task using Open Office.
What they have to do is just select the List of workers and click on a button and it will automate the mailmerge using the field of those workers data from DB. The Code of mine is as shown below
Public Sub OpenOfficeMail(ByVal StrFilter As String)
Dim oSM ''Root object for accessing OpenOffice from VB
Dim oDesk, oDoc As Object ''First objects from the API
Dim arg(-1) ''Ignore it for the moment !
''Instanciate OOo : this line is mandatory with VB for OOo API
oSM = CreateObject("com.sun.star.ServiceManager")
''Create the first and most important service
oDesk = oSM.createInstance("com.sun.star.frame.Desktop")
''Create a new doc
oDoc = oDesk.loadComponentFromURL("private:factory/swriter", "_blank", 0, arg)
''Close the doc
oDoc.Close(True)
oDoc = Nothing
''Open an existing doc (pay attention to the syntax for first argument)
oDoc = oDesk.loadComponentFromURL("file:///C:\Users\Savan\Documents\1.odt", "_blank", 0, arg)
Dim t_OOo As Type
t_OOo = Type.GetTypeFromProgID("com.sun.star.ServiceManager")
Dim objServiceManager As New Object
objServiceManager = System.Activator.CreateInstance(t_OOo)
Dim oMailMerge As New Object
oMailMerge = t_OOo.InvokeMember("createInstance", Reflection.BindingFlags.InvokeMethod, Nothing, _
objServiceManager, New [Object]() {"com.sun.star.text.MailMerge"}) 'com.sun.star.text.MailMerge"})
oMailMerge.DocumentURL = "file:///C:\Users\Savan\Documents\1.odt"
oMailMerge.DataSourceName = CreateSource(StrFilter)''Function that will return the datasource name which will be a text file's path
oMailMerge.CommandType = 0
oMailMerge.Command = "file:///C:\Mail.txt"
oMailMerge.OutputType = 2
oMailMerge.execute(New [Object]() {})**---->I am getting Error here**
End Sub