2

I have a little program that opens a word document, does some changes on a table, exports it to PDF, and then closes the document and application. When I open the document again it still has my original changes in the table. It looks like it is being cached in some kind of way. Here is my code:

private void Open()
{
    appWord = new Microsoft.Office.Interop.Word.Application();
    appWord.DisplayAlerts = WdAlertLevel.wdAlertsNone;
    string path = Environment.CurrentDirectory + "\\Resources\\document1.docx";
    wordDocument = appWord.Documents.Open(path);
}      

Remove some rows from some tables and export to PDF

private void Close()
{
    object missing = Type.Missing;
    object doNotSaveChanges = WdSaveOptions.wdDoNotSaveChanges;
    wordDocument.Close(doNotSaveChanges, missing, missing);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(wordDocument);
    appWord.Quit(ref doNotSaveChanges, ref missing, ref missing);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(appWord);
}

Am I closing the document in a wrong way? Or is it being cached? Some temp file that is saved somewhere? I don't have any other word processes open.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Joost Pielage
  • 137
  • 2
  • 9
  • You didn't show the code doing the modification. Is there anywhere in there a `wordDocument.Save()` call? How about the original file? Is its last modified date changed? And can you clarify the title? Is the document actually closed (check with task manager/Process Explorer for running Word processes) or is it that your changes are unexpectedly saved? – Dirk Vollmar Jun 15 '16 at 08:43
  • @JoostPielage: btw, when automating Word you usually don't have to explicitly release the document and application objects. – Dirk Vollmar Jun 15 '16 at 08:45
  • 1
    If it turns out that the PDF export saves your document for whatever reason, a very simple solution is to create a temporary copy of your source document before opening it in Word. – Dirk Vollmar Jun 15 '16 at 11:13
  • So when you end your application, are there any open Word instances? If not, please adjust the question title, as it does not match your question then. – Thorsten Dittmar Jun 15 '16 at 13:17
  • 1
    You state: "So I don't want the changes to be saved. After I exported to PDF the document can be closed and not be saved. This way I can reuse the document for the same function." In that case, save this document *as a template* (dotx file) then use `Documents.Add` instead of `Documents.Open` to create a new document. You can be sure that the original will not be changed. Close the new document without saving. – Cindy Meister Jun 15 '16 at 19:10
  • Based soley on your description, Word should not be saving any changes you make. But since you don't provide the full code, nor tell us which version of Word is involved, it's not possible to say for sure exactly what's going on. If you want someone to address the underlying problem you need to provide full information. Use the [edit] link below the question to provide it, please. – Cindy Meister Jun 15 '16 at 19:11

3 Answers3

1

The changes are not saved because when you are closing the doc, your are telling it not to save changes.

object doNotSaveChanges = WdSaveOptions.wdDoNotSaveChanges;
wordDocument.Close(doNotSaveChanges, missing, missing);

Try this instead:

object saveChanges = WdSaveOptions.wdSaveChanges;
wordDocument.Close(saveChanges, missing, missing);
  • So I don't want the changes to be saved. After I exported to PDF the document can be closed and not be saved. This way I can reuse the document for the same function. What I am saing is that I open the doc with a table of 20 rows. I remove 5 rows export the doc to pdf. Then close the doc and application. Now if I want to do this again the table still has 15 rows in it and not 20. – Joost Pielage Jun 15 '16 at 09:34
  • 1
    Ok I got your point. Basically you only need to temporarily delete records as long as the doc is open. Can you share your delete code, maybe i can come up with something after seeing it – Abdulraheem Abid Jun 15 '16 at 09:48
  • activeRowInTable = activeRowInTable - 2; int rowsToDelete = 3; Table quotationTable = draftDocument.Tables[quotationTableIndex]; for (int i = 0; i < rowsToDelete; i++) { quotationTable.Rows[activeRowInTable].Delete(); } – Joost Pielage Jun 15 '16 at 09:53
0

We actually use the following (shortened) code when closing a Word document:

object varFalse = false;
object missing = System.Type.Missing;

if (m_wordDoc != null)
{
    ((Microsoft.Office.Interop.Word.Document)m_wordDoc).Close(ref varFalse, ref missing, ref missing);
    //m_wordDoc = null;
}
if (m_wordApp != null)
{
    ((Microsoft.Office.Interop.Word.Application)m_wordApp).Quit(ref varFalse, ref missing, ref missing);
    //m_wordApp = null;
}

You'll notice that we use a bool value for the first parameter. Still, the above code properly closes the document and the Word instance.

However, we create a temporary copy of the template Word file before we do stuff and export it as PDF. It could be that exporting the file as PDF implicitly saves the original, which doesn't matter to us, as we delete the temporary file after the process.

Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139
  • Please note that since C# 4.0 / .NET 4.0 from 2010 this code can be written a lot more compact: `m_wordDoc.Close(false); m_wordApp.Quit(false)`. (And in general, explicitly nulling variables is not required to release the Word COM objects). – Dirk Vollmar Jun 16 '16 at 08:16
  • The fact that I'm setting the variables to `null` is due to the internal workings of the class this code resides in. They are not meant to release anything - the class just needs to determine whether there is a current Word or document instance. I'm going to comment out these lines, as they do not do anything here. – Thorsten Dittmar Jun 16 '16 at 08:25
-1

You may have some unwanted opened instance of your Word in your Task Manager.

Workink with COM in .Net requires to release com objects. More than that, you cannot use dots when working with word interop (or any other COM object) in .Net since between the dots, temporarly objects are created behind the scene and need to be released.

For example:

wordDocument = appWord.Documents.Open(path);

Should be replaced with

wordDocuments = appWord.Documents
wordDocument = wordDocuments.Open(path);

// Once done, you need to release those objects
System.Runtime.InteropServices.Marshal.ReleaseComObject(wordDocument);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wordDocuments);

You can look at this post, those are the same rules as in excel.

Community
  • 1
  • 1
ehh
  • 3,412
  • 7
  • 43
  • 91
  • 1
    This is not quite true. We're using VSTO with Word and we're not required to call `ReleaseComObject`. Still, the instances of Word are properly closed. – Thorsten Dittmar Jun 15 '16 at 12:54
  • [You don't need `ReleaseComObject`](http://stackoverflow.com/questions/3937181/#3938075), it is bad advice that has been floating around for ages that used to be thought to be good [but nolonger is](https://blogs.msdn.microsoft.com/visualstudio/2010/03/01/marshal-releasecomobject-considered-dangerous/). Just calling `GC.Collect(); GC.WaitForPendingFinalizers();` [in the right spot](http://stackoverflow.com/questions/17130382/understanding-garbage-collection-in-net/17131389#17131389) will do it because in the finalizer of the the COM objects will clean themselves up. – Scott Chamberlain Jun 15 '16 at 13:14
  • There are lot of opinions on if releasing COM objects or not, on if to explicitly call GC.Collect or not. Personally, when I used COM object intensely without releasing, I was facing lot of COM exceptions. Using the practice of releasing, solve all the problems. – ehh Jun 15 '16 at 13:59