I need to produce and save a MS Word .doc file starting from a template (let's say C:\template.doc) and a datasource (let'say C:\datasource.doc)
I'm using MailMerge.Execute and if I let Word to be visible, I see the correct result file, but I can't realize to save this file in any way. The code is:
Microsoft.Office.Interop.Word.Application myWord = new Microsoft.Office.Interop.Word.Application();
Object oFalse = false; Object oTrue = true; Object oFileName = #"C:\merged.doc";
Word.Document myMailMergeDoc = myWord.Documents.Open(#"C:\template.doc");
myMailMergeDoc.MailMerge.OpenDataSource(Name: #"C:\datasource.doc");
myMailMergeDoc.MailMerge.Destination = Word.WdMailMergeDestination.wdSendToNewDocument;
myMailMergeDoc.MailMerge.Execute(oFalse);
try
{
myWord.Documents["template.doc"].Close(oFalse);
myWord.Documents.Save(oFileName);
myMailMergeDoc.SaveAs(oFileName);
myWord.ActiveDocument.SaveAs(oFileName);
}
catch(System.Runtime.InteropServices.COMException ex)
{ }
None of the three saving methods in the try block saves the file on the disk. What am I doing wrong?
Ok, I did it: I missed to install VBA features from Office setup, now the document is correctly saved
Related
I have C# function that saves a supplied image into a PDF file using VSTO. But it is throwing:
System.AccessViolationException HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an
indication that other memory is corrupt. Source= StackTrace:
I have tried saving in various ways: see commented code:
public static Boolean ConvertImageFileToPDF(string imageFileName, string outputFileName, string attachmentName)
{
try
{
Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document wordDoc;
wordDoc = wordApp.Documents.Add();
wordDoc.Content.Font.Name = "Arial";
wordDoc.Content.Font.Size = 12;
wordDoc.Content.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphCenter;
wordDoc.Content.Text = attachmentName;
wordDoc.Content.InsertParagraphAfter();
wordDoc.InlineShapes.AddPicture(imageFileName, false, true);
wordDoc.Application.ActiveDocument.SaveAs2(outputFileName, WdSaveFormat.wdFormatPDF);
//wordDoc.SaveAs2(outputFileName, WdSaveFormat.wdFormatPDF);
//wordDoc.SaveAs(outputFileName, WdSaveFormat.wdFormatPDF);
wordDoc.Close();
wordApp.Application.Quit(false);
return true;
}
catch
{
return false;
}
The save location is valid (a simple temporary directory that is used elsewhere within the code without problems).
I've searched for solutions without luck, can anyone help please?
Is there any way to check if a specific word document is Open? When I open document myself before opening the app when I tell to my app to write something in document first try to open the document and thats where my app is stuck.Is there a way to check before I try to open if the file is already opened? at this moment my code looks like this:
object filename = s; // s is a string path which I get from database
Microsoft.Office.Interop.Word.Application app = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document doc1 = app.Documents.Open(s);
object missing = System.Reflection.Missing.Value;
app.Visible = true;
just put your code in a
try
{
//your code here
}
catch (Exception e)
{
//your behavior when the file is opened
}
i'm new to ASP.NET MVC and tried to generate an export from Formdata to word file. That worked quite well, all the Bookmarks in the Document are filled correctly with following code:
string savePath = (#"U:\Coding ASP.MVC\WebForm Export into WordFile\Gutachten.docx");
string templatePath = (#"U:\Coding ASP.MVC\WebForm Export into WordFile\wordTemplate.docx");
Microsoft.Office.Interop.Word.Application app = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document doc = new Microsoft.Office.Interop.Word.Document();
doc = app.Documents.Open(templatePath);
doc.Activate();
if (doc.Bookmarks.Exists("FileNoSIS"))
{
doc.Bookmarks["FileNoSIS"].Range.Text = FileNoSIS;
}
if (doc.Bookmarks.Exists("NameOfAction"))
{
doc.Bookmarks["NameOfAction"].Range.Text = NameOfAction;
}
doc.SaveAs2(savePath);
app.Application.Quit();
Response.Write("Success");
But now i want to get the thing done with a stream to edit the document and offer the new filled document as a download. Can anybody here give me some advice or any tip how to get there?
Thx
I'm working on Word 2010 plugin and I want to copy active document with track changes (http://office.microsoft.com/en-001/word-help/turn-track-changes-on-or-off-HA010370561.aspx) to XML format and later to send it somewhere else.
This is my code:
Microsoft.Office.Interop.Word.Document documentNew = new Microsoft.Office.Interop.Word.Document();
object missing = Type.Missing;
document.Range(ref missing, ref missing).Copy();
documentNew.Range(ref missing, ref missing).PasteAndFormat(Microsoft.Office.Interop.Word.WdRecoveryType.wdFormatOriginalFormatting);
Object xmlFormat = Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatXML;
documentNew.SaveAs2(file, xmlFormat);
This works, but does not include track changes in duplicate document. Anybody have idea how to also include changes?
How about saving document to the new document in XML first, then opening up the new document and make whatever changes are required? I've tested this approach and it preserves the tracked changed without having to do anything special.
Copy and pasting into a new document is not going to preserve the original tracked changes.
So the code would be:
public static void SaveAsXMLAndDoSomethingElse() {
String fn = #"C:\Users\zbook\Desktop\Track test.docx";
String fn_xml = #"C:\Users\zbook\Desktop\Track test3.xml";
Microsoft.Office.Interop.Word.Application app = new Microsoft.Office.Interop.Word.Application();
Documents docs = app.Documents;
Document doc = docs.Open(fn, ReadOnly:true);
//bool b = doc.TrackFormatting; // for some reason this line bombs
doc.SaveAs2(fn_xml, Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatXML);
doc.Close(false);
Marshal.ReleaseComObject(doc);
// now open up fn_xml ... and do whatever
app.Quit(false);
Marshal.ReleaseComObject(docs);
Marshal.ReleaseComObject(app);
}
I'm looking to replace a bookmark in a word document with the entire contents of another word document. I was hoping to do something along the lines of the following, but appending the xml does not seem to be enough as it does not include pictures.
using Word = Microsoft.Office.Interop.Word;
...
Word.Application wordApp = new Word.Application();
Word.Document doc = wordApp.Documents.Add(filename);
var bookmark = doc.Bookmarks.OfType<Bookmark>().First();
var doc2 = wordApp.Documents.Add(filename2);
bookmark.Range.InsertXML(doc2.Contents.XML);
The second document contains a few images and a few tables of text.
Update: Progress made by using XML, but still doesn't satisfy adding pictures as well.
You've jumped in deep.
If you're using the object model (bookmark.Range) and trying to insert a picture you can use the clipboard or bookmark.Range.InlineShapes.AddPicture(...). If you're trying to insert a whole document you can copy/paste the second document:
Object objUnit = Word.WdUnits.wdStory;
wordApp.Selection.EndKey(ref objUnit, ref oMissing);
wordApp.ActiveWindow.Selection.PasteAndFormat(Word.WdRecoveryType.wdPasteDefault);
If you're using XML there may be other problems, such as formatting, images, headers/footers not coming in correctly.
Depending on the task it may be better to use DocumentBuilder and OpenXML SDK. If you're writing a Word addin you can use the object API, it will likely perform the same, if you're processing documents without Word go with OpenXML SDK and DocumentBuilder. The issue with DocumentBuilder is if it doesn't work there aren't many work-arounds to try. It's open source not the cleanest piece of code if you try troubleshooting it.
You can do this with openxml SDK and Document builder. To outline here is what you will need
1> Inject insert key in main doc
public WmlDocument GetProcessedTemplate(string templatePath, string insertKey)
{
WmlDocument templateDoc = new WmlDocument(templatePath);
using (MemoryStream mem = new MemoryStream())
{
mem.Write(templateDoc.DocumentByteArray, 0, templateDoc.DocumentByteArray.Length);
using (WordprocessingDocument doc = WordprocessingDocument.Open([source], true))
{
XDocument xDoc = doc.MainDocumentPart.GetXDocument();
XElement bookMarkPara = [get bookmarkPara to replace];
bookMarkPara.ReplaceWith(new XElement(PtOpenXml.Insert, new XAttribute("Id", insertKey)));
doc.MainDocumentPart.PutXDocument();
}
templateDoc.DocumentByteArray = mem.ToArray();
}
return templateDoc;
}
2> Use document builder to merge
List<Source> documentSources = new List<Source>();
var insertKey = "INSERT_HERE_1";
var processedTemplate = GetProcessedTemplate([docPath], insertKey);
documentSources.Add(new Source(processedTemplate, true));
documentSources.Add(new Source(new WmlDocument([docToInsertFilePath]), insertKey));
DocumentBuilder.BuildDocument(documentSources, [outputFilePath]);