Click here to Skip to main content
15,886,067 members
Articles / Programming Languages / C#

Word Automation

Rate me:
Please Sign up or sign in to vote.
4.86/5 (23 votes)
8 Nov 2007CPOL6 min read 145.9K   3.8K   68  
Word Automation using Early Binding and Late Binding.
/*--------------------------------------------------------------------------
Project		: Word Automation
Component	: Automation
Module		: Word Automation
Description	: This class is used for word automation. Aupport almost all the 
              versions. Only tested with 2000 and 2003
Log
Date				Author							Comment
16-Aug-2007			Prathapachandran				Created
--------------------------------------------------------------------------*/
using System;
using System.IO;
using System.Reflection;
using System.Collections;

namespace Automation
{
	/// <summary>
	/// Cass for automating word.
	/// </summary>
	public class WordAutomation
	{			
		#region Member Functions		
		/// <summary>
		/// Constructor
		/// </summary>		
		public WordAutomation()
		{
		}
		/// <summary>
		/// Function to create a word document.
		/// </summary>
		/// <param name="fileName">Name of word</param>
		/// <param name="wordApplication">Word application</param>
		/// <param name="isReadonly">open mode</param>
		/// <returns>If word document exist, return word doc object
		/// else return null</returns>		
		public object CreateWordDoc(object fileName, 
			object wordApplication, bool isReadonly)
		{	
			object wordDocument = null;		
			if (File.Exists(fileName.ToString()) && wordApplication != null)
			{				
				object readOnly = isReadonly;
				object isVisible = true;
				object missing = System.Reflection.Missing.Value;	
				
				object wordDocuments = GetProperty("Documents",wordApplication);				
				// Open a given Word document.
				wordDocument = InvokeMember("Open",wordDocuments,
					new object[]{fileName, missing, 
									isReadonly, missing, missing, missing, 
									missing, missing, missing, missing, 
									missing, isVisible});																		
			}			
			return wordDocument;
		}
		/// <summary>
		/// Function to create a word application
		/// </summary>
		/// <returns>Returns a word application</returns>		
		public object CreateWordApplication()
		{
            string message = "Failed to create word application. Check whether"
                + " word installation is correct.";	
			Type wordType = Type.GetTypeFromProgID("Word.Application");	            
			if (wordType == null)
			{
                throw new Exception(message);
			}
			object wordApplication = Activator.CreateInstance(wordType);	
			if (wordApplication == null)
			{
                throw new Exception(message);
			}
			return wordApplication;
		}
		/// <summary>
		/// Function to close a word document.
		/// </summary>
		/// <param name="wordDocument">Document Object to close</param>
		/// <param name="canSaveChange">Need to save changes or not</param>
		/// <returns>True if successfully closed.</returns>		
		public bool CloseWordDoc(object wordDocument, bool canSaveChange)
		{
			bool isSuccess = false;
			if (wordDocument != null)
			{		
				object saveChanges = null;				
				if (canSaveChange)
				{
					saveChanges = -1; // Save Changes
				}
				else
				{
					saveChanges = 0; // No changes
				}
				InvokeMember("Close",wordDocument,new object[]{saveChanges});				
				isSuccess = true;
			}
			return isSuccess;
		}
		/// <summary>
		/// Function to close word application
		/// </summary>
		/// <param name="wordApplication">Word application to close</param>
		/// <returns>True if successfully closed</returns>		
		public bool CloseWordApp(object wordApplication)
		{
			bool isSuccess = false;
			if (wordApplication != null)
			{								
				object saveChanges = -1; // Save changes
				InvokeMember("Quit",wordApplication,new object[]{saveChanges});				
				isSuccess = true;
			}
			return isSuccess;
		}
		/// <summary>
		/// Function to get the word count from the document. Entire word should 
		/// match.
		/// </summary>
		/// <param name="wordDoc">Document to search</param>
		/// <param name="word">Word to search</param>
		/// <returns>Count of the word</returns>		
		public int GetWordCount(object wordDoc, string word)
		{		
			int count = 0;
			do
			{
				if (wordDoc == null)
				{
					break;
				}
				if (word.Trim().Length == 0)
				{
					break;
				}				
				InvokeMember("Activate",wordDoc);
				object content = GetProperty("Content",wordDoc);
				// Get the count from direct text inside the document.
				count+= GetCountFromRange(
					content,wordDoc,word);						
				object comments = GetProperty("Comments",wordDoc);
				object count1 = GetProperty("Count", comments);
				int rangeCount = (int)count1;
				for(int i = 1; i <= rangeCount;)
				{
					object comment = InvokeMember("Item", 
						comments, new object[] { i });
					object range = GetProperty("Range", comment);
					count+= GetCountFromRange(
						range,wordDoc,word);
					break;
				}	
				object sections = GetProperty("Sections",wordDoc);
				object last = GetProperty("Last",sections);
				object headers = GetProperty("Headers",last);
				rangeCount = (int)GetProperty("Count", headers);
				for (int i = 1; i <= rangeCount; i++)
				{
					object header = InvokeMember("Item", 
						headers, new object[] { i });
					object range = GetProperty("Range", header);
					count+= GetCountFromRange(
						range,wordDoc,word);
				}
				object footers = GetProperty("Footers",last);
				rangeCount = (int)GetProperty("Count", footers);
				for (int i = 1; i <= rangeCount; i++)
				{
					object footer = InvokeMember("Item", 
						footers, new object[] { i });
					object range = GetProperty("Range", footer);
					count+= GetCountFromRange(
						range,wordDoc,word);
				}
				object shapes = GetProperty("Shapes",wordDoc);
				rangeCount = (int)GetProperty("Count", shapes);
				for (int i = 1; i <= rangeCount; i++)
				{
					object shape = InvokeMember("Item", 
						shapes, new object[] { i });
					object textFrame = GetProperty("TextFrame",shape);
					int hasText = (int)GetProperty("HasText",textFrame);
					if (hasText < 0)
					{
						object range = GetProperty("TextRange", textFrame);
						count+= GetCountFromRange(
							range,wordDoc,word);
					}
				}			
			}
			while(false);
			return count;
		}		
		/// <summary>
		/// Function to get word count from a given range.
		/// </summary>
		/// <param name="range">Range</param>
		/// <param name="wordDocument">Document to search</param>
		/// <param name="word">Word to search</param>
		/// <returns>Count of words</returns>
		private int GetCountFromRange(
			object range, object wordDocument,string word)
		{			
			int count = 0;
			object missing = System.Reflection.Missing.Value;			
			object matchAllWord = true;			
			object item = 1; // Goto Page
			object whichItem = 1;// First page		
			InvokeMember("GoTo",wordDocument,new object[]{item, whichItem});
			object find = GetProperty("Find",range);
			InvokeMember("ClearFormatting",find);	
			SetProperty("Forward",find,true);
			SetProperty("Text",find,word);
			SetProperty("MatchWholeWord",find,true);
			InvokeMember("Execute",find);			
			bool found = (bool)GetProperty("Found",find);
			while (found) 
			{ 
				++count;
				InvokeMember("Execute",find);
				found = (bool)GetProperty("Found",find);
			} 
			return count;
		}
		/// <summary>
		/// Function to find and replace a given text.
		/// </summary>
		/// <param name="wordDoc">Word Document</param>
		/// <param name="findText">Text for finding</param>
		/// <param name="replaceText">Text for replacing</param>
		/// <param name="wordApplication">Word Application</param>
		/// <returns>True if successfully replaced.</returns>
		public bool FindReplace(object wordDoc,object wordApplication, 
			string findText, string replaceText)
		{
			bool isSuccess = false;
			do
			{
				if (wordDoc == null)
				{
					break;
				}
				if (wordApplication == null)
				{
					break;
				}
				if (replaceText.Trim().Length == 0)
				{
					break;
				}
				if (findText.Trim().Length == 0)
				{
					break;
				}
				object content = GetProperty("Content",wordDoc);

				ReplaceRange(content,wordDoc,wordApplication,findText,replaceText);

				object comments = GetProperty("Comments",wordDoc);
				object count1 = GetProperty("Count", comments);
				int rangeCount = (int)count1;
				for(int i = 1; i <= rangeCount; i++)
				{
					object comment = InvokeMember("Item", 
						comments, new object[] { i });
					object range = GetProperty("Range", comment);
					ReplaceRange(range,wordDoc,wordApplication,findText,replaceText);					
				}

				object sections = GetProperty("Sections",wordDoc);
				object last = GetProperty("Last",sections);
				object headers = GetProperty("Headers",last);
				rangeCount = (int)GetProperty("Count", headers);
				for (int i = 1; i <= rangeCount; i++)
				{
					object header = InvokeMember("Item", 
						headers, new object[] { i });
					object range = GetProperty("Range", header);					
					ReplaceRange(range,wordDoc,wordApplication,findText,replaceText);
				}
				object footers = GetProperty("Footers",last);
				rangeCount = (int)GetProperty("Count", footers);
				for (int i = 1; i <= rangeCount; i++)
				{
					object footer = InvokeMember("Item", 
						footers, new object[] { i });
					object range = GetProperty("Range", footer);
					ReplaceRange(range,wordDoc,wordApplication,findText,replaceText);
				}

				object shapes = GetProperty("Shapes",wordDoc);
				rangeCount = (int)GetProperty("Count", shapes);
				for (int i = 1; i <= rangeCount; i++)
				{
					object shape = InvokeMember("Item", 
						shapes, new object[] { i });
					object textFrame = GetProperty("TextFrame",shape);
					int hasText = (int)GetProperty("HasText",textFrame);
					if (hasText < 0)
					{
						object range = GetProperty("TextRange", textFrame);
						ReplaceRange(range,wordDoc,wordApplication,findText,replaceText);
					}
				}
				isSuccess = true;
			}
			while(false);
			return isSuccess;
		}
		/// <summary>
		/// Replace a word with in a range.
		/// </summary>
		/// <param name="range">Range to replace</param>
		/// <param name="wordDocument">Document to replace</param>
		/// <param name="wordApp">Word Application</param>
		/// <param name="findText">Text to find</param>
		/// <param name="replaceText">Text to replace</param>
		private void ReplaceRange(object range, 
			object wordDocument,
			object wordApp,
			string findText, string replaceText)
		{
			object missing = System.Reflection.Missing.Value;
			InvokeMember("Activate",wordDocument);					
			object item = 1;
			object whichItem = 1;
			InvokeMember("GoTo",wordDocument,new object[]{item, whichItem});			
			object replaceAll = 2; 
			object matchAllWord = true;	
			object find = GetProperty("Find",range);
			InvokeMember("ClearFormatting",find);
			object replacement = GetProperty("Replacement",find);
			InvokeMember("ClearFormatting",replacement);
			InvokeMember("Execute",find,
				new object[]{findText,false,true,
								missing,missing,missing,true,missing,missing
								,replaceText,replaceAll});												
		}
		/// <summary>
		/// Invoke a member from an instance
		/// </summary>
		/// <param name="method">Method name to invoke</param>
		/// <param name="instance">Instance that method includes</param>
		/// <param name="parameters">Parameters to the function</param>
		/// <returns>object that returns from the function</returns>
		private object InvokeMember(string method, object instance, 
            object[] parameters)
		{
			Type type = instance.GetType();
			return type.InvokeMember(method,
				BindingFlags.InvokeMethod,null,instance,parameters);
		}
		/// <summary>
		/// Invoke a member from an instance
		/// </summary>
		/// <param name="method">Method name to invoke</param>
		/// <param name="instance">Instance that method includes</param>
		/// <returns>object that returns from the function</returns>
		private object InvokeMember(string method, object instance)
		{
			Type type = instance.GetType();
			return type.InvokeMember(method,
				BindingFlags.InvokeMethod,null,instance,new object[]{});
		}
		/// <summary>
		/// Function to get the property from a class
		/// </summary>
		/// <param name="propertyName">Name of property to access</param>
		/// <param name="instance">Instance that property includes</param>
		/// <returns>Property Value</returns>
		private object GetProperty(string propertyName, object instance)
		{
			Type type = instance.GetType();
			return type.InvokeMember(propertyName,
				BindingFlags.GetProperty,null,instance,new object[]{});
		}
		/// <summary>
		/// Function to set the property value
		/// </summary>
		/// <param name="propertyName">Name of property to set</param>
		/// <param name="instance">Instance that property includes</param>
		/// <param name="value">Value to set</param>
		private void SetProperty(string propertyName,object instance, object value)
		{						
			Type type = instance.GetType();			
			type.InvokeMember(
				propertyName,BindingFlags.SetProperty,
				null,instance,new object[]{	value} );
		}		
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder Appfabs
India India
- C#, WPF, WCF
- Java, J2EE, jersey, Spring MVC, Spring Boot, Spring Security, Hibernate, Spring Data
- NoSQL with Cassandra
- C, C++, Qt, OpenGL, Python
- SQL Server, Oracle, PostgreSQL
- Glassfish, Apache, Tomcat, NodeJS and IIS
- Hadoop, Flume, Spark
- Amazon Web Services (AWS) & Jenkins
- Big Data and Analytics

Comments and Discussions