How to do a simple mail merge in OpenOffice - c#

I need to do a simple mail merge in OpenOffice using C++, VBScript, VB.Net or C# via OLE or native API. Are there any good examples available?

I haven't come up with a solution I'm really happy with but here are some notes:
Q. What is the OO API for mail merge?
A. http://api.openoffice.org/docs/common/ref/com/sun/star/text/MailMerge.html
Q. What support groups?
A. http://user.services.openoffice.org/en/forum/viewforum.php?f=20
Q. Sample code?
A. http://user.services.openoffice.org/en/forum/viewtopic.php?f=20&t=946&p=3778&hilit=mail+merge#p3778
http://user.services.openoffice.org/en/forum/viewtopic.php?f=20&t=8088&p=38017&hilit=mail+merge#p38017
Q. Any more examples?
A. file:///C:/Program%20Files/OpenOffice.org_2.4_SDK/examples/examples.html (comes with the SDK)
http://www.oooforum.org/forum/viewtopic.phtml?p=94970
Q. How do I build the examples?
A. e.g., for WriterDemo (C:\Program Files\OpenOffice.org_2.4_SDK\examples\CLI\VB.NET\WriterDemo)
Add references to everything in here: C:\Program Files\OpenOffice.org 2.4\program\assembly
That is cli_basetypes, cli_cppuhelper, cli_types, cli_ure
Q. Does OO use the same separate data/document file for mail merge?
A. It allows for a range of data sources including csv files
Q. Does OO allow you to merge to all the different types (fax, email, new document printer)?
A. You can merge to a new document, print and email
Q. Can you add custom fields?
A. Yes
Q. How do you create a new document in VB.Net?
A.
Dim xContext As XComponentContext
xContext = Bootstrap.bootstrap()
Dim xFactory As XMultiServiceFactory
xFactory = DirectCast(xContext.getServiceManager(), _
XMultiServiceFactory)
'Create the Desktop
Dim xDesktop As unoidl.com.sun.star.frame.XDesktop
xDesktop = DirectCast(xFactory.createInstance("com.sun.star.frame.Desktop"), _
unoidl.com.sun.star.frame.XDesktop)
'Open a new empty writer document
Dim xComponentLoader As unoidl.com.sun.star.frame.XComponentLoader
xComponentLoader = DirectCast(xDesktop, unoidl.com.sun.star.frame.XComponentLoader)
Dim arProps() As unoidl.com.sun.star.beans.PropertyValue = _
New unoidl.com.sun.star.beans.PropertyValue() {}
Dim xComponent As unoidl.com.sun.star.lang.XComponent
xComponent = xComponentLoader.loadComponentFromURL( _
"private:factory/swriter", "_blank", 0, arProps)
Dim xTextDocument As unoidl.com.sun.star.text.XTextDocument
xTextDocument = DirectCast(xComponent, unoidl.com.sun.star.text.XTextDocument)
Q. How do you save the document?
A.
Dim storer As unoidl.com.sun.star.frame.XStorable = DirectCast(xTextDocument, unoidl.com.sun.star.frame.XStorable)
arProps = New unoidl.com.sun.star.beans.PropertyValue() {}
storer.storeToURL("file:///C:/Users/me/Desktop/OpenOffice Investigation/saved doc.odt", arProps)
Q. How do you Open the document?
A.
Dim xComponent As unoidl.com.sun.star.lang.XComponent
xComponent = xComponentLoader.loadComponentFromURL( _
"file:///C:/Users/me/Desktop/OpenOffice Investigation/saved doc.odt", "_blank", 0, arProps)
Q. How do you initiate a mail merge in VB.Net?
A.
Don't know. This functionality is in the API reference but is missing from the IDL. We may be slightly screwed. Assuming the API was working, it looks like running a merge is fairly simple.
In VBScript:
Set objServiceManager = WScript.CreateObject("com.sun.star.ServiceManager")
'Now set up a new MailMerge using the settings extracted from that doc
Set oMailMerge = objServiceManager.createInstance("com.sun.star.text.MailMerge")
oMailMerge.DocumentURL = "file:///C:/Users/me/Desktop/OpenOffice Investigation/mail merged.odt"
oMailMerge.DataSourceName = "adds"
oMailMerge.CommandType = 0 ' http://api.openoffice.org/docs/common/ref/com/sun/star/text/MailMerge.html#CommandType
oMailMerge.Command = "adds"
oMailMerge.OutputType = 2 ' http://api.openoffice.org/docs/common/ref/com/sun/star/text/MailMerge.html#OutputType
oMailMerge.execute(Array())
In VB.Net (Option Strict Off)
Dim t_OOo As Type
t_OOo = Type.GetTypeFromProgID("com.sun.star.ServiceManager")
Dim objServiceManager As Object
objServiceManager = System.Activator.CreateInstance(t_OOo)
Dim oMailMerge As Object
oMailMerge = t_OOo.InvokeMember("createInstance", _
BindingFlags.InvokeMethod, Nothing, _
objServiceManager, New [Object]() {"com.sun.star.text.MailMerge"})
'Now set up a new MailMerge using the settings extracted from that doc
oMailMerge.DocumentURL = "file:///C:/Users/me/Desktop/OpenOffice Investigation/mail merged.odt"
oMailMerge.DataSourceName = "adds"
oMailMerge.CommandType = 0 ' http://api.openoffice.org/docs/common/ref/com/sun/star/text/MailMerge.html#CommandType
oMailMerge.Command = "adds"
oMailMerge.OutputType = 2 ' http://api.openoffice.org/docs/common/ref/com/sun/star/text/MailMerge.html#OutputType
oMailMerge.execute(New [Object]() {})
The same thing but with Option Strict On (doesn't work)
Dim t_OOo As Type
t_OOo = Type.GetTypeFromProgID("com.sun.star.ServiceManager")
Dim objServiceManager As Object
objServiceManager = System.Activator.CreateInstance(t_OOo)
Dim oMailMerge As Object
oMailMerge = t_OOo.InvokeMember("createInstance", _
BindingFlags.InvokeMethod, Nothing, _
objServiceManager, New [Object]() {"com.sun.star.text.MailMerge"})
'Now set up a new MailMerge using the settings extracted from that doc
oMailMerge.GetType().InvokeMember("DocumentURL", BindingFlags.SetProperty, Nothing, oMailMerge, New [Object]() {"file:///C:/Users/me/Desktop/OpenOffice Investigation/mail merged.odt"})
oMailMerge.GetType().InvokeMember("DataSourceName", BindingFlags.SetProperty, Nothing, oMailMerge, New [Object]() {"adds"})
oMailMerge.GetType().InvokeMember("CommandType", BindingFlags.SetProperty, Nothing, oMailMerge, New [Object]() {0})
oMailMerge.GetType().InvokeMember("Command", BindingFlags.SetProperty, Nothing, oMailMerge, New [Object]() {"adds"})
oMailMerge.GetType().InvokeMember("OutputType", BindingFlags.SetProperty, Nothing, oMailMerge, New [Object]() {2})
oMailMerge.GetType().InvokeMember("Execute", BindingFlags.InvokeMethod Or BindingFlags.IgnoreReturn, Nothing, oMailMerge, New [Object]() {}) ' this line fails with a type mismatch error

You should take a look at Apache OpenOffice API. A project for creating an API for Open Office. A few languages they said to support are: C++, Java, Python, CLI, StarBasic, JavaScript and OLE.
Java Example of a mailmerge in OpenOffice.

Related

Remove Web Element from WebPage With Selenium

Starting say that i know it's a bad practice to remove WebElement from a WebPage.
For testing purpose, i want understand if i can 'modify' the web page i load 'in local (so client side)' on my webBrowser, using Selenium automation.
In this example, i want to load the 'Google' main page, and try to remove the 'Google' title, from my webBrowser.
I tried using JavaScriptExecutor, but fail.
Here is the code.
Dim driver As IWebDriver
Dim ChromeOptions As New ChromeOptions
Dim driverWait_5 As Support.UI.WebDriverWait
Dim jsExec As OpenQA.Selenium.IJavaScriptExecutor
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
driver = New ChromeDriver("C:\ChromeDriver", ChromeOptions)
driverWait_5 = New Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(5))
jsExec = CType(driver, OpenQA.Selenium.IJavaScriptExecutor)
Dim address As String = "https://www.google.co.uk/webhp"
driver.Navigate.GoToUrl(address)
Dim element As IWebElement = driverWait_5.Until(ExpectedConditions.ElementIsVisible(By.Id("lga")))
If IsNothing(element) = False Then
jsExec.ExecuteScript("document.getElementById('lga').remove();")
End If
End Sub
Any help?
Updated, after help of #Infern0 and #ali, i updated the code, that now works.
Thanks all.
I'm not very familiar with Vb.Net syntax but the C# version below should work;
private void RemoveGoogleLogo()
{
var driver = new ChromeDriver(#"<<chromePath>>")
{
Url = "https://www.google.co.uk/webhp"
};
driver.Navigate();
var driverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
driverWait.Until(x => x.FindElement(By.Id("lga")).Displayed);
driver.ExecuteScript("document.getElementById('lga').remove();");
}

Use vb.net dll in C#. How to acces the objects in C# form from vb.net dll?

I cant completly converted the vb.net code to c# code so i decided to make a vb.net dll and then add it to c# form.
But im new about this dll things and i dont know how to acces the objects in C# form. I added C# application to references in dll as i did for the dll too. But i cant still access the timer and 2 labels which are in C# application.
This is my vb.net dll
Public Class Class1
Public Sub Bypass(block1 As String, block2 As String, ok1 As String, ok2 As String)
Try
Dim folderPath As String = Environment.GetFolderPath(SpecialFolder.Windows)
FileSystem.FileClose(New Integer() {1})
FileSystem.FileClose(New Integer() {2})
If My.Computer.FileSystem.FileExists((folderPath & "\xspirit.sys")) Then
FileSystem.FileOpen(1, (folderPath & "\xspirit.sys"), OpenMode.Append, OpenAccess.ReadWrite, OpenShare.LockReadWrite, -1)
Else
File.WriteAllBytes((folderPath & "\xspirit.sys"), New Byte() {0})
FileSystem.FileOpen(1, (folderPath & "\xspirit.sys"), OpenMode.Append, OpenAccess.ReadWrite, OpenShare.LockReadWrite, -1)
block1 = "Erişim Engellendi"
MsgBox("Erişim Engellendi xspirit")
End If
If My.Computer.FileSystem.FileExists((folderPath & "\xhunter1.sys")) Then
FileSystem.FileOpen(2, (folderPath & "\xhunter1.sys"), OpenMode.Append, OpenAccess.ReadWrite, OpenShare.LockReadWrite, -1)
Else
File.WriteAllBytes((folderPath & "\xhunter1.sys"), New Byte() {0})
FileSystem.FileOpen(2, (folderPath & "\xhunter1.sys"), OpenMode.Append, OpenAccess.ReadWrite, OpenShare.LockReadWrite, -1)
block2 = "Erişim Engellendi"
MsgBox("Erişim Engellendi xhunter1")
End If
Catch exception1 As Exception
ProjectData.SetProjectError(exception1)
Dim ex As Exception = exception1
ProjectData.SetProjectError(ex)
Dim exception As Exception = ex
ProjectData.ClearProjectError()
ProjectData.ClearProjectError()
End Try
Dim p As Process()
p = Process.GetProcessesByName("Wolfteam.bin") 'set wolfteam process
If p.Count = 1 Then ' if wolfteam process detected
ok1 = "XignCode Clear Başarılı"
ok2 = "XignCode Clear Başarılı"
MsgBox("XignCode Clear Başarılı xspirit")
MsgBox("XignCode Clear Başarılı xhunter1")
End If
End Sub
End Class
I tried to convert C# but i cant do it completely so i tried to access the objects from my dll with this code but i couldn't do it (Yes i added it to references).
C#app.Form1(its okay until here but i cant continue this code.It doesn't accept the rest of it)
I wanted to write this actually:
C#app.Form1.Timer1.Enabled = False or C#app.Form1.label1.Text = "test"
I tried too:
Dim test1 As String="test"
'then acces them from C# and then:
vbnetdll.Class1 tt = new vbnetdll.Class1();
label1.Text=f.vbmethod.test1;
But i couldn't do this to. Because it doesn't accept. What is wrong?
By default when you add an item to a form it is declared as a private field in the form's class, like this:
private System.Windows.Forms.Label label1;
So it's not going to accessible from another assembly that references the form. It actually has nothing to do with C# vs vb.net.

VMWare Vim, Getting PortWorldWideName property using c# or vb.net

I try to enumerate all hosts, vm's and storage-adapters in my vCenter-infrastructure by using the vmware.vim-library in vb.net.
But I cannot find a way to get the WWN from the HBA...in powershell there is a property called 'portworldwidename' but this is not available using .net.
foreach($hba in $esx.Config.StorageDevice.HostBusAdapter){
if($hba.GetType().Name -eq "HostFibreChannelHba"){
$wwn = $hba.PortWorldWideName
$wwnhex = "{0:x}" -f $wwn
Write-Host $wwnhex
}
}
This is what I have in vb.net:
Dim c As New VimClient
c.Connect("https://myvcenter/sdk")
c.Login("username", "password")
Dim vmsHosts = c.FindEntityViews(GetType(HostSystem), Nothing, Nothing, Nothing)
For Each evbHostSystem In vmsHosts
Dim hs = CType(evbHostSystem, HostSystem)
Console.WriteLine(hs.Name)
Dim hbas = hs.Config.StorageDevice.HostBusAdapter
For Each hba In hbas
Console.WriteLine(hba.Model)
'hba.portworldwidename is not available...
Next
Next
Thanks for any help!
Regards,
Jan
Found it:
You need to get the type of the returning HBA-object. If it's "HostFibreChannelHba" you need to cast it an 'HostFibreChannelHba'. Then, all properties are available.
Need to take a deeper look at the VI API-Guide :)
Dim hbas = hs.Config.StorageDevice.HostBusAdapter
For Each hba In hbas
Console.WriteLine(hba.Model)
If hba.GetType.Name.Equals("HostFibreChannelHba") Then
Dim fibreHBA = CType(hba, HostFibreChannelHba)
Console.WriteLine(String.Format("{0:x}", fibreHBA.PortWorldWideName))
End If
Next
Regards,
Jan

How can I create a custom sortable field in Outlook populated by a formula?

Having successfully created a custom field in Outlook via a formula and parsing the Subject field; I have now hit a new snag. The custom field is not sortable. It appears as of current that the only way to achieve this is to create a new user property which would then be sortable and could be leveraged when defining the field.
The option also exists to push everything into either a VBA script or C# app using the interop. Either way would work for me however I would prefer to go the VBA route and keep it self contained.
The emails exist in a folder and can be ran after the fact; the solution does not need to remain constantly active.
If anyone could point me to code which can easily achieve this that would be great. If I am missing an option to make the custom field sortable then please provide the alternative as that is the end goal.
EDIT:
This is what I currently have...
Sub SortCustomField()
Dim olApp As Outlook.Application
Dim objLotusInbox As Outlook.MAPIFolder
Dim objLotusInboxItems As Outlook.Items
Dim objNameSpace As Outlook.NameSpace
Dim objProperty As Outlook.UserDefinedProperty
Set olApp = CreateObject("Outlook.Application")
Set objNameSpace = olApp.GetNamespace("MAPI")
Set objLotusInbox = objNameSpace.GetDefaultFolder(olFolderInbox).Folders("Lotus Notes Inbox")
Set objLotusInboxItems = objLotusInbox.Items
objLotusInboxItems.Sort "[Notes2Outlook Created]", False
Set objLotusInboxItems = Nothing
Set objLotusInbox = Nothing
Set objNameSpace = Nothing
Set olApp = Nothing
End Sub
Erroring out at the sort; pretty certain it is due to the fact that the stated field is a user defined field as it works on other fields such as From.
UPDATE:
Made some ground, however when going back to Outlook it does not appear to populate the field defined during the run.
Dim olApp As Outlook.Application
Dim objLotusInbox As Outlook.MAPIFolder
Dim objLotusInboxItems As Outlook.Items
Dim objNameSpace As Outlook.NameSpace
Dim objMailProperty As Outlook.UserProperty
Dim objMailItem As Outlook.MailItem
Dim objParsedDate As Date
Dim sample As Object
Set olApp = CreateObject("Outlook.Application")
Set objNameSpace = olApp.GetNamespace("MAPI")
Set objLotusInbox = objNameSpace.GetDefaultFolder(olFolderInbox).Folders("Lotus Notes Inbox")
Set objLotusInboxItems = objLotusInbox.Items
For Each objMailItem In objLotusInboxItems
Set objMailProperty = objMailItem.UserProperties.Add("MyUserProp", olDateTime)
objParsedDate = CDate(Mid(objMailItem.Subject, (InStr(objMailItem.Subject, "[") + 1), (InStr(objMailItem.Subject, "]") - InStr(objMailItem.Subject, "[")) - 1))
objMailProperty.Value = objParsedDate
Next
Set objLotusInboxItems = Nothing
Set objLotusInbox = Nothing
Set objNameSpace = Nothing
Set olApp = Nothing
I was having the same problem using c# and Add-in-express VSTO addin.
I solved it by saving the MailItem object after I has made the property change.
So for your code I would do the following:objMailItem.Save at the pertinent point. Namely at the end of each iteration of the For loop.
NB: In my c# code I use Marshal.ReleaseComObject for the USerProperty assigned object.
Since you are populating it in the VBA already you should be able to change the User-Property to a text field which can be sorted.
The method I use is running a script based on a rule but in your case you can call it as a sub in the for-each loop.
Sub SomeAction(Item As Outlook.MailItem)
Dim myProperty As Outlook.UserProperty
Set myProperty = Item.UserProperties.Add("MyUserProp", olText, True)
myProperty.Value = Mid(objMailItem.Subject, (InStr(objMailItem.Subject, "[") + 1), (InStr(objMailItem.Subject, "]") - InStr(objMailItem.Subject, "[")) - 1))
Item.Save
Set myProperty = Nothing
End Sub
Only thing left to do is add a user defined column in your view which is a Text based user defined field.
note, since you are using a Date/Time item, this method should work just as well when you define the UserProperty as olDateTime
I've combined the answers from above to add a user defined column which is populated by running a rule selecting the script. I can then sort my inbox by the senders domain. My thanks to the previous contributors.
Public Sub SortByDomain(oMsg As Outlook.MailItem)
On Error Resume Next
Dim sDomain As String 'The Sender's domain
Dim oNS As Outlook.NameSpace 'My namespace
Dim oInbox As Outlook.MAPIFolder 'My Inbox
Dim oTarget As Outlook.MAPIFolder 'The domain folder
Dim myProperty As Outlook.UserProperty
'If it's not your domain, decipher the domain.
If InStr(oMsg.SenderEmailAddress, "mydomain.com") < 1 Then
sDomain = Mid(oMsg.SenderEmailAddress, InStr(oMsg.SenderEmailAddress, "#") + 1)
Else
sDomain = "mydomain.com"
End If
Set myProperty = oMsg.UserProperties.Add("SenderDomain", olText, True)
myProperty.Value = sDomain
oMsg.Save
'Cleanup.
Set oTarget = Nothing
Set oInbox = Nothing
Set oNS = Nothing
Set myProperty = Nothing
End Sub

Are there any Outlook Contacts Controls in ASP.NET?

How can I access Microsoft Outlook contacts using ASP.NET? Are there any controls that can do this?
If by control you mean api, there already is one - Exchange Web Services (EWS). Assuming you are dealing with exchange, and have EWS set up. The web services usually sit at:
https://[yourmaildomain.com]/EWS/Exchange.asmx
Here is some quick code - not production tested (also in vb.net)
Dim esb As New ExchangeServiceBinding()
esb.Credentials = New NetworkCredential("someusername", "somepassword")
esb.Url = "https://[yourmaildomain.com]/EWS/Exchange.asmx"
Dim addressType As New EmailAddressType()
With addressType
.EmailAddress = "email#domain.com"
.MailboxType = MailboxTypeType.Mailbox
.MailboxTypeSpecified = True
End With
' properties
Dim itemProperties As New ItemResponseShapeType()
itemProperties.BaseShape = DefaultShapeNamesType.AllProperties
' Identify which folders to search to find items.
Dim folderIDs(0) As DistinguishedFolderIdType
folderIDs(0) = New DistinguishedFolderIdType()
folderIDs(0).Id = DistinguishedFolderIdNameType.contacts
folderIDs(0).Mailbox = addressType
Dim findItemRequest As New FindItemType()
findItemRequest.Traversal = ItemQueryTraversalType.Shallow
findItemRequest.ItemShape = itemProperties
findItemRequest.ParentFolderIds = folderIDs
' send request
Dim findItemResponse As FindItemResponseType = esb.FindItem(findItemRequest)
Dim rmta As ResponseMessageType() = findItemResponse.ResponseMessages.Items
For Each rmt As ResponseMessageType In rmta
If rmt.ResponseClass = ResponseClassType.Success Then
Dim firmt As FindItemResponseMessageType = CType(rmt, FindItemResponseMessageType)
If firmt IsNot Nothing Then
Dim root As FindItemParentType = firmt.RootFolder
Dim obj As Object = root.Item
If TypeOf obj Is ArrayOfRealItemsType Then
Dim items As ArrayOfRealItemsType = DirectCast(obj, ArrayOfRealItemsType)
If items.Items IsNot Nothing Then
For Each it As ItemType In items.Items
If TypeOf it Is ContactItemType Then
Dim cit As ContactItemType = DirectCast(it, ContactItemType)
Response.Write("<p>")
Response.Write(cit.Subject)
Response.Write("<p>")
End If
Next
End If
End If
End If
End If
Next
FROM Microsoft Support:
How to use the Microsoft Outlook Object Library to retrieve a contact by using Visual C#
MSDN:
Outlook Object Model Overview
How to: Access Outlook Contacts (Some more nice how to's at the end)
You would need to create an ActiveX Application that the client would install to allow you access to this. Unless it's an internal development project, don't expect people to install something that gives you access to their email program.

Categories