How can I do a find and replace using C# in a word doc? For example, let's replace all instances of the word "Run" with "Ran"?
Maybe something like a String.Replace("run", "ran"); but that executed okay, but no changes were made.
A Find and Replace method :
public void FindAndReplaceWordText(ref Microsoft.Office.Interop.Word.Document wordDoc, string textToReplace, string newText)
{
object missing = System.Type.Missing;
foreach (Microsoft.Office.Interop.Word.Range tmpRange in wordDoc.StoryRanges)
{
//set the text to find and replace
tmpRange.Find.Text = textToReplace;
tmpRange.Find.Replacement.Text = newText;
tmpRange.Find.Wrap = Microsoft.Office.Interop.Word.WdFindWrap.wdFindContinue;
//Declare an object to pass as a parameter that sets the Replace parameter to the "wdReplaceOne" enum.
object replaceOne = Microsoft.Office.Interop.Word.WdReplace.wdReplaceOne;
//Execute the Find and Replace
tmpRange.Find.Execute(ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref replaceOne,
ref missing, ref missing, ref missing, ref missing);
}
Invoking the method:
FindAndReplaceWordText(ref wordDoc, "Ran", "Run");
Hope this helps!
Related
I have a code that opens up a word document, reads an excel file as data source for mail merge fields, and then saves the document.
The problem: I want the text in the merge field to be shown (and saved) as "previewed". (e.g. the field shows its value lets say "Dog" instead of its field title "Animal"). In the Word application i would simply click the button "Preview Result".
By recording a macro I have found that this can be solved in Visual Basic by the line ActiveDocument.MailMerge.ViewMailMergeFieldCodes = wdToggle
although I have not managed to use this in the C#-code.
I am new in both coding and this forum, so please let me know if I can provide more information.
using System;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using Word = Microsoft.Office.Interop.Word;
using System.Runtime.InteropServices;
using Microsoft.Office.Core;
namespace word
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void CreateWordDocument(object wordFilename, object excelSource)
{
Word.Application wordApp = new Word.Application();
object missing = Missing.Value;
Word.Document myWordDoc = null;
object readOnly = false;
object isVisible = false;
wordApp.Visible = true;
myWordDoc = wordApp.Documents.Open(ref wordFilename, ref missing, ref readOnly,
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);
myWordDoc.Activate();
myWordDoc.MailMerge.MainDocumentType =
Word.WdMailMergeMainDocType.wdNotAMergeDocument;
myWordDoc.MailMerge.OpenDataSource(Name: excelSource, Format: ref missing,
SQLStatement: "SELECT*FROM`Data$`");
//Any code for previewing
//VB-code: ActiveDocument.MailMerge.ViewMailMergeFieldCodes = wdToggle
myWordDoc.SaveAs2(ref wordFilename, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing,
ref mailmerge, ref missing, ref missing,
ref missing, ref missing, ref missing,
ref missing);
myWordDoc.Close();
wordApp.Quit();
}
}
The property to use is:
myWordDoc.ActiveWindow.View.MailMergeDataView = true;
Read more here:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.office.interop.word.view.mailmergedataview?view=word-pia
I am trying to reverse document paragraphs with the following code:
using Word = Microsoft.Office.Interop.Word;
object filePath = #"input.docx";
Word.Application app = new();
app.Visible = false;
object missing = System.Type.Missing;
object readOnly = false;
object isVisible = false;
Word.Document doc = app.Documents.Open(
ref filePath,
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);
try
{
Word.Range cachedPara2 = doc.Paragraphs[2].Range.Duplicate;
doc.Paragraphs[2].Range.FormattedText = doc.Paragraphs[1].Range.FormattedText;
doc.Paragraphs[1].Range.FormattedText = cachedPara2.FormattedText;
doc.SaveAs(#"output.docx");
}
finally
{
doc.Close();
app.Quit();
}
I expect this:
but the actual result is this:
How to get expectations?
UPDATE
With the answer below, I was able to get the expected result for my first case.
Now, in another case, I wanna do the following:
Unfortunately, I couldn't quite figure it out how .Collabse() method works. I am trying to do it with .InsertParagraphAfter():
doc.Paragraphs[2].Range.InsertParagraphAfter();
doc.Paragraphs[3].Range.FormattedText = doc.Paragraphs[5].Range.FormattedText;
doc.Paragraphs[5].Range.FormattedText = doc.Paragraphs[2].Range.FormattedText;
doc.Paragraphs[2].Range.Delete();
Where does this empty paragraph come from? How avoid it?
A range object does not have any content itself, it merely points to the location of the content, rather like a set of map co-ordinates.
What you need to do is add the content of the second paragraph before the first, which will create a new first paragraph. You can then delete what is now the third paragraph. For example:
Word.Range target = doc.Paragraphs[1].Range;
target.Collapse wdCollapseStart;
target.FormattedText = doc.Paragraphs[2].Range.FormattedText;
doc.Paragraphs[3].Range.Delete;
I am trying to get bullet list from docx using C#, however, instead of bullet number or symbol, the output gets a weird symbol or rectangle with a question mark inside "", instead of a bullet. Following is the code snippet I am using to get bullet value, but it is not working:
Application word = new Application ();
Document doc = new Document ();
object fileName = #"D:\testing\Sample_2.docx";
// Define an object to pass to the API for missing parameters
object missing = System.Type.Missing;
doc = word.Documents.Open (ref fileName,
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);
for (int i = 0; i < doc.Paragraphs.Count; i++) {
string bullet = doc.Paragraphs[i + 1].Range.ListFormat.ListString;
}
((_Document) doc).Close ();
((_Application) word).Quit ();
I am looking to compare two word documents and I found a solution online that compares word documents using c#. When the code is executed, it opens three applications (the original document, the document that needs to be compared, and a third document that shows the results). Is there a way for these three application to not open up and instead return a boolean to the console?
objective: Display the comparison of the two documents in a console application as either 'the same' or 'different'
using System;
using System.IO;
using Microsoft.Office.Interop.Word;
class Program
{
static void Main()
{
Application wordApp = new Application();
wordApp.Visible = true;
object wordTrue = (object)true;
object wordFalse = (object)false;
object fileToOpen = #"C:\doc1.docx";
object missing = Type.Missing;
Document doc1 = wordApp.Documents.Open(ref fileToOpen,
ref missing, ref wordFalse, ref wordFalse, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref wordTrue, ref missing,
ref missing, ref missing, ref missing);
object fileToOpen1 = #"C:\doc2.docx";
Document doc2 = wordApp.Documents.Open(ref fileToOpen1,
ref missing, ref wordFalse, ref wordFalse, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing);
Document doc = wordApp.CompareDocuments(doc1, doc2, WdCompareDestination.wdCompareDestinationNew, WdGranularity.wdGranularityWordLevel,
true, true, true, true, true, true, true, true, true, true, "", true);
//Something like the following:
if (doc1 != doc2)
{
Console.WriteLine("They are not same");
}
else
{
Console.WriteLine("They are identical");
}
Console.ReadKey();}}
Have you tried set Visible = false?
I think this is why your word documents pops up.
I did some word docs manipulation in the past, and by setting visible property to false, you can work with the doc without showing it. (winword.exe will execute anyway)
Your code is using interops like Microsoft.Office.Interop.Word, so you can hide the windows using :
wordApp.Visible = false;
and Finally :
wordApp.Quit();
A faster approach is however, reading them in byte. you can compare the two byte arrays to figure out how similar they are.
I'm using word automation to generate a docx file, then print it out. Here is my basic code. I found that I have to wait some time after adoc.PrintOut, otherwise, the print may fail. It seems it is because I close the file after that. Before the file is closed, word does not have time to print it out yet. So, basically, adoc.PrintOut is non-blocked (this may not be the correct term). Right now, I wait for 10 seconds, it works fine. However, does it have a more elegant solution for this? I mean, how can wait until PrintOut finished, then close the doc?
thanks
object yes = true;
object no = false;
object missing = System.Reflection.Missing.Value;
Word.Application wordApp = new Word.Application();
object fileName = originalFileName;
Word.Document adoc = null;
try
{
adoc = wordApp.Documents.Open(ref fileName,
ref missing, ref no, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref yes, ref missing, ref missing, ref missing, ref missing);
adoc.Activate();
/*
some other processing
*/
object sFile = fileName;
adoc.PrintOut(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, ref missing, ref missing, ref missing);
// http://msdn.microsoft.com/en-us/library/b9f0ke7y
//adoc.PrintPreview();
for (int i = 0; i < 10; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
Application.DoEvents();
}
//adoc.Save();
object savechanges = Word.WdSaveOptions.wdDoNotSaveChanges; //.wdSaveChanges;
object originalFormat = Word.WdOriginalFormat.wdWordDocument;
object routeDocument = missing; // Type.Missing; // true;
((Word._Document)adoc).Close(ref savechanges, ref originalFormat, ref routeDocument);
((Word._Application)wordApp).Quit(ref savechanges, ref missing, ref missing);
adoc = null;
wordApp = null;
}
catch
{
}
finally
{
/*
some dispose work
*/
// do it twice to release all memory
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
You can use the first parameter of PrintOut.
object background = false;
adoc.PrintOut(background, 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, ref missing,
ref missing);
As the documentation says:
http://msdn.microsoft.com/en-us/library/microsoft.office.tools.word.document.printout(v=vs.80).aspx
"Background
true to have the customization code continue while Microsoft Office Word prints the document."