First of all I have been programming in C++ for many years. However, it has just been a few weeks that I have attacked automation. Initially for Excel I got a bundle of help from the forum for using wxAutoExcel. Works fine. Now I am trying to control Word. My first task for this is to add a table to Word. On the internet I found the following link which describes the classes, properties and methods for Word Automation.
Microsoft.Office.Interop.Word Namespace | Microsoft Docs
In this documentation, to create a table we use Tables.Add which needs a Range.
Tables.Add(Range, Int32, Int32, Object, Object) Method
Unlike a lot of the other classes there is no Ranges collection class with a Add function to create a Range. So I first got a Bookmark which has a Range Property and used it.
So two questions:
How do you create a Range?
What do you use for the second parameter of the tables.CallMethod("Add", ?????????????, 6, 7); ?
My code is below.
wxAutomationObject application;
application.CreateInstance("Word.Application");
application.PutProperty("DisplayAlerts", false);
application.PutProperty("Visible", true);
wxAutomationObject documents;
application.GetObject(documents, "Documents");
wxVariant docVariant;
docVariant = documents.CallMethod("Add");
wxAutomationObject document((WXIDISPATCH*)docVariant.GetVoidPtr());
document.CallMethod("Activate");
// All good until here. Now I need to get a Range. There is no Range collection so I get a bookmark first which has a Range
wxAutomationObject bookmarks;
document.GetObject(bookmarks, "Bookmarks");
wxVariant variant;
variant = bookmarks.CallMethod("Item", "\\EndOfDoc"); // Get a existing bookmark
wxAutomationObject bookmark((WXIDISPATCH*) variant.GetVoidPtr());
wxAutomationObject range;
bookmark.GetObject(range, "Range");
// OK I have a Range. Now to add a table
wxAutomationObject tables;
document.GetObject(tables, "Tables") ;
wxVariant tableVariant;
wxVariant rangeVariant;
rangeVariant.Clear();
// From above the Tables.Add requires a Range, number of rows and columns and two optional
//parameters. The wxAutomationObject.CallMethod function requires a wxVariant for the second parameter.
// How do I turn a Range into a wxVariant?
tableVariant = tables.CallMethod("Add", ?????????????, 6, 7);
Word Automation using wxAutomation and wxVariant
-
- In need of some credit
- Posts: 7
- Joined: Mon Apr 25, 2022 9:18 am
-
- In need of some credit
- Posts: 7
- Joined: Mon Apr 25, 2022 9:18 am
Re: Word Automation using wxAutomation and wxVariant
I think I just figured out how to add a table by looking at some of the code in wxAutoExcel. This weems to work.
wxVariant rangeVariant;
rangeVariant.Clear();
IDispatch* dispatch = (IDispatch*)range.GetDispatchPtr();
dispatch->AddRef();
rangeVariant = (void*)dispatch;
tableVariant = tables.CallMethod("Add", rangeVariant, 6, 7);
I still would like to find out how to create a Range
wxVariant rangeVariant;
rangeVariant.Clear();
IDispatch* dispatch = (IDispatch*)range.GetDispatchPtr();
dispatch->AddRef();
rangeVariant = (void*)dispatch;
tableVariant = tables.CallMethod("Add", rangeVariant, 6, 7);
I still would like to find out how to create a Range
Re: Word Automation using wxAutomation and wxVariant
Please use the code tags for code, it makes your posts more readable and thus increases changes of getting help.
I recommend using VBA documentation for automating MS Word.
As for the Range object, it depends which one (i.e., where) you want it: https://docs.microsoft.com/en-us/office ... ge-objects
For example, this SSCCE adds a styled table at the beginning of a new document:
There is nothing difficult about using wxAutomationObject. One just needs to learn its API and understand how to convert between wxVariant and wxAutomationObject. The rest is just painful drudgery.
EDIT Simplified the code a bit by removing unused objects.
I recommend using VBA documentation for automating MS Word.
As for the Range object, it depends which one (i.e., where) you want it: https://docs.microsoft.com/en-us/office ... ge-objects
For example, this SSCCE adds a styled table at the beginning of a new document:
Code: Select all
#include <wx/wx.h>
#include <wx/msw/ole/automtn.h>
class MyApp : public wxApp
{
public:
bool OnInit() override
{
wxVariant v;
wxAutomationObject application, document, range, table;
// start word instance and show it
if ( !application.GetInstance("Word.Application") )
{
wxLogError("Could not start Word.");
return false;
}
application.PutProperty("Visible", true);
application.PutProperty("DisplayAlerts", false);
// Add empty document
v = application.CallMethod("Documents.Add");
if ( !v.IsType("void*") )
{
wxLogError("Could not add a new Document.");
return false;
}
document.SetDispatchPtr((IDispatch*)v.GetVoidPtr());
// Obtain a range from first characters in the document
v = document.CallMethod("Range", 0, 1);
if ( !v.IsType("void*") )
{
wxLogError("Could not obtain Range from a Document.");
return false;
}
range.SetDispatchPtr((IDispatch*)v.GetVoidPtr());
// Add table with 5 columns and 15 rows to range
IDispatch* rangeIDispatch = (IDispatch*)range.GetDispatchPtr();
rangeIDispatch->AddRef(); // we need to this because wxAutomationObject::Invoke() decreases the ref count of its parameters
v = (void*)rangeIDispatch;
v = document.CallMethod("Tables.Add", v, 15, 5);
if ( !v.IsType("void*") )
{
wxLogError("Could not add a Table.");
return false;
}
table.SetDispatchPtr((IDispatch*)v.GetVoidPtr());
table.PutProperty("Style", -171); // -171 = wdStyleTableColorfulList
return false;
}
}; wxIMPLEMENT_APP(MyApp);
EDIT Simplified the code a bit by removing unused objects.
Last edited by PB on Wed Aug 03, 2022 9:05 am, edited 1 time in total.
-
- In need of some credit
- Posts: 7
- Joined: Mon Apr 25, 2022 9:18 am
Re: Word Automation using wxAutomation and wxVariant
Once again, thanks PB. I am just now starting to understand how to use wxAutomationObject. In almost all cases I have been able to resolve the problems after what you call hours of drugery. Small things such as changing border styles of a table takes a while of going through. I hope that I do have to bother you too much in the futher.