Embbed outlook mails into word document - c#

Is there a way to embbed outlook mailitems into word document programatically from a Outlook Mailitem List.??
I am trying to achieve something like this
Word.Application wdApp = new Word.Application();
Word.Document wdDoc = wdApp.Documents.Add(ref missing, ref missing, ref missing,
ref missing);
foreach(Outlook.MailItem olMail in mailAttachments)
{
//Paste/embbed this olMail into the word document
}

Ya Finally i found an effective solution
I used the InlineShapes.AddOLEObject method
My solution:
static void creatDocument(List<Outlook.MailItems> mailAttachments)
{
string userprofile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
object missing = System.Reflection.Missing.Value
object start=0;
object end =0;
object classType ="{00020D0B-0000-0000-C000-000000000046}";
object fileName;
object linkToFile = false;
object displayAsIcon = true;
object iconFileName = Path.Combine(userprofile,"Pictures\MailIcon.ico");
object iconIndex =0;
object iconLabel;
object range;
Word.Application wdApp=new Word.Application();
Word.Document wdDoc = wdApp.Documents.Add(ref missing, ref missing, ref missing, ref missing);
Range rng = wdDoc.Range(ref start,ref missing);
foreach(outlook.MailItem olMail in mailAttachments)
{
olMail.SaveAs(Path.Combine(userprofile,"Documents\TemperoraySave") + CleanFileName(olMail.Subject) + ".msg" ,Outlook.OlSaveAsType.olMsg);
fileName = Path.Combine(userprofile,"Documents\TemperoraySave") + CleanFileName(olMail.Subject) + ".msg"
iconLabel = CleanFIleName(olMail.Subject) + ".msg";
rng = wdDoc.Content;
rng.Collapse(WdCollapseDirection.wdCollapseEnd);
range = rng;
wdDoc.InLineShapes.AddOLEObject(ref classType,ref fileName,ref linkToFile,ref displayAsIcon,ref iconFIleName,ref iconIndex,ref iconLabel,ref range);
var mailRanger = wdDoc.Paragraphs.Add();
mailRanger.Format.SpaceAfter =10f;
}
}
private static string CleanFileName(string fileName)
{
return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty));
}

Nope. The Word object model doesn't provide anything for that. Instead, you may consider using the CustomDocumentPropertiesenter link description here collection for storing your custom data. For example, you may save the message as an .msg file and save the path to the file or the ID of the record in the database to a custom document property. After, when you need to open a message you can get the ID or path for retrieving the email message.

You can't embed the source text of the emails, but you can copy the MailItem.HTMLBody or MailItem.Body (text) values and insert them into the Word document.

Related

How to compare image (Shape) present in each page of word document through Microsoft.Interop.Word using C#.Net?

I am using following code to replace image (Shape in Microsoft.Interop.Office.Word) of the word document with new image but what the requirement from client is that I need to check the 1st Image of the 1st page of the word document and then compare this image with image of the rest of the document and if match it get replaced with new image else not so need help on how can we compare two shapes(Images)
public void ReplaceWordImage(string FilePath)
{
Word.Document d = new Word.Document();
Word.Application WordApp;
WordApp = new Microsoft.Office.Interop.Word.Application();
bool headerImage = false;
try
{
object missing = System.Reflection.Missing.Value;
object yes = true;
object no = false;
object filename = #"D:/ImageToReplace/5.docx";
d = 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);
List<Word.ShapeRange> ranges = new List<Microsoft.Office.Interop.Word.ShapeRange>();
List<Word.ShapeRange> headerRanges = new List<Microsoft.Office.Interop.Word.ShapeRange>();
foreach (Word.Shape shape in d.Shapes)
{
if (shape.Type == Microsoft.Office.Core.MsoShapeType.msoPicture)
{
shape.Delete();
foreach (Word.Range r in ranges)
`enter code here` {
r.InlineShapes.AddPicture(#"D:\Untitled.jpg", ref missing, ref missing);
break;
}
}
The Word object model doesn't provide anything to compare two images. The best what you could do is to save both on the disk and then try comparing the bytes representation of both. However, there is a better way to get the job done. The answer is the Open XML SDK which allows getting the bytes representation of images on the fly without saving them to a disk before. The Open XML SDK contains a class WordprocessingDocument that can manipulate a memory stream containing a WordDocument content. And MemoryStream can be converted using ToArray() to a byte[]. See Convert Word of interop object to byte [] without saving physically for more information.

Word Document SaveAs2 in Format wdFormatDocument97

I'm using Microsoft Interop Word version 15.0.0.0 in order to create a new Word document, insert some text into it, and save it.
When I'm saving it using the following command:
document.SaveAs2(wordFilePath);
the document is saved in format DOCX.
But when I'm saving it using the following command:
document.SaveAs2(wordFilePath, Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatDocument97);
the document is seemingly saved as Word-97 DOC (Windows explorer display it with Word-97 DOC icon and type), but it is really internally saved as DOCX (I can see this in two ways: it has the same size of the corresponding DOCX, and when I open it with Word-2016 and select SaveAs, the default save format is DOCX!).
How can I save a document in real document-97 format?
Here's the function used to create a new Word document, whose type depends on the extension (DOC vs. DOCX) of given file path:
public static void TextToMsWordDocument(string body, string wordFilePath)
{
Microsoft.Office.Interop.Word.Application winword = new Microsoft.Office.Interop.Word.Application();
winword.Visible = false;
object missing = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Word.Document document = winword.Documents.Add(ref missing, ref missing, ref missing, ref missing);
if (body != null)
{
document.Content.SetRange(0, 0);
document.Content.Text = (body + System.Environment.NewLine);
}
if (System.IO.Path.GetExtension(wordFilePath).ToLower() == "doc")
document.SaveAs2(wordFilePath, Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatDocument97);
else // Assuming a "docx" extension:
document.SaveAs2(wordFilePath);
document.Close(ref missing, ref missing, ref missing);
document = null;
winword.Quit(ref missing, ref missing, ref missing);
winword = null;
}
And here's the code used to call this function:
TextToMsWordDocument("abcdefghijklmnopqrstuvwxyz", "text.doc");
TextToMsWordDocument("abcdefghijklmnopqrstuvwxyz", "text.docx");
It's been a rather stupid error...compare ‘ == ".doc" ’ instead of ‘ == "doc"...
I didn't notice it due to the fact that when SaveAs2 received a file path with extension ".doc" and no WdSaveFormat, it - strangely enough- created a Word document file that had the problem I explained here...

Edit Excel Spreadsheet object in word document (C# Interop)

I am currently trying to edit cells of an excel spreadsheet object with c# interop. I inserted it in a word document as an object.
Until there i didn't succeed to programm anything that really works. I'm able to select the component but i can't open it to edition and then reach grid's cells.
I use a button control in a custom office ribbon to launch edit. Here is my method:
public void EditTable(Office.IRibbonControl control)
{
Word.Application oWordApp = (Word.Application)Marshal.GetActiveObject("Word.Application");
Word.Document oWordDoc = oWordApp.ActiveDocument;
Word.Bookmark ReqsBookmark = DocumentHelper.GetBookmark("test");
ReqsBookmark.Select();
}
The only way i know to access a specific object with interop is with bookmarks.
Does anybody have an idea of how doing such a thing?
In Word, an Excel worksheet (workbook) is "wrapped" in an OLE control that is a member of the InlineShapes or Shapes collection. So you need the AddOLEObject method of the collection you want to use.
Access to the object model of the OLE server (Excel) is through the OLEFormat property of the InlineShape or Shape. So your code would be something like the sample below.
Note that although you say this is a VSTO project, the code you show us is not VSTO. You're starting up a new instance of the Word.Application, but the VSTO Add-in would be running in-process. My code is VSTO code, but can certainly be adjusted for other situations...
{
Word.Document doc = Globals.ThisAddIn.app.ActiveDocument;
object oRngTarget = Globals.ThisAddIn.app.Selection.Range;
//object oRngTarget = DocumentHelper.GetBookmark("test").Range;
object oOLEClass = "Excel.Sheet.12";
object oFalse = false;
Word.InlineShape ils = doc.InlineShapes.AddOLEObject(ref oOLEClass, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref oRngTarget);
Word.OLEFormat olef = ils.OLEFormat;
System.Globalization.CultureInfo oldCI= System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
Excel.Workbook wb = (Excel.Workbook)olef.Object;
Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets[1];
try
{
ws.get_Range("A1").Value2 = "New category";
ws.get_Range("B1").Value2 = 6.8;
}
catch (Exception ex)
{
System.Diagnostics.Debug.Print(ex.Message);
}
finally
{
ws = null;
wb = null;
ils = null;
doc = null;
System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
}
}
To later work with a spreadsheet in the Word document, you basically follow the same principle: declare and instantiate a InlineShape.OLEFormat object, Activate it, then cast olef.Object to an Excel.Workbook:
olef.Activate();
Excel.Workbook wb = (Excel.Workbook)olef.Object;
I finally succeeded thanks to this post about modify an embedded Excel object inside a Word doc
Here's the c# method if anybody need it one day:
{
Word.Document oWordDoc = Globals.ThisAddIn.Application.ActiveDocument;
Excel.Workbook oOLE = null;
Excel.Worksheet oSheet = null;
Word.InlineShapes ils = oWordDoc.InlineShapes;
ils[1].OLEFormat.Activate();
oOLE = ils[1].OLEFormat.Object;
oSheet = oOLE.Worksheets[1];
oSheet.get_Range("A1").Value = "I did it too!";
}
Thank you again #CindyMeister for your answer, it helped me to understand how it really works.

Adding to Word document with bullet formatting at end

I work on a process that reads a Word document and appends some images to the end of it. The issue I'm running into is that the document ends with a lettered list and the images I am appending are becoming a part of that list. I can't seem to find a way to end that list before adding the images.
Microsoft.Office.Interop.Word.Application winword =
new Microsoft.Office.Interop.Word.Application();
winword.Visible = false;
object missing = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Word.Document document = winword.Documents.Open(documentName);
object lastLine = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToLine;
object lastDirection = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToLast;
document.Sections.Add(missing);
document.Sections[document.Sections.Count]
.Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary].LinkToPrevious = false;
document.Sections[document.Sections.Count]
.Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary].Range.Text = "";
winword.Selection.GoTo(ref lastLine, ref lastDirection, ref missing, ref missing);
winword.Selection.EndKey(WdUnits.wdStory, missing);
foreach(string image in images)
{
document.Application.Selection.InlineShapes.AddPicture(image);
}
document.SaveAs2("finished.doc",
Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatDocument97);
document.Close();
winword.Quit();

Read a Word Document Using c#

I need to start reading a word document from a specific point.
That key word is taken from a dropdown combo box.
The keyword is something like [blah blah, blah, 001]
So, I need to read only the content from that keyword to next heading ...
I used this to read heading numbers and line by line
but heading num notworking
string headNum = objparagraph.Range.ListFormat.ListString;
string sLine = objparagraph.Range.Text;
Word.Application word = new Word.Application();
Word.Document doc = new Word.Document();
object fileName = #"C:\wordFile.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);
string ReadValue = string.Empty;
// Activate the document
doc.Activate();
foreach (Word.Range tmpRange in doc.StoryRanges)
{
ReadValue += tmpRange.Text;
}
If I understood correctly, you need to read the Word document starting from your keyword to next heading. In other words, something like the red text in the following document:
In that case, here is how you can accomplish that with GemBox.Document:
string keyword = " [blah blah, blah, 001]";
DocumentModel document = DocumentModel.Load("input.docx");
ContentPosition start = document.Content
.Find(keyword)
.First()
.End;
ContentPosition end = new ContentRange(start, document.Content.End)
.GetChildElements(ElementType.Paragraph)
.Cast<Paragraph>()
.First(p => p.ParagraphFormat.Style != null && p.ParagraphFormat.Style.Name.Contains("heading"))
.Content
.Start;
string text = new ContentRange(start, end).ToString();
The text variable's value will be:
Sample text content that we want to retrieve.
Another sample paragrap.
Also, here are additional Reading and Get Content examples, they contain some useful information.

Categories