OpenXML: Losing Custom Document Property After Editing Word Document - vb.net

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)

Related

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

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?

OTA - ALM 11.52 - Building Graphs through OTA

I am trying to create reports in the 'Analysis View' using OTA and HP ALM 11.52.
I've searched the OTA Reference Documentation and looked for samples online and I've found a few samples, but none seem to work.
There seem to be three methods utilised:
TDConnection.GraphBuilder.BuildGraph(GraphDefinition)
TDConnection.testFactory.BuildSummaryGraph("TS_STATUS", "TS_STATUS", "", 0, myFilter, False, False)
and a third method involving an AnalysisItemFactory object that I can't find anywhere in the OTA documentation.
I've tried the first two and they seem to run without triggering an error, however, no graph appears in ALM.
Is there a difference between these methods and which is the cleanest method?
Here are my attempts so far:
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Method 1: GraphBuilder
'Set GB = QCConnection.GraphBuilder
'Set G1 = GB.CreateGraphDefinition(2, 0)
'G1.Property(0) = "TS_NAME"
'G1.Property(1) = "TC_STATUS"
'Set tsf = QCConnection.TestSetFactory
'Set myFilter = tsf.Filter
'myFilter.Filter ("TC_STATUS") = "Not(N/A)"
'G1.Filter = "Filter: Status[Not N/A]"
'Set g = GB.BuildGraph(G1)
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Method 2: BuildSummaryGraph
'Dim testF
'Dim graph1
'Dim Filter
'Set testF = QCConnection.testFactory
'Set myFilter = testF.Filter
'myFilter.Filter("TS_STATUS") = "Not(N/A)"
'Set graph1 = _
'testF.BuildSummaryGraph("TC_NAME", "TS_STATUS", "", 0, myFilter, False, False)
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Method 3: AnalysisItemsFactory? I can't find any documentation on this object, yet I've seen it referenced in other code samples.
'Set aiFolderFact = QCConnection.AnalysisItemFolderFactory
'Set aiFact = QCConnection.AnalysisItemFactory ~~~ This line actually runs fine so I know it at least exists. But I am definitely not using the proper methods below.
'Set G1 = aiFact.AddItem("")
'G1.Field("AI_PARENT_ID") = 1001 'Public
'G1.Field("AI_TYPE") = "Graph"
'G1.Field("AI_SUB_TYPE") = "Progress Graph"
'G1.Field("AI_OWNER") = qcUserName.Value
'G1.Field("AI_MODULE") = "requirement"
'G1.Field("AI_NAME") = "test graph"
'G1.Post
As I mentioned previously, all of these scripts run error free, but I see no graph in the Analysis View. I've also noticed that there seem to be no "Name" or "Path" fields.
I've taken a look at the tables, and there seems to be 'Analysis_Item_Folder' and 'Analysis Items' tables so It's know it's possible to do this through the OTA client. Is there an AnalysisItemFactory and could someone please kindly provide a sample script of what I'm looking for?
I was able to generate a report with the help of this HP ALM forum entry.
As in the forum mentioned it is not an official documented feature of HP ALM. Therefore it can be that in the future it won't work without replacement. Please keep that in mind.
In case the forum entry may get deleted I copied the answer by a user called "delarosa62" here (date of copy 2015/9/8):
Hi MichaelMotes and the rest of the community members.
I developed a VBA code to generate dashboard standard reports automatically. I get the "successful exception" you have mentioned. However my report does not get generated in my hard disk.
I don't get any errors.
I have adapted your Visial Basic Code to VBA using OTA. I have the otareport 1.0 Type Library and otaxml type lib registered in the tools/reference option in the VBA module window.
I am pasting my code below hoping you guys can give me some insight on this. I am not getting any errors. Just the exception which includes a successful completion message.
Sub externalSTDReports()
Dim reqFact
Dim reqFilter
Dim reqList
Dim gTDConn As Object
Set gTDConn = CreateObject("TDApiOle80.TDConnection")
'QC Connection data
login_id = ActiveWorkbook.Sheets("CONFIG").Cells(9, 3).value
login_passwd = ActiveWorkbook.Sheets("CONFIG").Cells(10, 3).value
domain_name = ActiveWorkbook.Sheets("CONFIG").Cells(11, 3).value
project_name = ActiveWorkbook.Sheets("CONFIG").Cells(12, 3).value
server_name = ActiveWorkbook.Sheets("CONFIG").Cells(13, 3).value
gTDConn.InitConnectionEx server_name
gTDConn.login login_id, login_passwd
gTDConn.Connect domain_name, project_name
Set Rep = New OTAREPORTLib.Reporter
Call Rep.SetConnection(gTDConn, 0) ' This line doesn´t return errors. But I don´t know if it is correct
Set RepConf = Rep.ReportConfig
Rep.File = "C:\Users\cris\AppData\Local\Temp\TD_80\4c223b57\Reports\std.html"
Rep.Template = "C:\Users\cris\AppData\Local\Temp\TD_80\4c223b57\Reports\default.xsl"
'******************************************************** filter Reports
Set aiFact = gTDConn.AnalysisItemFolderFactory
Set reportFact = gTDConn.AnalysisItemFactory
Set aiFilter = aiFact.Filter
Set aiList = aiFilter.NewList
Set anf = reportFact.Filter
Dim FilterStr As String
For Each ai In anf.NewList
reportName = ai.Name
reportID = ai.id
If reportName = "tmp" Then
FilterStr = ai.Field("AI_FILTER_DATA")
RepConf.Filter = FilterStr
On Error Resume Next
'i is empty. Don´t know why
i = Rep.Generate(0, 0) MsgBox i & " --- " & Rep.File Debug.Print Rep.File '-------------------- Exit For
End If
Next
Set gTDConn = Nothing
Set aiFact = Nothing
Set reportFact = Nothing
Set aiFilter = Nothing
Set aiList = Nothing Set anf = Nothing
Set RepConfig = Nothing
Set Rep = Nothing
MsgBox "END "
End Sub 'Pls HELP!!
Graphs can be generated under analysis folder, its a bit of a process because you need a sound understanding of the database, XML and OTA API. There is no direct API available for building graphs, I have created the code samples below
https://github.com/sumeet-kushwah/ALM_OTA_Wrapper/blob/master/ALM_Wrapper/Analysis.cs
Check the following functions
CreateDefectAgeGraph
CreateExcelReport
CreateDefectSummaryGraph
CreateSummaryGraph
These functions are called from the tests available below
https://github.com/sumeet-kushwah/ALM_OTA_Wrapper/blob/master/ALM_Wrapper_Tests/ALM_Wrapper_Test.cs
Look for test function
Test_AnalysisAndDashboardScripts
If you have any questions regarding the process, please let me know.

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

How do I search through a string for a particular hyperlink in Visualbasic.net?

I have a written a program which downloads a webpage's source but now I want to search the source for a particular link I know the link is written like this:
<b>Geographical Survey Work</b>
Is there anyway of using "Geographical Survey Work" as criteria to retrieve the link? The code I am using to download the source to a string is this:
Dim sourcecode As String = ((New Net.WebClient).DownloadString("http://examplesite.com"))
So just to clarify I want to type into an input box "Geographical Survey Work" for instance and "/internet/A2" to popup in a messagebox? I think it can be done using a regex, but that's a bit beyond me. Any help would be great.
With HTMLAgilityPack:
Dim vsPageHTML As String = "<html>... your webpage HTML code ...</html>"
Dim voHTMLDoc.LoadHtml(vsPageHTML) : vsPageHTML = ""
Dim vsURI As String = ""
Dim voNodes As HtmlAgilityPack.HtmlNodeCollection = voHTMLDoc.SelectNodes("//a[#href]")
If Not IsNothing(voNodes) Then
For Each voNode As HtmlAgilityPack.HtmlNode In voNodes
If voNode.innerHTML.toLower() = "<b>geographical survey work</b>" Then
vsURI = voNode.GetAttributeValue("href", "")
Exit For
End If
Next
End If
voNodes = Nothing : voHTMLDoc = Nothing
Do whatever you want with vsURI.
You might need to tweak the code a bit as I'm writing free-hand.

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