Using Word with C#
-
The form is probably closing because you're not handling the exception like you should be. Users should never see an exception thrown but should see a nice little error message without your app crashing. As far as the
COMException
, I'm betting the problem is where param values should be an empty variant but you're passing a reference tofalse
. This is not the same in the world of COM. Instead, try the following:object empty = Missing.Value;
Anywhere you need to pass an empty argument, pass a
ref
toempty
(or whatever you call it). Also, .NET naming conventions recommend that you don't use the hungarian notation, like putting "C" before a class name. Just consider how all the classes you use in the .NET Base Class Library (BCL) are named, as well as the methods, properties, etc. Using the same conventions is important, because anyone using your library or extending your application - and that's any language that targets the CLR like C#, VB.NET, MC++, COBOL.NET, and many others - should be consistent to avoid confusion and other hastles.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
Thank you for your answer. I agree that user should never see an exception, but I think it is even better to write correct code and avoid the exception, rather than displaying the error message. Exception would be nice if for instance the .dot file doesn't exist, but here it seems to be different. About the empty : the Find.Execute function takes 15 parameters. The VBA help of Word gives me the feeling that none are supposed to be empty, but false. I have tried to use empty with some of these parameters, that are supposed to be facultative, but it changed nothing. So I'm in need of more specific solution. About the naming convention: I usually don't use hungarian notation, except in two cases. First, to differentiate between some parameters (like if I have a member Param, and a parameter Param), or when I'm porting an old C++ code, which is the case here, and I forget to rename a few classes or function.
-
Thank you for your answer. I agree that user should never see an exception, but I think it is even better to write correct code and avoid the exception, rather than displaying the error message. Exception would be nice if for instance the .dot file doesn't exist, but here it seems to be different. About the empty : the Find.Execute function takes 15 parameters. The VBA help of Word gives me the feeling that none are supposed to be empty, but false. I have tried to use empty with some of these parameters, that are supposed to be facultative, but it changed nothing. So I'm in need of more specific solution. About the naming convention: I usually don't use hungarian notation, except in two cases. First, to differentiate between some parameters (like if I have a member Param, and a parameter Param), or when I'm porting an old C++ code, which is the case here, and I forget to rename a few classes or function.
Stephane David wrote: but I think it is even better to write correct code and avoid the exception, rather than displaying the error message. I don't agree, exceptions are meant to happen and be handled, it doesn't necessarily mean they are bad. Since you need to properly handle them and using a MessageBox to the user is typically a good option, when it is pertinent. Some exceptions can be handled internally, however when they are of value to the user, they should be informed. - Nick Parker
My Blog -
Stephane David wrote: but I think it is even better to write correct code and avoid the exception, rather than displaying the error message. I don't agree, exceptions are meant to happen and be handled, it doesn't necessarily mean they are bad. Since you need to properly handle them and using a MessageBox to the user is typically a good option, when it is pertinent. Some exceptions can be handled internally, however when they are of value to the user, they should be informed. - Nick Parker
My BlogThat's what I meant. In that case, the only information I can provide the user with is "this function doesn''t work, and I don't know how to make it work". If the error happens 100% of the time, then is it not an exception, it really is a programming error. It doesn't prevent me from handling the exception, but it is not a solution to my problem.
-
Thank you for your answer. I agree that user should never see an exception, but I think it is even better to write correct code and avoid the exception, rather than displaying the error message. Exception would be nice if for instance the .dot file doesn't exist, but here it seems to be different. About the empty : the Find.Execute function takes 15 parameters. The VBA help of Word gives me the feeling that none are supposed to be empty, but false. I have tried to use empty with some of these parameters, that are supposed to be facultative, but it changed nothing. So I'm in need of more specific solution. About the naming convention: I usually don't use hungarian notation, except in two cases. First, to differentiate between some parameters (like if I have a member Param, and a parameter Param), or when I'm porting an old C++ code, which is the case here, and I forget to rename a few classes or function.
Stephane David wrote: I agree that user should never see an exception, but I think it is even better to write correct code and avoid the exception, rather than displaying the error message. This is a bad assumption! Did you write Microsoft Word? I'm betting you didn't, so why trust the work of other people whom you probably don't know, and code in another application where a whole different set of problems exist? Never do. Never trust user input, and never trust another application. Always account for problems that might occur. Do you think that Word blindly accepts input from calling functions? And just because a parameter takes a value of
true
doesn't mean that the converse isfalse
. Look again at the type:Variant
. When a variant isn't specified, it is an empty or missing variant, hence usingMissing.Value
(or sometimes you seeType.Missing). I found this example on MSDN: [How to: search for text in Word documents](http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_wrcore/html/wrtskhowtosearchfortextinworddocuments.asp)[[^](http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_wrcore/html/wrtskhowtosearchfortextinworddocuments.asp "New Window")]. They use `Type.Missing` to find text. You have the right values for the `ReplaceWith` and `Replace` parameters. Also, you can search over the whole document (since in the example they set the range to the first two paragraphs) by using `Document.Content` instead of `Application.Selection.Range`, which - if I remember correctly - is an empty range anyway. I don't know about that, though - it's been a while since I programmed with the Office libraries. In any case, `Document.Content` is a `Range` over the whole document, which seems to be what you wanted anyway. Good luck! -----BEGIN GEEK CODE BLOCK----- [Version: 3.21](http://www.geekcode.com/geek.html) GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
Stephane David wrote: I agree that user should never see an exception, but I think it is even better to write correct code and avoid the exception, rather than displaying the error message. This is a bad assumption! Did you write Microsoft Word? I'm betting you didn't, so why trust the work of other people whom you probably don't know, and code in another application where a whole different set of problems exist? Never do. Never trust user input, and never trust another application. Always account for problems that might occur. Do you think that Word blindly accepts input from calling functions? And just because a parameter takes a value of
true
doesn't mean that the converse isfalse
. Look again at the type:Variant
. When a variant isn't specified, it is an empty or missing variant, hence usingMissing.Value
(or sometimes you seeType.Missing). I found this example on MSDN: [How to: search for text in Word documents](http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_wrcore/html/wrtskhowtosearchfortextinworddocuments.asp)[[^](http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_wrcore/html/wrtskhowtosearchfortextinworddocuments.asp "New Window")]. They use `Type.Missing` to find text. You have the right values for the `ReplaceWith` and `Replace` parameters. Also, you can search over the whole document (since in the example they set the range to the first two paragraphs) by using `Document.Content` instead of `Application.Selection.Range`, which - if I remember correctly - is an empty range anyway. I don't know about that, though - it's been a while since I programmed with the Office libraries. In any case, `Document.Content` is a `Range` over the whole document, which seems to be what you wanted anyway. Good luck! -----BEGIN GEEK CODE BLOCK----- [Version: 3.21](http://www.geekcode.com/geek.html) GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
Ok... I've tried to use an ActiveDocument.Content. I've tried with Selection. I've tried using Missing.Value with several parameters. Nothing works. I always get the same error... The execption starts to be not very... exceptional... And to close the topic of exception, I never said I don't want to handle an exception. I said I don't know how to correct this one. Right now, my function always raise an exception, so it is useless....
-
Ok... I've tried to use an ActiveDocument.Content. I've tried with Selection. I've tried using Missing.Value with several parameters. Nothing works. I always get the same error... The execption starts to be not very... exceptional... And to close the topic of exception, I never said I don't want to handle an exception. I said I don't know how to correct this one. Right now, my function always raise an exception, so it is useless....
Like I mentioned in the message you replied to, try
Type.Missing
instead ofMissing.Value
. This is what was given in the article I linked for you.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
Like I mentioned in the message you replied to, try
Type.Missing
instead ofMissing.Value
. This is what was given in the article I linked for you.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
Arggh!!!! :mad: I'm using this simple exemple directly from the article you linked for me. And it still doesn't work!!! Would there be something else? Like not a simple parameter error, but perhaps a difference if I'm using Office XP or Windows XP? // C# internal void SelectionFind() { string strFind = "find me"; Word.Find fnd = ThisApplication.Selection.Find; fnd.ClearFormatting(); fnd.Text = strFind; object missingValue = Type.Missing; if (fnd.Execute(ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue)) { MessageBox.Show("Text found."); } else { MessageBox.Show("The text could not be located."); } }
-
Arggh!!!! :mad: I'm using this simple exemple directly from the article you linked for me. And it still doesn't work!!! Would there be something else? Like not a simple parameter error, but perhaps a difference if I'm using Office XP or Windows XP? // C# internal void SelectionFind() { string strFind = "find me"; Word.Find fnd = ThisApplication.Selection.Find; fnd.ClearFormatting(); fnd.Text = strFind; object missingValue = Type.Missing; if (fnd.Execute(ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue)) { MessageBox.Show("Text found."); } else { MessageBox.Show("The text could not be located."); } }
Maybe you just typed your code fragment in wrong, but you didn't actually specify anything to find...or replace, for that matter. You're using
ref missingValue
in all ofFind.Execute
's parameters.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
Maybe you just typed your code fragment in wrong, but you didn't actually specify anything to find...or replace, for that matter. You're using
ref missingValue
in all ofFind.Execute
's parameters.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
That was on purpose. As the replace doesn't work, I've tried the very basic, with the simpliest exemple I could find in the library, just find a text. And I still get the exception. In this exemple, they do not use a parameter, but Word.Find.Text instead
-
I've tried to used this article http://www.codeproject.com/csharp/CsAutomateWord.asp?target=Word to create a character sheet. I have a CCharacter class, that contains all information about a character, and I want to generate a MS Word document with these information. So I've created .dot document, with thinks like Name _Name_ Age _Age_ in arrays (I've tried also without the array, directly in the text). _XXX_ is code that I will use for replacement. Now, to the code: // Create a Word application Word.ApplicationClass vk_word_app = new Word.ApplicationClass(); // Open the .dot object FileName =Directory.GetCurrentDirectory()+"\\Models\\Sheet.dot"; Word.Document vk_my_doc = vk_word_app.Documents.Open(... // Create a new document Word.Document vk_new_doc = vk_word_app.Documents.Add((... // Copy the .dot into the new document vk_my_doc.Select(); vk_word_app.Selection.Copy(); vk_new_doc.Select(); vk_word_app.Selection.PasteAndFormat(Word.WdRecoveryType.wdPasteDefault); // close the .dot vk_my_doc.Close( ref vk_false, ref vk_missing, ref vk_missing ); All the previous steps work. I get a new document, build from my template. Now, I'd like to fill it with actual information. So I do this // Select the new doc vk_new_doc.Select(); // Define some variable object vk_false = false; object vk_true = true; object vk_num = Word.WdFindWrap.wdFindStop; object vk_find = "_Nom_"; object vk_replaceWith = Name_Familly; // This one is a member of CCharacter class object vk_replace = Word.WdReplace.wdReplaceOne; // Try to replace the text vk_word_app.Selection.Find.Execute( ref vk_find, ref vk_false, ref vk_false, ref vk_false, ref vk_false, ref vk_false, ref vk_true, ref vk_num, ref vk_false, ref vk_replaceWith, ref vk_replace, ref vk_false, ref vk_false, ref vk_false, ref vk_false ); And... it doesn't work. I got this error: System.Runtime.InteropServices.COMException (0x800706F7): Le relais a reçu des données incorrectes. at Word.Find.Execute(Object& FindText, Object& MatchCase, Object& MatchWholeWord, Object& MatchWildcards, Object& MatchSoundsLike, Object& MatchAllWordForms, Object& Forward, Object& Wrap, Object& Format, Object& ReplaceWith, Object& Replace, Object& MatchKashida, Object& MatchDiacritics, Object& MatchAlefHamza, Object& MatchControl) My form close, the word doc stays opened. "Le relais a reçu des données incorrectes" would translate as "incorrect data received". Any idea of a way to solve this would
After many testing, I've discovered that it didn't work because of my Office XP. I have installed Office 2000 instead, and now it works. Except for one thing. I'd like to replace text which is a TextBox, and not in the body of the document. But Word.Content doesn't include shapes apparently. Anyone with an idea?