Selection.InsertFile() not finding file despite it being in directory - c#

I am experimenting with the Microsoft.Office.Interop.Word namespace to do some manipulation of docx files, specifically programmatically merging them.
I created a simple test harness to try out some of the functionality and I am getting a file not found error despite the file being in the executing directory.
All I am trying to do is merge two docx files, doc1.docx and doc2.docx respectively. Again I am just playing around with this functionality at this point so I created a simple C# console app and have the following:
using Word = Microsoft.Office.Interop.Word;
//and in my method:
object defaultTemplate = #"Normal.dotm";
object missing = System.Type.Missing;
object outputFile = "out.docx";
Word.Application wordApplication = new Word.Application();
//using the default Word template
Word._Document wordDocument = wordApplication.Documents.Add(defaultTemplate);
Word.Selection selection = wordApplication.Selection;
//add files manually. THIS is where things are failing
selection.InsertFile("doc1.docx");
selection.InsertFile("doc2.docx");
I get an exception with the message "This file could not be found." in my first call to InsertFile(). I am certain the files exist in my debug directory, which is where this program is running. MSDN explicitly states that if you don't provide a path with your parameter it uses the current directory. It finds the template Normal.dotm fine. I feel like I am missing something simple here but have been messing with it for over a half hour with no luck. Does anyone have any suggestions on what I should be doing here? Thanks for reading!

Make sure for your path is available. use GetCurrentDirectory() to be sure your current directory is what you want. else use full path.

You also might need to set the default file path.
MyWordApp.Application.Options.set_DefaultFilePath()

Related

Issue in file access with absolute paths

I've created a .NetCore console application in which am trying to check if a file exists using its absolute path, but am facing issues, I always get a false response even though the file exists. Even though I pass absolute path as parameter to API, it always prefixes the current working directory, so the path gets evaluated as doesn't exists.
I'm running this code on a windows 10 desktop and the application is created using .NetCore 2.1. I've tried various different methods to evaluate the existence of file like FileInfo Class instance and File.Exists static method. They've failed so far. I've diagnosed the issue, but I couldn't find a way to fix it.
using System;
using System.IO;
namespace FileAccess
{
class Program
{
static void Main(string[] args)
{
FileInfo fileInfo = new FileInfo(#"‪D:\ScriptData\test.zip");
Console.WriteLine($"Full Name: {fileInfo.FullName}");
Console.WriteLine($"FileInfo.Exists: {fileInfo.Exists}");
Console.Write($"File.Exists with #: {File.Exists(#"‪D:\ScriptData\test.zip")}")
Console.ReadLine();
}
}
}
The output of the code is:
Full Name: D:\Work\Samples\FileAccess\FileAccess\bin\Debug\netcoreapp2.1\?D:\ScriptData\test.zip
False
False
Even though am passing the absolute path, it prefixes the current working directory to the path I've passed. I've checked the Access to the file, its all fine, still I get false as response for both the cases.
Screenshot of Error
Screenshot of Debug Info
Judging your screen shot and the output, there is an invisible character at the start of the file path. That will cause .NET not to recognize it is an absolute path and automatically it will make it an absolute path itself.
If you use this code, you will notice that the inserted ? causes the problem here:
System.IO.FileInfo fi = new System.IO.FileInfo(#"?D:\some_file.ext");
Which outputs: C:\Users\...\ConsoleApp8\bin\Debug\netcoreapp2.2\?D:\some_file.ext.
Instead of:
System.IO.FileInfo fi = new System.IO.FileInfo(#"D:\some_file.ext");
Which outputs: D:\some_file.ext.
If you put your code in a HEX editor, you will see there is indeed a character before D:.
Thank goodness you cut and paste your original code! I know you did because when I cut and paste your code I can see that you have invisible characters after the open quote and before the D:\.
These two lines look identical but they're not! Cut and paste them if you don't believe me!
Your code:
FileInfo fileInfo = new FileInfo(#"‪D:\ScriptData\test.zip");
Fixed code:
FileInfo fileInfo = new FileInfo(#"D:\ScriptData\test.zip");
Here's what the binary editor shows.
You've got E2 80 AA secretly stuck in your source code file at the beginning of your filename. Which happens to be the UTF-8 representation of the LEFT-TO-RIGHT EMBEDDING character.

Office Interop Word Mail Merge throws DISP_E_TYPEMISMATCH exception

My issue involves a word file which has a macro embedded from another company which we have to remove and then set a new data source path (xlsx spreadsheet). The macro must be removed because it already sets the data source which is not available anymore when we get the file. Now I'm looking for a possibility to change the data source (path) of said word file programmatically but can't find any that does the job only VB Code. We don't want to write another macro and inject it we only want to change the data source path before the user downloads the file. I'm free to use any library.
Can anyone please suggest me a way to change the data source of a word file programmatically?
Update:
I'm now working with the MS Office Interop Word Library and achieved what I was looking for (changing data source) but unfortunately the excel file is damaged afterwards and can't be opened anymore saying "invalid data format".
Code below:
Application app = new Application();
Document officeDoc = app.Documents.Open(toBeMerged);
var srcFile = #"C:\DataSource.xlsx";
FileInfo fileInfo = new FileInfo(srcFile)
{
IsReadOnly = false
};
officeDoc.MailMerge.CreateDataSource(srcFile);
officeDoc.Save();
officeDoc.Close();
app.Quit();
Update 2
I've set all the needed parameters.
officeDoc.MailMerge.CreateDataSource(missing, missing, missing, missing, missing, missing, missing, missing, srcFile);
The parameters are as following:
CreateDataSource(Name, PasswordDocument, WritePasswordDocument, HeaderRecord, MSQuery, SQLStatement, SQLStatement1, Connection, LinkToSource)
This throws a System.Runtime.InteropServices.COMException 0x80020005 (DISP_E_TYPEMISMATCH) exception but the word gets successfully generated. When I put the srcFile variable at the begining where it should belong the excel file gets like above mentioned damaged despite giving all the optional parameters.
Thanks in advance helping me solving my last issue.

Roslyn CodeFix can't find previously created AdditionalDocument

I am writing a C# Roslyn Analyzer & CodeFix which will create a new .txt file, based on some variables, if it doesn't exist and it will append a new line if it does.
The Analyzer and the creation of the file work perfectly using the following code in RegisterCodeFix Action:
var proj = document.Project.AddAdditionalDocument("file.txt",
"text content");
return proj.Solution;
Although, when I am trying to search the project's collection AdditionalDocuments it is empty, even if the file is created previously (and the project is saved, if that matters).
var doc = document.Project.AdditionalDocuments.FirstOrDefault(x =>
x.Name == "file.txt"); //doc is null
I tried adding the new file as a plain Document instead of an AdditionalDocument but the file.txt is created as a source code file file.cs and not as a .txt one, but, for a reason, I can find it as file.cs in the Project.Documents collection.
Any thoughts of how can I create a non-source code file in a CodeFixProvider and use it?
You need to apply the changes to your workspace after you've added the document:
workspace.TryApplyChanges(proj.Solution);
However, according to this link, it seems that a current bug means AddAdditionalDocument() doesn't persist the document beyond the workspace in memory, meaning the project will not have the new document when reloaded.
Also, AddDocument() will only add documents with an extension corresponding to the language of the containing project, for instance, calling AddDocument() on on a C# Class Library project, will rename the extension to '.cs' if not already so.

open specific word doc. depending on user selection c#

i currently have a word doc. file merging program and am attempting to open a specific word doc. depending on user selection.
// sample of code used:
string outputFolder = null;
...
// file selection
...
string outcomeFolder = outputFolder;
string outputFile = "Combined Folder " + fileDate + " # " + fileTime + ".docx";
string outputFileName = Path.Combine(outcomeFolder, outputFile);
in the program, outputFolder is selected by the user via a fileBrowserDialog
currently, the program runs correctly and merges the files in the folder selected by the user however it fails to open Microsoft Word as well as the outcome document merged.
i've attempted to use:
Microsoft.Office.Interop.Word.Application officeApp =
new Microsoft.Office.Interop.Word.Application();
...
// merging code
...
Document documentTest = officeApp.Documents.Open(outputFileName);
i've noticed that though the program fails to launch Word, Task Manager continues to create a new instance of Word. The merged document formed also cannot be deleted as it claims the file is currently in use. It's as if program it's opening in the background however not physically launching. The Task Manager instance of Word must then be killed before the merged file can be edited / deleted
Any suggestions as to remedy this? Am i missing something simplistic or is the issue due to the non-static file path? - if any additional information is required please ask. thank you
Update 1:
Since implementing the officeApp.Visible = true; the program now launches the file created which can then be edited / re-saved etc. However if i immediately run the program again, attempting to create another merged file within the same folder etc. I am presented with "RPC server is unavailable. (Exception from HRESULT: 0x800706BA)"
Update 2:
As listed above, I was getting a generic HRESULT error code which I have now since remedied. I moved the "new officeApp" into the "Merge" handler which seems to be allowing multiple merges in quick succession without throwing errors.
Update 3:
To make things more simplistic, i've experimented with implementing Process.Start(outputFileName); to open the document. This is due to the additional check box I am now introducing which allows the user to decide whether the merged doc. will be launched / presented once created. This new code also prevents the additional Word.exe's from being created if the file visibility is set to false.
thank you all for your suggestions and help.
Have you tried making Word visible?
officeApp.Visible = true;

Loading FlowDocument.xaml that is part of my solution

I created a FlowDocument.xaml in my current WPF project. What i want to do is when the user clicks a button the XAML document will be loaded in the code behind, have some data on the document modified, and then print it out. The sticking point is i don't know how load the flow document so that i can modify it.
When I do:
FileStream fs = File.Open("FlowDocument.xaml", FileMode.Open)
It says that it can't find the file. The file is part of the project and I'm guessing it gets packaged with the rest of the project when compiled.
Any help is appreciated
Assuming it is configured to be a Resource, then you can load it like so:
FlowDocument doc= Application.LoadComponent(new Uri("/Path/FlowDocument.xaml", UriKind.RelativeOrAbsolute)) as FlowDocument;
This looks like it might be a path/relative path issue...just for testing purposes, try specifying the entire physical/absolute path in the File.Open statement...
You could also do
string path = Directory.GetCurrentDirectory();
to check to see what the current directory is and then make sure that the file FlowDocument.xaml is in that directory

Categories

Resources