static void Main()
{
Application excelapp = new Application();
Workbook book = excelapp.Workbooks.Open(#"C:\HWYFAB.xlsx",
0, false, 5, "", "", false, XlPlatform.xlWindows , "",
true, false, 0, true, false, false);
Worksheet sheet = (Worksheet)book.Sheets[1];
Range cell = (Range)sheet.Cells[3, 2];
Console.WriteLine(cell.Text);
cell.ClearContents();
book.Close(true, "HWYFAB.xlsx", false);
excelapp.Quit();
}
This program runs and exits as expected. It does print the correct value that's in cell B3 to the console. When closing it asks if I want to replace the existing file. I click yes. When I open the spreadsheet in Excel, the value is still in cell B3 despite the cell.ClearContents().
Any thoughts?
Your call to cell.ClearContents() will clear formulas and value constants from the cell. This should absolutely be working. You can confirm this after your call to cell.ClearContents() by testing if cell.Value2 == null, which should be true.
I believe that the problem with your code is in the call to book.Close(true, "HWYFAB.xlsx", false). The problem is that you are explicitly passing in the name of your workbook, but you are leaving off the path. (Note that when you open the workbook you are including the full path, including the "C:\" directory.) By leaving off the full path to the workbook when you save, you are saving to the current directory, which could be "My Documents" or anywhere else.
If you wish to save the workbook in-place, at its original location, then you should pass in Type.Missing for the Filename parameter. For example:
book.Close(true, Type.Missing, false);
This idea is untested, but I'm fairly confident that this should work for you. Give it a try...
-- Mike
Related
I have an excel application, that gets consolidated lists from SharePoint using power query. I have set the property to refresh on open of the excel application, to refresh the dataset. When I manually open the excel, it refreshes and i get the updated data. However, I am using this excel in my winform application to get the data.
So in order to refresh the data, i am trying to open and close the excel from code.
But the data doesn't get refreshed, and it screws up the power query addin. When I manually open the excel sheet again, after running the code i get the error "The query did not run, or the database table could not be opened."
And the Power Query is not seen anymore on the ribbon.
Below is the code i use to open and close the Excel application:
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
string workbookPath = #"C:\Test\Test.xlsx";
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
Excel.Sheets excelSheets = excelWorkbook.Worksheets;
string currentSheet = "Sheet1";
Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelSheets.get_Item(currentSheet);
Excel.Range excelCell = (Excel.Range)excelWorksheet.get_Range("A1", "A2");
excelWorkbook.Close(true, "Test.xlxs", null);
Is this the best way to refresh the data?
If your Power Query/BI implementation does not allow usage of the Data Management Gateway (DMG) as suggested by a previous poster, you may want to explore a new piece of software called Power Update to set the update to a schedule.
Plus you may be able to run their Excel data-source update tasks from within your C# application if this is part of the requirement.
Two things to be aware of.
Connections in excel default to background (asynchronous) refresh, which can make your programmatic refresh code non-deterministic.
Power Query does polling to update the status of the query refresh. So if you close the workbook right after the refresh the status won't have a chance to update and next time you open the workbook the status will indicate an error.
In order to get a reliable refresh, you will need to set the connections to no longer background refresh, so the refresh blocks, and then also sleep for a short time after the refresh to let Power Query's polling discover that the refresh is complete.
I would change your script to this
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
string workbookPath = #"C:\Test\Test.xlsx";
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
excelWorkbook.RefreshAll();
System.Threading.Thread.Sleep(2000);
excelWorkbook.Close(true, "Test.xlxs", null);
You could make this code even better by looping through the queries and setting them to not background refresh like this vba code does
https://social.technet.microsoft.com/Forums/en-US/9cbdd731-d139-49ee-8f30-89de371ba74d/multiple-queries-run-one-after-another?forum=powerquery#df2947a7-585a-4f75-8337-e0ead5068254
I'm trying to read data from excel file. My problem is when I finished reading it's always appear an dialog ask for save. How can I turn off it?
Here is my code:
Missing missing = Missing.Value;
Excel.Application _app = new Excel.Application();
Excel.Workbook _workBook = _app.Workbooks.Open(e.Argument.ToString());
Excel.Worksheet _workSheet = _workBook.ActiveSheet;
Excel.Range _range = _workSheet.UsedRange;
BackgroundWorker bw = sender as BackgroundWorker;
for (int i = 0; i < _range.Rows.Count; i++) {
if (_workSheet.Cells[i + 2, 1].Value != null && _workSheet.Cells[i + 2, 2].Value != null)
{
inputList.Add(new infoInput(_workSheet.Cells[i + 2, 1].Value, _workSheet.Cells[i + 2, 1].Value));
}
bw.ReportProgress(((i + 1) * 100)/_workSheet.UsedRange.Rows.Count);
}
_workBook.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(_workBook);
_app.DisplayAlerts = false;
_app.Quit();
P/S Sorry for my English! Thanks in advance.
You should set the DisplayAlerts property to FALSE to prevent this message when you call .Quit() method.
_app.DisplayAlerts = false;
_app.Quit();
_Application.Quit method:
If unsaved workbooks are open when you use this method, Microsoft
Excel displays a dialog box asking whether you want to save the
changes. You can prevent this by saving all workbooks before using the
Quit method or by setting the DisplayAlerts property to False. When
this property is False, Microsoft Excel doesn’t display the dialog box
when you quit with unsaved workbooks; it quits without saving them.
have you tried something like this
_workBook.Close(SaveChanges:false)
or
WB.Close(false, Type.Missing, Type.Missing);
according to this link:
http://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.workbook.close.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
if you omit this parameter, a save dialog will appear.
If there are no changes to the workbook, this argument is ignored. If
there are changes to the workbook and the workbook appears in other
open windows, this argument is ignored. If there are changes to the
workbook but the workbook does not appear in any other open windows,
this argument specifies whether changes should be saved, as shown in
the following list.
true. Saves the changes to the workbook. If there is not yet a file
name associated with the workbook, then FileName is used. If FileName
is omitted, the user is asked to supply a file name.
false. Does not save the changes to the workbook.
Omitted. Displays a dialog box asking the user whether or not to save
changes.
I had this same problem. All the suggestions about macros, repairing MS Office, etc. were no help at all -- although they were related to the problem ...
It turns out that I accidentally changed a date in one cell of the spreadsheet from a valid date -- ex: 02/06/2021 -- to the letter "H". I don't know when I did it, but it was not a temporary change -- i.e., I apparently hit Enter or an arrow kay after the change. Interestingly, that cell was NOT linked to any macros or formulas; it just was formatted as a date. When I repaired the date, and saved the spreadsheet, the problem went away for good.
I have a WinForms app written in C# that uses the following code to open an Excel Template, prior to exporting data from a SQL database into the Worksheets of the Template.
Microsoft.Office.Interop.Excel.Application oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = true;
oXL.DisplayAlerts = false;
Microsoft.Office.Interop.Excel.Workbook mWorkBook = oXL.Workbooks.Open(path, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Excel.Worksheet mWorkSheet = mWorkBook.Worksheets["Invoice"];
However, this code actually opens the Template itself, so that any data exported from SQL into the workbook, is saved to the Template. What I want is to programmatically open a copy of the template in the same way this works when you double click a template directly in Windows Explorer and a copy is automatically created, without the original Template being touched.
How can I do this programmatically?
You can actually use the Workbooks.Add function of your Excel Application object, and pass in the template path as a parameter. Any future changes that you do programmatically will be done to an as-yet-to-be-saved copy in memory.
I've found that this is useful when you want to prepare / preformat a new excel workbook for a user to interact with later.
string templatePath = "c:\\temp\\template.xlsx";
Workbook wb = oXL.Workbooks.Add(templatePath);
//wb will be a memory copy of template.xlsx
then copy the file you want to open to the destination of your choice and open the copy...
System.IO.File.Copy(sourceFile, destFile, true);
the sourcefile is the original file;
the destFile is your copy
and you open the destfile with oXL.Workbooks.Opeen("path to destfile",....)
So your original file is never touched:)
Im trying to pass 8 string values in to a row in an already existing excel spreadsheet and then be able to select that row programmatically using C#. I am using a Windows Service with a file system watcher that is constantly monitoring a directory for a file to be added once the file is added it needs to extract the file contents in to object properties and then write them to an excel sheet. Would anyone have any idea how to do this without having to pay for any additional excel extensions? I am using excel 2007 and Visual Studio 2012. Any help would be much appreciated.
Thanks
Bernard
Hi I actually got it working there. I used the following code to write to a specific cell in an already existing excel sheet:
string path = #"C:\ProjectTesting\TwsDde.xlsm";
oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = true;
oXL.DisplayAlerts = false;
mWorkBook = oXL.Workbooks.Open(path, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
//Get all the sheets in the workbook
mWorkSheets = mWorkBook.Worksheets;
//Get the allready exists sheet
mWSheet1 = (Microsoft.Office.Interop.Excel.Worksheet)mWorkSheets.get_Item("Basic Orders");
Microsoft.Office.Interop.Excel.Range range= mWSheet1.UsedRange;
mWSheet1.Cells[12, 1] = "bla bla bla";
This code was taken from this article which also goes on to save the excel sheet:
http://rmanimaran.wordpress.com/2011/02/15/programmatically-insert-to-existing-excel-file-using-c/
I hope this helps somebody else.
Thanks
Bernard
I'm trying to open an excel workbook and trying to get a worksheet in it. Excelapp.workbooks.Open line is throwing an Exception as
System.Runtime.InteropServices.COMException from HRESULT: 0x800A03EC at Microsoft.Office.Interop.Excel.Workbooks.Open
Here is my code:
Excel.Application excelApp = new Excel.ApplicationClass();
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(strWBPath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, true);
StrWbPath is my Excel location. I'm refering to 2007 excel and added Microsoft.office.interop.excel of version 12.0.0.0.
(Sorry for answering this old question, but it's google result #1 for this problem and the correct answer is missing).
The error occurs because excel thinks the Workbook has been corrupted. When opening the Excel file, the last parameter tells excel how to handle this situation. Pass Microsoft.Office.Interop.Excel.XlCorruptLoad.xlExtractData to instruct it to retrieve the data (This will open a popup telling the user excel tried to extract the data if the file is corrupted).
However, I noticed this problem can also be caused if the workbook you are trying to open has a different locale than your excel (was saved on a machine using another language setting) OR your system not having the en-us locale set.
While this is extremely stupid, it's easy to overcome. For me the solution was to just set the current locale to en-us before opening the file:
static System.Globalization.CultureInfo oldCI;
oldCI = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
xlWorkBook = xlApp.Workbooks.Open(filePath, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, Microsoft.Office.Interop.Excel.XlCorruptLoad.xlExtractData);
System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
credit goes to this page
What if you try System.Reflection.Missing.Value instead of Type.Missing?
Regards,
M.
Which class are you using?
Microsoft.Office.Interop.Excel.ApplicationClass
if this then try changing it to
Microsoft.Office.Interop.Excel.Application
In case it helps someone else, I lost tons of time on this one. I was passing Microsoft.Office.Interop.Excel.XlCorruptLoad.xlRepairFile for the CorruptedLoad parameter for all files, thinking it meant "open the file, and if it's corrupt, attempt a repair". This worked for most files.
However, for some files, I was still getting the exception (Exception from HRESULT: 0x800A03EC). Yet if you open the file in Excel manually, it is not corrupt.
It turned out that for those files, you must not supply the CorruptedLoad parameter. Then it opens successfully. So in the end I adjusted my code to first try without any CorruptedLoad parameter, and only if that returns the exception, then try passing xlRepairFile for that parameter. I also adjusted my understanding of that parameter to mean "open and repair this file regardless of whether it's corrupt".