Search code examples
c#visual-studio-2010ms-word.net-4.0office-interop

Editing Word Doc Programmatically C#


C#, Visual Studio 2010, .NET 4.0

I'm trying to edit a word doc template and searching for specific strings and replacing them with values from my C# program. I've tried using Microsoft.Office.Interop.Word and things work really well, if Office 2003 or greater is installed on the environment. Problem is, the environment I need it to work on is using Word 2000 and upgrading it isn't an option because 2000 is needed for some other programs on that PC.

So I tried opening the template doc in Notepad++, it opens fine, it had a bunch of weird letters and stuff, but I can find/replace my values and save. Then when I open the saved doc, it looks great. Great! So how would I do this with my program? I've tried using the File class and I've tried StreamWriter but both save the files as garbage so when I try to open them with word they ask me for what encoding I am using, and that doesn't seem to work.

Any idea what encoding I need to use? or how does Notepad++ able to edit the doc and save it in the correct format?

    //Using Microsoft Office Interop Word
        private void method0()
        {
            Microsoft.Office.Interop.Word._Document aDoc = null;
            object missing = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Word._Application wordApp = new Microsoft.Office.Interop.Word.Application();

            try
            {
                if (File.Exists("AIO2CertTemplate.doc"))
                {
                    DateTime today = DateTime.Now;

                    object fileName = System.Windows.Forms.Application.StartupPath + "\\AIO2CertTemplate.doc";
                    object saveFileName = textBoxSaveFilePath.Text;
                    object readOnly = false;
                    object isVisible = true;

                    wordApp.Visible = true;

                    aDoc = wordApp.Documents.Open(ref fileName, ref missing, ref readOnly, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref isVisible, ref missing, ref missing, ref missing, ref missing);

                    aDoc.Activate();

                    this.FindAndReplace(wordApp, "<Model>", textBoxModel.Text);
                    this.FindAndReplace(wordApp, "<Serial#>", textBoxSerial.Text);
                    this.FindAndReplace(wordApp, "<CalBy>", textBoxCalBy.Text);
                    this.FindAndReplace(wordApp, "<Cal Date>", today.ToShortDateString());
                    this.FindAndReplace(wordApp, "<InspectedBy>", textBoxInspBy.Text);
                    this.FindAndReplace(wordApp, "<Insp Date>", today.ToShortDateString());

                    aDoc.SaveAs(ref saveFileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                    //wordApp.Quit();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                aDoc.Close();
                wordApp.Quit();
            }
        }

Using File Class

private void method1()
        {
            string templateFilePath = System.Windows.Forms.Application.StartupPath + "\\AIO2CertTemplate.doc";

            string text = File.ReadAllText(templateFilePath);
            text = text.Replace("<Model>", textBoxModel.Text);
            text = text.Replace("<Serial#>", textBoxSerial.Text);
            text = text.Replace("<CalBy>", textBoxCalBy.Text);
            text = text.Replace("<Cal Date>", DateTime.Now.ToShortDateString());
            text = text.Replace("<InspectedBy>", textBoxInspBy.Text);
            text = text.Replace("<Insp Date>", DateTime.Now.ToShortDateString());

            //System.Text.ASCIIEncoding enc = new ASCIIEncoding();
            //System.Text.Encoding.Unicode

            File.WriteAllText(textBoxSaveFilePath.Text, text, System.Text.Encoding.Default);
        }

Using StreamWriter

private void method2()
        {
            StreamWriter sw = new StreamWriter(textBoxSaveFilePath.Text);
            string templateFilePath = System.Windows.Forms.Application.StartupPath + "\\AIO2CertTemplate.doc";

            using (StreamReader sr = new StreamReader(templateFilePath))
            {
                string line;

                while ((line = sr.ReadLine()) != null)
                {
                    line = line.Replace("<Model>", textBoxModel.Text);
                    line = line.Replace("<Serial#>", textBoxSerial.Text);
                    line = line.Replace("<CalBy>", textBoxCalBy.Text);
                    line = line.Replace("<Cal Date>", DateTime.Now.ToShortDateString());
                    line = line.Replace("<InspectedBy>", textBoxInspBy.Text);
                    line = line.Replace("<Insp Date>", DateTime.Now.ToShortDateString());

                    sw.WriteLine(line);
                }
            }

            sw.Close();
        }

Thanks in advanced!

edit: Here is my find and replace method

private void FindAndReplace(Microsoft.Office.Interop.Word.Application doc, object findText, object replaceWithText)
{
    //options
    object matchCase = false;
    object matchWholeWord = true;
    object matchWildCards = false;
    object matchSoundsLike = false;
    object matchAllWordForms = false;
    object forward = true;
    object format = false;
    object matchKashida = false;
    object matchDiacritics = false;
    object matchAlefHamza = false;
    object matchControl = false;
    object read_only = false;
    object visible = true;
    object replace = 2;
    object wrap = 1;
    //execute find and replace
    doc.Selection.Find.Execute(ref findText, ref matchCase, ref matchWholeWord,
        ref matchWildCards, ref matchSoundsLike, ref matchAllWordForms, ref forward, ref wrap, ref format, ref replaceWithText, ref replace,
        ref matchKashida ,ref matchDiacritics, ref matchAlefHamza, ref matchControl);                
}

Edit #2: I did as Cindy posted I needed to create an my own IA for Word 2000. I created a temp folder on my C: for easy navigation via the command prompt. I copied the TlbImp.exe (found in C:/Program Files/Microsoft SDK/) and the MS Word OLB file found on the PC with Windows 2000 installed (C:/Program Files/Microsoft Office/Office). I then opened my command prompt (start->run->cmd.exe). Navigated to my temp folder cd C:\Temp then ran the following cmd TlbImp.exe MSWORD9.OLB /out: Microsoft.Office.Interop.Word.dll and it creates a dll in your directory. I then removed my old Interop reference and added this new dll. I had to change my namespace to using MSOffice.Word; and then updated the commands because they now take less parameters than the newer versions of the dll. Below is my updated methods:

private void FindAndReplace(MSOffice.Word._Application WordApp, object findText, object replaceWithText)
        {
            object matchCase = true;
            object matchWholeWord = true;
            object matchWildCards = false;
            object matchSoundsLike = false;
            object matchAllWordForms = false;
            object forward = true;
            object format = false;
            object matchKashida = false;
            object matchDiacritics = false;
            object matchAlefHamza = false;
            object matchControl = false;
            object read_only = false;
            object visible = true;
            object replace = 2;
            object wrap = 1;

            WordApp.Selection.Find.Execute(ref findText, ref matchCase, ref matchWholeWord, ref matchWildCards, ref matchSoundsLike,
                ref matchAllWordForms, ref forward, ref wrap, ref format, ref replaceWithText, ref replace, ref matchKashida,
                ref matchDiacritics, ref matchAlefHamza, ref matchControl);
        }

        private void method0()
        {
            MSOffice.Word._Document aDoc = null;
            object missing = System.Reflection.Missing.Value;
            MSOffice.Word._Application wordApp = new MSOffice.Word.Application();

            try
            {
                if (File.Exists("AIO2CertTemplate.doc"))
                {
                    DateTime today = DateTime.Now;

                    object fileName = System.Windows.Forms.Application.StartupPath + "\\AIO2CertTemplate.doc";
                    object saveFileName = textBoxSaveFilePath.Text;
                    object readOnly = false;
                    object isVisible = true;

                    wordApp.Visible = true;

                    //aDoc = wordApp.Documents.Open(ref fileName, ref missing, ref readOnly, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref isVisible, ref missing, ref missing, ref missing, ref missing);
                    aDoc = wordApp.Documents.Open(ref fileName, ref missing, ref readOnly, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref isVisible);

                    aDoc.Activate();

                    this.FindAndReplace(wordApp, "<Model>", textBoxModel.Text);
                    this.FindAndReplace(wordApp, "<Serial#>", textBoxSerial.Text);
                    this.FindAndReplace(wordApp, "<CalBy>", textBoxCalBy.Text);
                    this.FindAndReplace(wordApp, "<Cal Date>", today.ToShortDateString());
                    this.FindAndReplace(wordApp, "<InspectedBy>", textBoxInspBy.Text);
                    this.FindAndReplace(wordApp, "<Insp Date>", today.ToShortDateString());

                    //aDoc.SaveAs(ref saveFileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                    aDoc.SaveAs(ref saveFileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                    //wordApp.Quit();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                aDoc.Close();
                wordApp.Quit();
            }
        }

It could be cleaned up a little bit, but that is the basic info I learned to get this thing working.


Solution

  • Using the "Interop" with Office 2000 involves more steps than with later versions. That's because Microsoft did not supply any PIAs for Office 2000.

    (IA = Interop Assembly. This is what "translates" between the COM type libraries and the .NET Framework. PIA = Primary interop assembly and is an optimized version of the IAs distributed by the "owner" of the type library. PIAs are installed in the GAC and are version specific. IAs are not version specific, but may have certain problems communicating with the COM libraries.)

    Therefore, you need to create a set of IAs to provide the service of communicating between .NET and the Office COM type libraries (*.tlb). Your project will reference these and they need to be distributed with your project.

    Visual Studio's Windows SDK provides tlbimp.exe as a commandline tool for generating IAs. Here's the basic syntax:

    tlbimp <type-library-file>
    

    More information can be found in the MSDN documentation: https://msdn.microsoft.com/en-us/library/697w37zd(v=vs.110).aspx

    An alternative, that's also version independent, is to use late-binding (also known as PInvoke using GetType().InvokeMember).