Can't open bound excel file in C# project - c#

I have an excel file in my project which is listed as resource.
Now I try to open it with a button click like this:
private void Button_Click_Blist(object sender, RoutedEventArgs e)
{
Excel.Application xl = new Excel.Application();
Excel.Workbook wb = xl.Workbooks.Open("Blist.xlsx");
}
My problem is that it says that it can't find the file and throws this exception:
System.Runtime.InteropServices.COMException
We couldn't find 'Blist.xlsx'. Was the object perhaps moved, renamed,
or deleted?

This code uses OLE Automation to start Excel and tell it to open a file in the relative path Blist.xlsx. The executable in this case is Excel, not your own application. The relative path will be resolved using Excel's working directory.
To avoid this problem, pass the absolute file path to Excel :
var fullPath=Path.GetFullPath("Blist.xlsx");
Excel.Workbook wb = xl.Workbooks.Open(fullPath);
Another possibility, which gives no control of (or dependency on) Excel, is to just "start" the file with Process.Start, eg :
Process.Start("Blist.xlsx");
Or
var fullPath=Path.GetFullPath("Blist.xlsx");
Process.Start(fullPath);
The Windows Shell will find the application that can open this document based on its extension and start it, passing the file path as an argument. This can start Excel, Libre Calc or any other application registered to open this particular file extension.

So I tried this and apparently the .Open() method some extra complexety with relative paths (see #PanagiotisKanavos comment). You can make a work around, by getting the current directory path, and pre-pending it, giving the absolute path of the file:
string filename = "Blist.xlsx";
string currentPath = Directory.GetCurrentDirectory();
var xl = new Microsoft.Office.Interop.Excel.Application();
var wb = xl.Workbooks.Open(currentPath + "\\" + filename);
xl.Visible = true;
However, you should (almost) never use hardcoded file names in your code. So the above solution is just an example, not something to copy into production code...

Related

SSIS Report: How to rename an excel file in a specific location

We get an excel file in a specific location where the name of the file may vary every time.
So every time we rename the excel file manually to "Report.xlsx" and then we have some operation to be done using a script task. The file_Path + file_Name is hardcoded in the script task as
Microsoft.Office.Interop.Excel.Workbook workBook = excelApp.Workbooks.Open(#"D:\Desktop\Report.xlsx");
Is there a way to get the file name from the file location and pass it to the above code ?
Note:
The file Path is static but the file name will vary every time.
At a time there will be only one excel file in the file Path.
We are already using a Sequence Container so cant change it.
Thanks in advance..
This will let you use the actual file name. Make sure to reference System.Linq
var dir = new System.IO.DirectoryInfo(#"D:\Desktop");
var fullFilePath = dir.GetFiles("*.xlsx").Select(f => f.FullName).First();
if(fullFilePath != null)
Microsoft.Office.Interop.Excel.Workbook workBook = excelApp.Workbooks.Open(fullFilePath);

Excel File created as read only

I have created an Excel Add-in using VSTO in C#. I want to create a new Excel file from a template located on a SharePoint site. A file picker dialog box is used so the user can chose which file to use as a template. Everything works fine exept the new workbook is created as read only. If I copy the template file on my computer, and use the same program to pick that file as a template, the new workbook is not created as read only.
The file on the sharePoint is not being open elseware when creathing the new file. Is there a way to specify the sharePoint library is a safe source? Or to set the newly created workbook readonly property to false?
{
string pathSP= #”\\Business.sharepoint.com#SSL\teams\group\NDC\”;
if (System.IO.Directory.Exists(pathSP))
{
Excel.Application excelObj = Globals.ThisAddIn.Application;
Office.FileDialog fileDialog = excelObj.FileDialog[Office.MsoFileDialogType.msoFileDialogFilePicker];
fileDialog.InitialFileName = initialPath;
fileDialog.AllowMultiSelect = false;
fileDialog.InitialView = Office.MsoFileDialogView.msoFileDialogViewDetails;
fileDialog.Title = "Create Excel file from template";
fileDialog.Filters.Clear();
fileDialog.Filters.Add("Excel template", "*.xls; *.xlsx; *.xlsm; *.xltx; *.xltm; *.xlt", 1);
string TemplatePath;
if (fileDialog.Show() == -1)
{
templatePath = fileDialog.SelectedItems.Item(1);
fileDialog = null;
}
else
{
templatePath=""
fileDialog = null;
}
if (templatePath != "")
{
Excel.Workbook ws= excelObj.Workbooks.Add(templatePath);
}
}
else
{
MessageBox.Show("SharePoint site is not available", "Create Excel file from template", MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
}
}
for the two ways you mentioned:
set the share point library as a safe source - this can be achieved by setting the excel setting: Options -> Trust Centre -> Trust Centre Settings -> Trusted Locations -> add the sharepont location
set the file access (readonly=false) at the end of your process
Actually as a general practice when dealing with template file (not limited to excel), the system should copy the template file to a local temp location (ideally the running user's TEMP folder), use it and then delete it afterwards. this way would avoid all kinds of problems such as file-lock-by-other-user/process problems.
So I think your problem is the Workbooks.Add(). Check out what Microsoft says about it:
[Workbooks.Add()] Determines how the new workbook is created. If this argument is a string specifying the name of an existing Microsoft Excel file, the new workbook is created with the specified file as a template.
I believe the workbook you're creating is a carbon copy of whatever the sharepoint server has, including permissions. The fact it works locally is another clue that sharepoint might be fiddling with permissions.
I suggest try saving a copy of the file locally. You can even use the SaveFileDialog object to give the user a GUI to save their new copy.
SaveFileDialog userSaveFileDialog = new SaveFileDialog();
userSaveFileDialog.Filter = "Excel 2007 and later | *.xlsx, Excel Macro Enabled Worksheet | *.xlsm, I'm guessing this is a 2007 template | *.xltx, Template Macro maybe | *.xltm, I almost definitely think this is a template file | *.xlt";
userSaveFileDialog.Title = "Save an Excel File";
userSaveFileDialog.ShowDialog();
this.Application.ActiveWorkbook.SaveCopyAs(#userSaveFileDialog.FileName);
Once you're done, you can programmatically open the newly saved workbook using userSaveFileDialog.FileName as your filepath.

C# Excel unable to copy worksheet

I am working on a web App where user can upload an Excel file and I need to copy data from the user worksheet to a destination worksheet in order to do some calculation. To do so, I have the following code:
public class ExcelCtrl
{
private Excel.Application excelApp = null;
private Excel.Workbook srcworkbook = null;
private Excel.Workbook destworkbook = null;
public void excel_init(String srcpath, String destpath, string copyrange)
{
//Open Excel
this.excelApp = new Excel.Application();
//Open user's file
this.srcworkbook = excelApp.Workbooks.Open(srcpath);
Excel.Worksheet srcworksheet = (Excel.Worksheet)srcworkbook.Worksheets.get_Item(1);
//Open calculation file
this.destworkbook = excelApp.Workbooks.Open(destpath);
Excel.Worksheet destworksheet = (Excel.Worksheet)destworkbook.Worksheets.get_Item(1);
//Range of copy
Excel.Range from = srcworksheet.get_Range(copyrange);
Excel.Range to = destworksheet.get_Range(copyrange);
//Copy
from.Copy(to);
//Close user's file
srcworkbook.Close();
//Open Xla file
excelApp.Workbooks.Open("someXlaFile.xla");
excelApp.Workbooks.Open("AnotherXlaFile.xla");
}
Basically I have to different method to run different calculations and they have the following structure. What differ one calculation method to another are just the macro called, the number of macro and the copy range.
public static string Calculation1(String InputFileName, String CurDir)
{
//The Excel calculation file and its path
string filename = "CalculationFile.xls";
string path_server = ExcelCtrl.DossierCalcs + filename;
ExcelCtrl excel = new ExcelCtrl();
excel.excel_init(CurDir + "\\" + InputFileName, ExcelCtrl.DossierCalcs + filename, "A1:Z105");
//excel.excel_run("Macro1");
//The rest is not important
path_server = CurDir + "\\Resultats - " + InputFileName;
excel.excel_run("AnotherMacro", path_server);
excel.excel_close();
return path_server;
}
Now all work fine, except one calculation (the one above). I am unable to copy data from the user worksheet.
I have tested to :
(normal usage) upload an Excel file with some new data and when I download the file after calculation, it is still the old data.
reduce the range of copy ( I though maybe it is too big) to "A1:Z50" then "A1:A2". However, I have another calculation file where I copy a range of "A1:M730" and it works fine.
copy it manually with Ctrl + C; Ctrl + V (I thought maybe the worksheet is protected from modification or something)
With the first 2 tests, I still got old data (not the user data) and the last one works, I can paste user data; though not very useful if someone need to do it manually everytime an user ask for this calculation.
I hope this is enough for you to understand my problem and hope you can guide me.
Thanks
EDIT
Hello,
Just to clarify a little bit about what I am doing. I have an web app where user can download an Excel xlsx file and they have to fill in with their data. After that, They have to upload their file to the server and choose the calculation they want to run. On the server side, I copy their data (see code above) to the corresponding Excel calculation file. So for each calculation I have one input file for the user and one calculation file to run. In total I have 14 input files and 14 calculations files and 13 of them work fine.
I have done some more tests, the following tests do not copy my data :
(And I am using Excel 2010)
Changing the name of my destination Excel file to something more common because there were a "#" in the file name.
Changing the name of my destination Excel file to one another destination file where the copy works.
Changing the worksheet color (I really don't believe that will solve my problem but I have nothing to lose)
Deleting worksheets from my destination file one by one
And the following tests work (data are copied to the destination file) :
Copying to a new Excel file
Copying to an other Excel calculation file (let's say file B) where I know the copy works
My thought for the last case is because when I open my problematic Excel file, 2 warnings come up. The first one says that the workbook contains link to other data sources and ask me if I want to update it (even after updating, it keeps asking me everytime I open it) and the second one says that the workbook contains links that can not be updated.I have also this 2 warnings when I open file B but with this file the copy works.
So I have tried to delete all links in the file and it does not work either. Futhermore, those links are used in my 13 others files.
I am kind of lost now since I have deleted all worksheet and links from my Excel file and it still won't copy. The only difference I see between my problematic file and a new file is that the former contain Macro.

Open Excel with password in C#, and close the excel externally

I am looking for a way to open the password protected Excel file in Excel from my c# program.
Please notice I just need to open it for my user. I am not looking for something like Excel Interop to modify the file.
For a file that has no password, I can simply launch the process start with the full path file name as a parameter. But this one has password in it, so it can't be done like this.
If I use Excel interope to open it, I can open it, but the Excel process will leave there when user close the Excel window.
var excelApp = new Excel.Application();
excelApp.Visible = true;
var wb = excelApp.Workbooks.Open(#"d:\temp\test.xlsx", Password:"1234");
Since user will be modifying the file in the Excel window and then close the windows. This part is out of my control. I simply just want to launch the file, then I don't have to care about it. But by using Excel interope, the COM is actually referecing back to my c# program, so that the whole Excel process can't be disposed completely.
I think I know a workaround for it.
Create a helper C# console application called OpenExcelWorkbookWithPassword.exe which looks like that:
static void Main(string[] args)
{
var excelapp = new Excel.Application();
excelapp.Visible = true;
Excel.Workbook workbook = excelapp.Workbooks.Open(args[0], Password: args[1]);
}
and use this from your main application with the following code:
string path = #"d:\temp\test.xlsx";
string pw = "1234";
System.Diagnostics.Process.Start("OpenExcelWorkbookWithPassword.exe", path + " " + pw);
When the user is closing Excel the Excel.exe process will be terminated even if your main application is still running.

Running macros through code on server: Wrong path to excel file?

In my application I open a .xlsm file with a macro (copies data to .xlsm file) and a .xlsx file that executes that macro. Let's say my files are called FileWithMacro.xlsm and FileThatExecutesMacro.xlsx. I need this application on a server but have developed it locally. To debug the application, I put my files to C:\Users\myUser\Documents\.
I'm opening the FileWithMacro.xlsm like this:
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open(serverPath + "FileWithMacro.xlsm");
Excel._Worksheet worksheet = workbook.Sheets["FileThatExecutesMacro"];
After that, I call the method that runs the macro:
RunMacro(serverPath + "FileThatExecutesMacro.xlsx");
My method looks like this:
private static void RunMacro(string source)
{
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open(source);
Excel._Worksheet worksheet = workbook.Sheets[1];
worksheet.Activate();
try
{
excelThatRunsMacro.Run("FileWithMacro.xlsm!MyMacro");
workbook.Save();
excelThatRunsMacro.Quit();
}
// and so on
}
Locally the macros work without any problems. When I change all the paths and copy the output of my code to the server (\\myServer\someUrl...), I'm getting the following exception:
'C:\Users\myServerUser\Documents\FileWithMacro.xlsm' could not be found.
Although I changed all my paths to the correct server location (and I am really sure that there is no local path in my code and in the macro anymore). I even deleted my bin and obj folders and rebuilt the project but that didn't change anything. I even created a new project and built it without using local paths but I got the same error. What am I doing wrong? Is excel.Run by default searching the macro in the Documents folder?
Or is the problem because of the line Windows("FileWithMacro.xlsm").Activate in my macro? When running the macro manually, it works fine. It just doesn't work when running it through the code.
I couldn't find out why I got the exception. However, I've found a workaround. Before executing the macro, I copy the FileWithMacro.xlsm to the location in the error message. When I then used the code like I've had it, I've got a message that the FileWithMacro.xlsm is already in use. To fix this, I just had to pass the Excel.Application to my method and use this instance instead of creating a new one:
private static void RunMacro(Excel.Application excel, string source)

Categories

Resources