wxautomation and ms word bookmarks

This forum can be used to talk about general design strategies, new ideas and questions in general related to wxWidgets. If you feel your questions doesn't fit anywhere, put it here.
Post Reply
IanMac
In need of some credit
In need of some credit
Posts: 2
Joined: Tue Apr 15, 2014 3:36 pm

wxautomation and ms word bookmarks

Post by IanMac »

hello and thanks in advance for any help
I use a customized version of wxwidgets ( 2.8.12) in a package for creating applications that is compatible with a package I have used for the last 15 years called Superbase that you may have heard of

Here are some examples of how the code is written (error handling and variable definition removed)
I realise that it is slightly different but anybody with wxwidget capability should understand real quick.

excel =@ wxautomation1.new(createinstance="excel.application", error=e)
excel.putproperty(property="Visible", error=e, - 1); // Make Excel Visible
workbooks =@ excel.getobject(property="Workbooks", error=e)
workbooks.callmethod(method="Add", error=e); // Open a new workbook
workbook =@ excel.getobject(property="ActiveWorkBook", error=e)
worksheet =@ excel.getobject(property="ActiveSheet", error=e)
// This creates a chart embedded in the current sheet using the Excel default format
rangeselect(excel, "C1:C5", error=e)
selection =@ excel.getobject(property="Selection", error=e)

All of these instructions work fine with Excel. Please note that it is possible to get an object <chart> which is part of the ChartObjects collection.

Things are similar with Word

wo =@ wxautomation1.new(createinstance="word.application", error=e)
wo.putproperty(property="Visible", error=e, - 1); // Make Word Visible
wordfile =@ wo.getobject(property="Documents", error=e)
filename = "c:\test\test.doc"
wordfile.callmethod(method="Open", error=e, filename); // Open the test document
doc =@ wo.getobject(property="ActiveDocument", error=e)
bookmarks =@ doc.getobject(property="Bookmarks", error=e); this adds a bookmark no problem
bookmarks.callmethod(method="Add", error=e, "test4")
bookcount = bookmarks.getproperty(property= "Count", error=e)
if bookcount > 0
exists = bookmarks.callmethod(method="Exists", error=e, "test2"); this gives "true" :all is OK up to here

So I can create a bookmark, count the number of bookmarks in the collection & show that a particular bookmark exits BUT it seems impossible to get a reference to a specific bookmark even though it exists in the Collection

bookmark =@ bookmarks.getobject(property = "Item", error=e, 1, "test2") error but works for chart in Excel
bookmark =@ bookmarks.callmethod(method = "Item", error=e, "test2") error
etc etc

The problem comes when I try to get a reference to a bookmark in the Bookmarks collection
In Excel the following works fine
chartobjects =@ worksheet.getobject(property="ChartObjects", error=e)
chartobjects.callmethod(method="Add", error=e, 50, 90, 270, 150)
chartcount = worksheet.getproperty(property="ChartObjects.Count", error=e)
chart =@ chartobjects.getobject(property="Item", error=e, 1)
so a particuler chart can be addressed directly

With Word this produces an error
bookmarks =@ doc.getobject(property="Bookmarks", error=e) this is OK
bookmarks.callmethod(method="Add", error=e, "test4") this is OK
bookcount = bookmarks.getproperty(property= "Count", error=e) this is OK
bookmark =@ bookmarks.getobject(property = "Item", error=e, "test4") this produces an error

I have tried to emulate the Word problem by modifying a PowerPoint example provided by PB

wxAutomationObject wo;
wo.CreateInstance("Word.Application");
if ( !wo.IsOk() )
{
wxLogError("Failed to obtain Word.Application instance.");
return;
}
wo.SetVisible(true)

wxAutomationObject wordfiles;
wo.GetObject(wordfiles, "Documents");
if ( !wordfile.IsOk() )
{
wxLogError("Failed to obtain Word Documents property instance.");
return;
}
wordfile.CallMethod("Open",1, "c:\test\test.doc");

wxAutomationObject doc;
wo.GetObject(doc, "ActiveDocument");
if ( !doc.IsOk() )
{
wxLogError("Failed to obtain Active Document instance.");
return;
}

wxAutomationObject bookmarks;
doc.GetObject(bookmarks, "Bookmarks");
if ( !bookmarks.IsOk() )
{
wxLogError("Failed to obtain Bookmarks instance.");
return;
}
bookmarks.callMethod("Add",1,"test4");

wxAutomationObject bookmark;
wxVariant vBookmark;
wxVariant params[2];

params[0] = 2; // bookmark no. 2
vBookmark = bookmarks.CallMethod("Item", 1, params);
if ( vBookmark.GetVoidPtr() == NULL )
{
wxLogError("Failed to obtain a bookmark instance.");
return;
}

bookmark.CallMethod("Select");
it would be here than you could put something like
bookmark.CallMethod("TypeText",1, "Whatever I wanted to type in")
I obviously cannot test this code but if I am right there should be a problem with the last part. If it works with wxwidgets then
there is a problem with my package.
Sorry to have been a bit long and thanks
Ian Macpherson
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxautomation and ms word bookmarks

Post by PB »

As I told you before, I think the correct way to obtain an existing item from MSO collection is to use its Item method. I do not know why (some?) collections allow you to get an item using wxAutomationObject::GetObject() call, which obtains a property as an object. Item is documented being a method and not a property and IIRC, obtaining a collection item using wxAutomationObject::CallMethod("Item", index) always worked for me for any collection.

This working C++ code showing how to add a new bookmark from Bookmarks collection and subsequently obtain the first bookmark from the Bookmarks collection, tested with MS Word 2010.

First, set-up MS Word, add an empty document and obtain the Bookmarks interface for ActiveDocument

Code: Select all

wxAutomationObject word;
		word.CreateInstance("Word.Application");
		if ( !word.IsOk() )
		{
			wxLogError("Failed to obtain Word.Application instance.");
			return;
		}
		word.PutProperty("Visible", true);

		wxAutomationObject documents;
		word.GetObject(documents, "Documents");
		if ( !documents.IsOk() )
		{
			wxLogError("Failed to obtain Word.Documents property instance.");
			return;
		}
								
		documents.CallMethod("Add"); // add an empty document
		
		wxAutomationObject doc;
		word.GetObject(doc, "ActiveDocument");
		if ( !doc.IsOk() )
		{
			wxLogError("Failed to obtain Word.ActiveDocument instance.");
			return;
		}

		wxAutomationObject bookmarks;
		doc.GetObject(bookmarks, "Bookmarks");
		if ( !bookmarks.IsOk() )
		{
			wxLogError("Failed to obtain Bookmarks instance.");
			return;
		}
Next, add a new bookmark and obtain its instance. Please observe that a method call using wxAutomationObject::CallMethod() does not return an wxAutomationObject instance but a wxVariant. You have to obtain the interface pointer using wxVariant::GetVoidPtr() method and set the pointer to wxAutomation object using wxAutomation::SetDispatchPtr(). I do not know what would the proper syntax be in the programming language you use.

Code: Select all

wxVariant variant;
		wxAutomationObject bookmark;

		// we can get the newly added bookmark like this
		variant = bookmarks.CallMethod("Add", "Bookmark1");
		if ( !variant.GetVoidPtr() )
		{
			wxLogError("Failed to add a bookmark.");
			return;
		}
		// set the IDispatch pointer from wxVariant to the bookmark object
		bookmark.SetDispatchPtr((IDispatch*)variant.GetVoidPtr());
		variant = bookmark.GetProperty("Name");		
		wxLogDebug("Bookmark was added under name %s", variant.GetString()); // should output "Bookmark was added under name Bookmark1"
And finally, this is how you obtain an individual bookmark, the code demonstrates getting bookmark number 1 (which we added in the code above). The procedure of creating the bookmark instance from wxVariant returned by wxAutomationObject::CallMethod() is pretty much the same as in the code above.

Code: Select all

		variant = bookmarks.CallMethod("Item", 1); // retrieve bookmark #1
		if ( !variant.GetVoidPtr() )
		{
			wxLogError("Failed to obtain bookmark #1.");
			return;
		}
		// set the IDispatch pointer from wxVariant to the bookmark object
		bookmark.SetDispatchPtr((IDispatch*)variant.GetVoidPtr());
		variant = bookmark.GetProperty("Name");		
		wxLogDebug("Bookmark #1 is named %s", variant.GetString()); // should output "Bookmark #1 is named Bookmark1"	
As I know nothing about the programming language/environment you use, I probably won't be able to help you much more, but perhaps the provided C++ code will be enough.
IanMac
In need of some credit
In need of some credit
Posts: 2
Joined: Tue Apr 15, 2014 3:36 pm

Re: wxautomation and ms word bookmarks

Post by IanMac »

May I say many thanks to PB I sent his comments to the guy who wrote the whole SIMPOL thing & he said many thanks also & that it would be necessary to create a new method something like getcollectionobject(string funcname, integer index)
He is currently getting widgets 3.0 to work with Simpol & says it seems to be working mainly as it should & after that he will look into the new method.
So That covers things fine for me & many many thanks
Ian Macpherson
Post Reply