I want to read a word document without opening it. Then replace some text in it and then save it with another name in the same format using C#. But the document is not being saved with the changes but int the same way as the original document. Any help will be appreciated. Thanks in advance.
string path = Server.MapPath("~/CustomerDocument/SampleNDA5.docx");
WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(path, false);
{
var body = wordprocessingDocument.MainDocumentPart.Document.Body;
foreach (var text in body.Descendants<Text>())
{
if (text.Text.Contains("<var_Date>"))
{
text.Text = text.Text.Replace("<var_Date>", DateTime.Now.ToString("MMM dd,yyyy"));
}
}
wordprocessingDocument.SaveAs(Server.MapPath("~/CustomerDocument/SampleNDA10.docx"));
wordprocessingDocument.Close();
}
I think this should help. It explains how to put edits back into a collection.
https://www.codeproject.com/Articles/87616/List-T-ForEach-or-Foreach-It-Doesn-t-Matter-Or-Doe
So if your word template is the same each time you essentially
Copy The Template
Work On The Template
Save In Desired Format
Delete Template Copy
Each of the sections that you are replacing within your word document you have to insert a bookmark for that location (easiest way to input text in an area).
I always create a function to accomplish this, and I end up passing in the path - as well as all of the text to replace my in-document bookmarks. The function call can get long sometimes, but it works for me.
Application app = new Application();
Document doc = app.Documents.Open("sDocumentCopyPath.docx");
if (doc.Bookmarks.Exists("bookmark_1"))
{
object oBookMark = "bookmark_1";
doc.Bookmarks.get_Item(ref oBookMark).Range.Text =
"My Text To Replace bookmark_1";
}
if (doc.Bookmarks.Exists("bookmark_2"))
{
object oBookMark = "bookmark_2";
doc.Bookmarks.get_Item(ref oBookMark).Range.Text =
"My Text To Replace bookmark_2";
}
doc.ExportAsFixedFormat("myNewPdf.pdf", WdExportFormat.wdExportFormatPDF);
((_Document)doc).Close();
((_Application)app).Quit();
This code should get you up and running unless you want to pass in all the values into a function.
If you need some more explanation I can help as well :) my example saves it as a .pdf, but you can do any format you prefer.
Related
I'm writing a application that can edit paragraphs in a Word Template (.docx). In these paragraphs they can contain custom DOCPROPERTY. I can read and edit the paragraph then write them back successfully, however when I write them back when a DOCPROPERTY is included it writes it back as text.
An example of my code to edit a paragraph is as follows. I understand why this is happening in my code because I'm writing it as Text. my question is how I write DOCPROPERTY to a .docx file so Word reads it as DOCPROPERTY and not text.
paragraph.RemoveAllChildren<Run>();
paragraph.AppendChild<Run>(new Run(new Text("DOCPROPERTY "System" \* MERGEFORMAT")));
I've searched around and cannot see a suitable example.
I've found how to do it.
Run r = new Run();
Text t = new Text();
t.Text = "System";
r.Append(t);
r.Append(new Text { Text = " ", Space = SpaceProcessingModeValues.Preserve });
r.Append(new SimpleField() { Instruction = #"DOCPROPERTY System \\*MERGEFORMAT" });
paragraph.Append(r);
I am converting a single HTML page to Doc using spire doc. I need to convert multiple html pages from single folder to single Doc. How this can be done. Can anyone give some idea or any library available to achieve this?
Please find my code to convert single HTML to Doc.
Spire.Doc.Document document = new Spire.Doc.Document();
document.LoadFromFile(#"D:\DocFilesConvert\htmlfile.html", Spire.Doc.FileFormat.Html, XHTMLValidationType.None);
document.SaveToFile(#"D:\DocFilesConvert\docfiless.docx", Spire.Doc.FileFormat.Docx);
There seems no direct way to achieve this. One workaround I find is to convert each HTML document to a single Word file, and then merge these Word files in one file.
//get HTML file paths
string[] htmlfilePaths = new string[]{
#"F:\Documents\Html\1.html",
#"F:\Documents\Html\2.html",
#"F:\Documents\Html\3.html"
};
//create Document array
Document[] docs = new Document[htmlfilePaths.Length];
for (int i = 0; i < htmlfilePaths.Length; i++)
{
//load each HTML to a sperate Word file
docs[i] = new Document(htmlfilePaths[i], FileFormat.Html);
//combine these Word files in one file
if (i>=1)
{
foreach (Section sec in docs[i].Sections)
{
docs[0].Sections.Add(sec.Clone());
}
}
}
//save to a Word document
docs[0].SaveToFile("output.docx", FileFormat.Docx2013);
I was able to read a text and write it back to a word document.
I have a table with data. I have to read the entire table object and save it to the database, then retrieve the table back to word document whenever needed.
Here is the code for the text content. I need the same for Table object.
private string Get(Word.Range range)
{
System.Windows.Forms.Clipboard.Clear();
if (range.Text.Length > 0)
{
System.Threading.Thread.Sleep(800);
rtb = new System.Windows.Forms.RichTextBox();
range.Select();
oWord.Selection.Copy();
rtb.Rtf = (string)System.Windows.Forms.Clipboard.GetData(System.Windows.Forms.DataFormats.Rtf); ;
System.Windows.Forms.Clipboard.Clear();
return rtb.Rtf.Remove(rtb.Rtf.LastIndexOf("\\pard"), 5);
}
return string.Empty;
}
You can pick up the exact range as defined in Word using WordOpenXML and restoring it with InsertXML.
Read:
string txt = range.WordOpenXML();
Save txt to your database.
Write back
range.InsertXML(txt);
Where txt was pulled from your database.
So, in theory you could backup and restore your complete document using:
ActiveDocument.Content.WordOpenXML();
My goal is to somehow be able to read bookmarks in an outlook .msg file, then replace them with a different text. I want to do this with C#.
I know how to access the body and change the text, but was wondering if there was a way to access directly the list of all the bookmarks and its location so that i can easily replace them, instead going through the whole body text, splitting it up, etc etc...
edit: this is how a bookmark window looks like from this window one can assign bookmarks, but it should be possible to obtain this list via c#.
Any relevant info is appreciated.
Thanks in advance.
Since Outlook most often uses Word as it's body editor - you need to add a project reference to Microsoft.Office.Interop.Word.dll and then access to the Outlook Inspector's WordEditor during the Inspector.Activate event. Once you have access to the Word.Document - it's trivial to load up the Bookmarks and access/modify their values.
Outlook.Inspector inspector = Globals.ThisAddIn.Application.ActiveInspector();
((Outlook.InspectorEvents_10_Event)inspector).Activate += () =>
{ // validation to ensure we are using Word Editor
if (inspector.EditorType == Outlook.OlEditorType.olEditorWord && inspector.IsWordMail())
{
Word.Document wordDoc = inspector.WordEditor as Word.Document;
if (wordDoc != null)
{
var bookmarks = wordDoc.Bookmarks;
foreach (Word.Bookmark item in bookmarks)
{
string name = item.Name; // bookmark name
Word.Range bookmarkRange = item.Range; // bookmark range
string bookmarkText = bookmarkRange.Text; // bookmark text
item.Select(); // triggers bookmark selection
}
}
}
};
I have a really simple word document with Content Controls (all text).
I want to loop through the controls, filling them with values from a dictionary. Should be super simple, but something is wrong:
var myValues = new Dictionary<string, string>(); //And fill it
using (var wordDoc = WordprocessingDocument.Open(outputFile, true))
{
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
foreach(SdtElement sdt in mainPart.Document.Descendants<SdtElement>())
{
SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault();
if (alias != null)
{
string sdtTitle = alias.Val.Value;
sdt.??? = myValues[sdtTitle];
}
}
mainPart.Document.Save();
}
How do I write my value into the document?
Do I need a CustomXmlPart?
If you are going to do something like that, you'll need to write suitable content into the Sdt's SdtContent: a paragraph or a run or a tc etc depending on the sdt's parent element.
The alternative is to put the contents of your dictionary into a CustomXml part, and set up databindings on each content control which refer to the relevant dictionary element. Word will then resolve the bindings when the docx is first opened (which is not much good to you if you expect your users to open it with something else).
You can use this code.
foreach (SdtElement sdt in mainPart.Document.Descendants<SdtElement>())
{
SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault();
if (alias != null)
{
string sdtTitle = alias.Val.Value;
Text t = sdt.Descendants<Text>().First();
t.Text = "test";
}
}