Problem with MailMerge with Office 2003

P

Peri

I'm using MailMerge from C#. It works fine on all Word versions except
2003. I don't add reference to Word dll file
instead I use late binding. High level code looks like this.

word = new TWord();
word.Open(templateFile);
word.MailMerge(datasourceFile);
word.CloseDocument(); // close template document
word.Show();


The problem occurs after word.MailMerge(datasourceFile) call.

public void MailMerge(string datasourceFile)
{
object datasource = null;
object mailMerge = null;
object activeDocument = null;
try
{
activeDocument = getActiveDocument();
mailMerge = getPropertyObject(activeDocument, "MailMerge");
datasource = getPropertyObject(mailMerge, "Datasource");

// values here I got from macro registered whilie doing this in Word

// error occurs on any of this 3 calls
setPropertyValue(mailMerge, "Destination", new object[] { 0 });
setPropertyValue(datasource, "FirstRecord", new object[] { 1 });
setPropertyValue(datasource, "LastRecord", new object[] { -16 });

InvokeMethod(mailMerge, "OpenDatasource", new object[] { datasourceFile,
0 });
InvokeMethod(mailMerge, "Execute", null);
}
finally
{
ComHelper.ReleaseComObject(activeDocument);
ComHelper.ReleaseComObject(datasource);
ComHelper.ReleaseComObject(mailMerge);
}
}

I think the code speaks for itself. getPropertyObject, setPropertyValue
and InvokeMethod are just shorcuts for InvokeMember.

protected object getPropertyObject(object parentObject, string
propertyName)
{
return g_type.InvokeMember(propertyName,
BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance,
null,
parentObject,
null);
}

protected void setPropertyValue(object objectContaining, string
propertyName, object[] value)
{
g_type.InvokeMember(propertyName,
BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance,
null,
objectContaining,
value);
}

protected object InvokeMethod(object objectWithMethod, string methodName,
object[] parameters)
{
return g_type.InvokeMember(methodName,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
null,
objectWithMethod,
parameters);
}

I recorded Macro in Office 2003 and it looks that it does exactly the same
I'm doing here. I have no idea what
to do. Anyone has any ideas?
 
P

Peri

And the exception I catch is

Exception type: System.Reflection.TargetInvocationException
Exception message: Exception has been thrown by the target of an
invocation.

with InnerException
Exception type: System.Runtime.InteropServices.COMException
Exception message: ¯±dany obiekt jest niedostêpny.
(message in English is somthing like: Requested object is unavailable)
 
P

Peri

When I changed order of calls in MailMerge method from

setPropertyValue(mailMerge, "Destination", new object[] { 0 });
setPropertyValue(datasource, "FirstRecord", new object[] { 1 });
setPropertyValue(datasource, "LastRecord", new object[] { -16 });

InvokeMethod(mailMerge, "OpenDatasource", new object[] { datasourceFile,
0 });
InvokeMethod(mailMerge, "Execute", null);

to

InvokeMethod(mailMerge, "OpenDatasource", new object[] { datasourceFile,
0 }); <-- this moved
setPropertyValue(mailMerge, "Destination", new object[] { 0 });
setPropertyValue(datasource, "FirstRecord", new object[] { 1 });
setPropertyValue(datasource, "LastRecord", new object[] { -16 });

InvokeMethod(mailMerge, "Execute", null);

it fails on last call (Execute) saying that Word cannot complete merge
operation. I can't give You exact message because
I'm not on the machine it fails. But I think I moved a bit. Maybe that
will help You to help me :)
 
C

Cindy M.

Hi Peri,

Something like this is extremely difficult to troubleshoot with late-binding
calls. And almost impossible, at this remove, without knowing what information
you're passing to the OpenDataSource method.

Just looking at your code, I'd say you should connect the data source
(OpenDataSource) *before* you try to set the mail merge properties. If you
don't specify the document is a mail merge document, none of the three
properties you're invoking are available.

You specify a document as a mail merge document either by connecting the data
source (Word does it for you), or by setting MailMerge.MainDocumentType to
something other than a normal Word document.
I'm using MailMerge from C#. It works fine on all Word versions except
2003. I don't add reference to Word dll file
instead I use late binding. High level code looks like this.

word = new TWord();
word.Open(templateFile);
word.MailMerge(datasourceFile);
word.CloseDocument(); // close template document
word.Show();


The problem occurs after word.MailMerge(datasourceFile) call.

public void MailMerge(string datasourceFile)
{
object datasource = null;
object mailMerge = null;
object activeDocument = null;
try
{
activeDocument = getActiveDocument();
mailMerge = getPropertyObject(activeDocument, "MailMerge");
datasource = getPropertyObject(mailMerge, "Datasource");

// values here I got from macro registered whilie doing this in Word

// error occurs on any of this 3 calls
setPropertyValue(mailMerge, "Destination", new object[] { 0 });
setPropertyValue(datasource, "FirstRecord", new object[] { 1 });
setPropertyValue(datasource, "LastRecord", new object[] { -16 });

InvokeMethod(mailMerge, "OpenDatasource", new object[] { datasourceFile,
0 });
InvokeMethod(mailMerge, "Execute", null);
}
finally
{
ComHelper.ReleaseComObject(activeDocument);
ComHelper.ReleaseComObject(datasource);
ComHelper.ReleaseComObject(mailMerge);
}
}

I think the code speaks for itself. getPropertyObject, setPropertyValue
and InvokeMethod are just shorcuts for InvokeMember.

protected object getPropertyObject(object parentObject, string
propertyName)
{
return g type.InvokeMember(propertyName,
BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance,
null,
parentObject,
null);
}

protected void setPropertyValue(object objectContaining, string
propertyName, object[] value)
{
g type.InvokeMember(propertyName,
BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance,
null,
objectContaining,
value);
}

protected object InvokeMethod(object objectWithMethod, string methodName,
object[] parameters)
{
return g type.InvokeMember(methodName,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
null,
objectWithMethod,
parameters);
}

I recorded Macro in Office 2003 and it looks that it does exactly the same
I'm doing here. I have no idea what
to do. Anyone has any ideas?

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 17 2005)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any follow question or reply
in the newsgroup and not by e-mail :)
 
J

Johnny E Jensen

Hi Peri

I just succeeded with a project like that. I found out that the datasource
file must have atleast 2 rows. - so perhaps?
public void CreateTemplate(string name, string datasource, string
MergeDataHeader, string UserFolder)

{

object objName = UserFolder + "\\" + name + ".dot";

_strDocumentFileName = objName.ToString();

object objFormat = Word.WdOpenFormat.wdOpenFormatAuto;

object objType = Word.WdDocumentType.wdTypeTemplate;

object objFileFormat = Word.WdSaveFormat.wdFormatTemplate;

_objApplication.Visible = true;

_objApplication.ScreenUpdating = false;

Word.Document objDocument = (Word.Document)_objApplication.Documents.Add(ref
_objMissing, ref _objTrue, ref _objMissing, ref _objMissing);


objDocument.MailMerge.OpenDataSource(datasource, ref objFormat, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing);

objDocument.SaveAs(ref objName, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing);

objDocument.MailMerge.EditMainDocument();

_objApplication.ScreenUpdating = true;

_objApplication.Activate();

}
 
P

Peri

Hi Peri

I just succeeded with a project like that. I found out that the
datasource
file must have atleast 2 rows. - so perhaps?
public void CreateTemplate(string name, string datasource, string
MergeDataHeader, string UserFolder)

{

object objName = UserFolder + "\\" + name + ".dot";

_strDocumentFileName = objName.ToString();

object objFormat = Word.WdOpenFormat.wdOpenFormatAuto;

object objType = Word.WdDocumentType.wdTypeTemplate;

object objFileFormat = Word.WdSaveFormat.wdFormatTemplate;

_objApplication.Visible = true;

_objApplication.ScreenUpdating = false;

Word.Document objDocument =
(Word.Document)_objApplication.Documents.Add(ref
_objMissing, ref _objTrue, ref _objMissing, ref _objMissing);


objDocument.MailMerge.OpenDataSource(datasource, ref objFormat, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing);

objDocument.SaveAs(ref objName, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing, ref _objMissing, ref _objMissing, ref _objMissing, ref
_objMissing);

objDocument.MailMerge.EditMainDocument();

_objApplication.ScreenUpdating = true;

_objApplication.Activate();

}

But where do you open the template file? If I understand the code u add
new document, and than just open datasource, and than save it. When I try
to do same in Word I get no results.

What I try is to open prepared template. Then open datasource, and then
merge. I fail on the merge part. My code is old VB code translated to
..NET. To me it looks the same but it doesn't work same, because old VB
code is still working with Word 2003 and my .NET code does not.

One more day and I will start to think how to use old VB code in my .NET
app :(
 
P

Peri

This is the VB code that works with all Office versions. I tried to
translate it to C#. It works with all Word versions but
2003 :(

With Documents(LayDoc).MailMerge
.OpenDataSource DataSourcePath, wdOpenFormatAuto
.Destination = wdSendToNewDocument
.DataSource.FirstRecord = 1
.DataSource.LastRecord = 10000

.Execute
End With

This code is very simple and as You can see I do the same in my code. I
don't know what's going on. I'm starting to think
how to use this code in my app or rewriting my code i VB.NET. I heard
VB.NET supports late binding better than C# and
I won't have to use those ugly InvokeMembers. Tham I guess I will be able
to translate this easier.
 
C

Cindy M.

Hi Peri,
InvokeMethod(mailMerge, "Execute", null);

it fails on last call (Execute) saying that Word cannot complete merge
operation. I can't give You exact message because
I'm not on the machine it fails. But I think I moved a bit. Maybe that
will help You to help me :)
And if you stop your code right before this line. Then go to the Word
application and work with the document like an end-user: can you execute
the merge there? That will tell us whether the problem is your code, or in
the document.

Can you see whether the data source is connected correctly (can you page
through the records)?

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 17 2005)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any follow question or
reply in the newsgroup and not by e-mail :)
 
P

Peri

And if you stop your code right before this line. Then go to the Word
application and work with the document like an end-user: can you execute
the merge there? That will tell us whether the problem is your code, or
in
the document.

Can you see whether the data source is connected correctly (can you page
through the records)?

I did it. I also added MailMerge task pane so I See what happens.

When I break on call to MailMerge.Execute in my code I see in Word that
template document is loaded and
all button on MailMerge task pane are active so it looks like datasource
is loaded ok. But when I press
button to MailMerge to new file I get error window telling me that Word
can't find datasource file and
shows the filename it can't find. And that datasurce file is different
then I specified with call to
MailMerge.OpenDatasource! But it is a filename where earlier datasource
files where generated to. So it looks
like this template "remembers" where datasource file should be. But only
when I try to MailMerge from C#.

On this error window I see two buttons. "Find datasource file" and
"Options" (I have Polish version so I translate.
You may have different captions). When I find the datasource after
clicking first button MailMerge is ok. When
I click Options and on window that appears I click "Remove datasource
information" and than save the template file
all works perfectly next time I try to MailMerge from C# code. I also
tried the same template document with
Word 2000 and it works to.

Does it tell You anything? I'm not the one that created the templates.
They were created long time ago
and I just have to make it work in .NET version of our application. One of
friends said that they may have added
some datasource information to the templates but he isn't sure because he
also isn't the one that created them.
Person that could help me is on a vacation and I won't see her this year.
 
C

Cindy M.

Hi Peri,

Yes, I recall having seen people complain about this problem before (word
remembering the previous data source, rather than a new one).

I suggest you try resetting the document to remove the data source, then
connect the data source.

You do this by setting the MainDocumentType property to wdNotAMergeDocument.
I did it. I also added MailMerge task pane so I See what happens.

When I break on call to MailMerge.Execute in my code I see in Word that
template document is loaded and
all button on MailMerge task pane are active so it looks like datasource
is loaded ok. But when I press
button to MailMerge to new file I get error window telling me that Word
can't find datasource file and
shows the filename it can't find. And that datasurce file is different
then I specified with call to
MailMerge.OpenDatasource! But it is a filename where earlier datasource
files where generated to. So it looks
like this template "remembers" where datasource file should be. But only
when I try to MailMerge from C#.

On this error window I see two buttons. "Find datasource file" and
"Options" (I have Polish version so I translate.
You may have different captions). When I find the datasource after
clicking first button MailMerge is ok. When
I click Options and on window that appears I click "Remove datasource
information" and than save the template file
all works perfectly next time I try to MailMerge from C# code. I also
tried the same template document with
Word 2000 and it works to.

Does it tell You anything? I'm not the one that created the templates.
They were created long time ago
and I just have to make it work in .NET version of our application. One of
friends said that they may have added
some datasource information to the templates but he isn't sure because he
also isn't the one that created them.
Person that could help me is on a vacation and I won't see her this year.

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 17 2005)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any follow question or
reply in the newsgroup and not by e-mail :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top