I have an Excel Workbook ("test.xlsx") that has a cell named "gv_epxsize". My goal is to open the excel workbook and write down the string "101" in the cell with the name "gv_epxsize".
The problem is that my code keeps making the file Read Only, so it will not write the string "101" to the named cell. I keep receiving a windows prompt that I already have the file open with Windows privileges and asks if I want to open a Read Only copy. The problem is that I don't have the file open, and there is no EXCEL.EXE process running before I initiated the code.
What I've already done:
I've saved the file as a different name in a different folder - still no luck.
The file is not saved in a shared folder.
I have made sure my TaskManager has every EXCEL.EXE process killed before I run my code.
Can someone please show me what I'm doing wrong here?
Here's the snippet of C#
string filePath = "C:\\Users\\ussatdafa\\Desktop\\Work\\Projects\\test.xlsx";
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
MessageBox.Show("Excel has not been properly installed");
}
else
{
//string fileName = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), filePath);
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Workbooks wbs = excelApp.Workbooks;
Workbook wb = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);
wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";
}
I'm honestly not sure what's going on, but I have two observations:
You are opening Excel twice -- that appears to be certain. One instance is xlApp and the other is excelApp. If you open your task manager on the instantiation of excelApp I'm pretty sure you will find two instances of Excel running. I have no idea if that's contributing to your issue or not
I always found it helpful, when debugging, to make Excel visible. You can always comment that line out before you deploy, but during debugging it's nice since exposing COM objects during debugging isn't as helpful as native .NET objects -- this way you can see it in its native form
I ran a version of your code with these changes and had no issues changing the cell value of the named range "gv_epxsize."
string filePath = "C:\\Users\\ussatdafa\\Desktop\\Work\\Projects\\test.xlsx";
Microsoft.Office.Interop.Excel.Application excelApp =
new Microsoft.Office.Interop.Excel.Application();
if (excelApp == null)
{
MessageBox.Show("Excel has not been properly installed");
}
else
{
excelApp.Visible = true;
Workbook wb = excelApp.Workbooks.Open(filePath, 0, false, 5, "", "", false,
XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Worksheet ws = wb.Sheets[1];
wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";
}
This worked flawlessly for me. Here is proof:
So that leads me to several possibilities:
(Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);
Isn't what you think it is. Or perhaps, it's not the same as what I used, which was:
Worksheet ws = wb.Sheets[1];
Which will return the first worksheet ("Sheet1" on a new workbook).
And of course, there is the possibility that having two Excels open is causing issues.
I am pretty sure your issue is with WHERE in your code you are saving the file. From your posted code, there is one thing that does not really work and could explain your problem. Take a look at the following snippet:
else {
//string fileName = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), filePath);
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Workbooks wbs = excelApp.Workbooks;
Workbook wb = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);
wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";
}
This is the else portion of the if (xlApp == null) statement. First in this else portion you create a NEW Excel application called excelApp with:
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Why you are doing this is unknown since you have already created one earlier called xlApp. But this is still ok; you are allowed to open more than one Excel application.
Then open the file and make changes:
Workbooks wbs = excelApp.Workbooks;
Workbook wb = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);
wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";
You open a workbook using the filePath and call the woorkbook wb. Then grab the first sheet in wb and assign it to a worksheet variable ws. Keep in mind you OPEN the workbook in this else clause. Make the changes to the workbook and then exit the else clause. All seems OK EXCEPT… since we have exited the else clause... excelApp, wbs, wb and ws variables NO LONGER EXIST. Even if you tried to save or close the file outside this else clause you will have no way to reference it because you CREATED those variables inside the else clause.
Since you can not create a new variable named wb if it already exist... Then it is clear the workbook wb is never getting saved or closed.
I put the following lines INSIDE your else clause and was able to open the file correctly even with your program running. It is clear you may be saving and closing the file somewhere later in your code but it’s not the file you opened in this else clause.
else {
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Workbooks wbs = excelApp.Workbooks;
Workbook wb = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);
wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";
wb.Save();
wb.Close();
excelApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
}
Hope this makes sense.
Related
I'm trying to ensure that an excel file passed to my application is opened in it's own window rather than an existing Excel instance. Is there a way of telling the Process to do this? The following code always uses an existing instance if present.
Process process = new Process();
process.StartInfo.FileName = myExcelFile;
process.Start();
thanks
Matt
Try the following.
Process process = new Process();
Process.Start("Excel.exe", myExcelFile);
Other option is, if you use Interop (i.e. Microsoft.Office.Interop.Excel.dll ), you can do it as follows. This will always open the file in a new instance.
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
string workbookPath = (#"C:\Sample.xlsx");
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
I have a wpf application that opens/creates excel files and reads/writes to them. In the normal way of the application running, no excel window is shown to the user.
The Scenario:
Through my application, I browse to excel file "AAA.xlsx", and the application loads it. Then, I try to browse to another excel file, but while on the browse window I choose excel file "BBB.xlsx", right click it and select open, Excel launches with both files open.
If I do the same routine, but beforehand I had the Excel program already open(with or without a file loaded), only the selected file will open.
Below is the constructor
public ExcelManipulator()
{
excelApp = new Excel.Application();
excelApp.Visible = false; //not making any difference
excelApp.IgnoreRemoteRequests = true; //not making any difference
workbooks = excelApp.Workbooks;
workbook = workbooks.Open(path);
...
}
My ultimate goal is the excel files that my application has loaded to be invisible from the user's screen.
I think you are referring to separate 'instances' of Excel.
Try the following.
Process process = new Process();
Process.Start("Excel.exe", myExcelFile);
Other option is, if you use Interop (i.e. Microsoft.Office.Interop.Excel.dll ), you can do it as follows. This will always open the file in a new instance.
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
string workbookPath = (#"C:\Sample.xlsx");
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
I have got an Excel workbook that is created with Excel.Interop. I save the workbook with workbook.SaveAs(path, XlFileFormat.xlOpenXMLWorkbook, "password", "password", false, false) and then need to close the workbook as a new worksheet will be appended at a later stage as part of some sort of automation.
When I try to open the workbook again with workbooks.Open(path, ReadOnly: false, Password: "password");, the process just hangs, nothing happens, i.e. no exception, nothing.
Below are snippets of what I am attempting:
var excelApplication = new Microsoft.Office.Interop.Excel.Application();
var excelWorkbooks = excelApplication.Workbooks;
var workbook = new object();
//Append means that the a new sheet will be added to the existing workbook, thus the book needs to be opened first.
if (Append)
{
Exception innerEx = null;
try
{
excelWorkbooks.Open(ExcelOutputPath, ReadOnly: false, Password: "password");
}
catch
{
innerEx = new Exception("FileNotFound");
};
}
//Lots of logic follows here
//and here
workbook.SaveAs(ExcelOutputPath, XlFileFormat.xlOpenXMLWorkbook, "password", "password", false, false);
workbook.Close(0);
Marshal.FinalReleaseComObject(workbook);
workbook = null;
What am I missing please?
For whoever comes across the same issue, it is because you need to specify the same password for the WriteResPassword parameter when trying to open the workbook. This is required since the workbook was originally saved with a WriteResPassword value
private void button1_Click(object sender, EventArgs e)
{
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(fileName, 0, true, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
range = xlWorkSheet.UsedRange;
xlAppDestination = new Excel.Application();
xlAppDestination.DisplayAlerts = false;
xlWorkBookDestination = xlAppDestination.Workbooks.Open(fileNameDestination, 0, false, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheetDestination = (Excel.Worksheet)xlWorkBookDestination.Worksheets.get_Item(1);
rangeDestination = xlWorkSheetDestination.UsedRange;
rangeDestination.Cells[1, 1] = (string)(range.Cells[14, 3] as Excel.Range).Text.ToString();
textBox1.Text = fileNameDestination;
//xlAppDestination.ActiveWorkbook.Save();
xlWorkBookDestination.SaveAs(fileNameDestination);
xlWorkBookDestination.Close(0);
xlWorkBook.Close(0);
xlCleanup();
}
I am trying to open one excel file, and transfer information from that file into another excel file, the destination excel file. The only problem is when it comes to saving. I open the destination file as not read-only, but when I try to saveas, it says that it is read-only. I make sure there are no extra excel tasks running in the background, it still happens. It works when I use save, but it does not reliably save over the destination file in the same location. I have yet to determine what pattern it takes, but I need to be able to overwrite the destination file in the same place every time, as this will be appending to old excel files that already exist. No matter what I do to the saveas statement, it always throws me back the read-only argument.
EDIT- I've tried to use the .Save() option, and turn off alerts. But instead of ignoring the alert to overwrite the destination file, it sticks it inside the Documents folder. Does anyone have experience with the behavior of the regular Save() method?
Did you right click on your excel file and check its properties to make sure the "Read-Only" property is not set?
rangeDestination.Cells[1, 1] = (string)(range.Cells[14, 3] as Excel.Range).Text.ToString();
textBox1.Text = fileNameDestination & ".xls";
I can't seem to find the proper way to open and close an excel file.
Here is what I have to open my file, which I find overly complicated:
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
Microsoft.Office.Interop.Excel.Sheets excelSheets = excelWorkbook.Worksheets;
Worksheet sheet = (Microsoft.Office.Interop.Excel.Worksheet)excelApp.Worksheets[2];
sheet.Select(Type.Missing);
I have no idea how to properly close it. I need to save it with the same path and make sure excel is not still running in the background after it is closed.
Can someone make it easy for me?
Thanks
Release the COM objects when completed...
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
# declare the application object
var xl = new Excel.Application();
# open a file
var wb = xl.Workbooks.Open("some_file.xlsx");
# close the file
wb.Close();
# close the application and release resources
xl.Quit();
#release the COM objects created as a final step:
Marshal.ReleaseComObject(wb);
Marshal.ReleaseComObject(xl);
Semi pseudo-code:
using Excel = Microsoft.Office.Interop.Excel;
# declare the application object
Excel.Application xl = new Excel.Application();
# open a file
Excel.Workbook wb = xl.Workbooks.Open("some_file.xlsx");
# do stuff ....
# close the file
wb.Close();
# close the application and release resources
xl.Quit();