This question already has answers here:
How do I save an XLSM file as an XLSX file without prompting the user about lost data? [duplicate]
(1 answer)
Save a *.xlsm file as *.xlsx and suppress the pop-up
(1 answer)
Closed 13 days ago.
This post was edited and submitted for review 13 days ago.
I have a C# program that runs a macro existing inside an xlsm file and after this macro has finished its operations, I would like to save this xlsm as .xlsx file. This is the code that runs and saves the macro file as xlsx:
void RunMacro(string macroFilename, string xlsxFilePath)
{
Excel.Application app = new Excel.Application();
Excel.Workbook workbook;
workbook = app.Workbooks.Open(macroFilename);
app.Visible = true;
app.Run("Main");
workbook.SaveAs(xlsxFilePath, Excel.XlFileFormat.xlOpenXMLWorkbook);
app.Workbooks.Close();
app.Quit();
}
Now, the issue is that in the line workbook.SaveAs(), I will get a prompt like this from Excel:
So how can I make it programatically that "Yes" is the default option here and this prompt is automatically closed without needing to click on anything?
EDIT:
The following threads (linked as the reason for closing this question) are not a solution:
How do I save an XLSM file as an XLSX file without prompting the user about lost data?
Save a *.xlsm file as *.xlsx and suppress the pop-up
Basically, there are two proposed solutions in these threads:
Set application.DisplayAlerts = false and call workbook.SaveAs(xlsxFilePath, Excel.XlFileFormat.xlOpenXMLWorkbook);
This still results in a prompt coming up where it is necessary to select 'Yes'. Here is my code:
void RunMacro(string macroFilename, string xlsxFilePath)
{
Excel.Application app = new Excel.Application();
Excel.Workbook workbook;
workbook = app.Workbooks.Open(macroFilename);
app.Visible = true;
app.DisplayAlerts = false;
app.Run("Main");
workbook.SaveAs(xlsxFilePath,Excel.XlFileFormat.xlOpenXMLWorkbook);
app.Workbooks.Close();
app.Quit();
}
Use Workbook.SaveCopyAs(xlsxFilePath)
This method call does circumvent the Excel prompt, but the xlsx file that it produces is corrupted:
Here is the code:
void RunMacro(string macroFilename, string xlsxFilePath)
{
Excel.Application app = new Excel.Application();
Excel.Workbook workbook;
workbook = app.Workbooks.Open(macroFilename);
app.Visible = true;
app.Run("Main");
workbook.SaveCopyAs(xlsxFilePath);
app.Workbooks.Close();
app.Quit();
}
Related
This question already has answers here:
Clean up Excel Interop Objects with IDisposable
(2 answers)
Why does Microsoft.Office.Interop.Excel.Application.Quit() leave the background process running?
(3 answers)
Closed 4 years ago.
I'm reading/writing an excel file using Interop library like so
(Update: this isn't a duplicate of Why does Microsoft.Office.Interop.Excel.Application.Quit() leave the background process running?, this question is about how to release excel from memory when there is an exception)
var myExcelApp = new Microsoft.Office.Interop.Excel.Application();
Excel.Workbooks AllWorkbooks= xlApp.Workbooks;
Excel.Workbook MyWorkBook= //Open workbook
Excel.Worksheet MySheet= //Open worksheet
//Do the work
MyWorkBook.Close(false, file);
myExcelApp.Quit();
Marshal.FinalReleaseComObject(myExcelApp );
//FInalReleaseComObject for MyWorkBooks
This works OK except when an exception is thrown, and then Excel lingers on in the background and has to be killed off using the task manager.
I'm not sure what the best way is to release these COM objects. Should I use the using blocks, or should I enclose everything in try catch like this?
Excel.Workbooks AllWorkbooks= null;
Excel.Workbook MyWorkBook=null;
Excel.Worksheet MyWorkshet=null;
Excel.Application myExcelApp=null;
try{
//Read file here
}
catch{
MyWorkBook?.Close(false, file);
myExcelApp?.Quit();
Marshal.FinalReleaseComObject(myExcelApp );
//FInalReleaseComObject for MyWorkBooks
}
Is the above the correct approach? I have to initialize excel objects as null, because they cannot be newed up.
Thanks
I have created a number of unit tests. At the beginning of each test I open a blank excel workbook on the TestInitialize however for this particular test I need to open another excel workbook. I want to open it inside the blank workbook opened on the TestInitialize . I tried doing the following however it opens them as 2 separate workbooks.
Any ideas why this is happening?
My code is as follows
using xl = Microsoft.Office.Interop.Excel;
private static string columnChartTemp = #"Testing\V8\TestMaster\V8.6\Testing\V8.6.0.11 Testing\columnChart.xlsx";
var excel = (xl.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
var myWorkbook = excel.Workbooks.Open(columnChartTemp);
excel.Visible = true;
A workbook is a file containing one or more worksheets (tabs.) You can't open a workbook inside of another workbook.
It sounds like you want to take a worksheet that's in a workbook and add it to another workbook. You can do that. Open both workbooks and copy the sheet from one to the other.
at the moment my current process is as followed. Query database - > Save file locally -> Open Workbook using Excel Interop Dll, Make Changes To Work Book, Save As using Excel Interop Dll. The reason for save as is because I require some addition settings so the file isn't set to read only.
The issue I'm coming across is that it's saving locally twice. First time is fine, second time a prompt will appear asking if I would like to override. I'm wondering how can I remove the Save File Locally process and have it in memory to work with? If I am able to work with the file in memory, I would have the prompt on Save As asking me if I would like to override the previous file.
Code:
//Save File Locally
System.IO.File.WriteAllBytes(saveFileDialog.FileName, Report.FileArray);
var fileLocation = saveFileDialog.InitialDirectory + saveFileDialog.FileName;
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
// Open Workbook Using Excel Interop Dll
Workbook wb = excel.Workbooks.Open(fileLocation);
Worksheet ws1 = wb.Worksheets.get_Item("English");
//Make Changes To WorkBook
ws1.Range["E5"].Value = StartDate;
ws1.Range["G5"].Value = EndDate;
// Save AS Using Excel Interop With shared settings to remove read only access
wb.SaveAs(fileLocation, AccessMode: XlSaveAsAccessMode.xlShared);
Process.Start(fileLocation);
You'd better disable the prompt, to what I remember this is possible but it imply a lot of umnaged code...
Try this
Microsoft.Office.Interop.MSProject.Application msProjectApp = new Microsoft.Office.Interop.MSProject.Application();
msProjectApp.DisplayAlerts = false;
Edit
Microsoft.Office.Interop.Excel.Application msProjectApp = new Microsoft.Office.Interop.Excel.Application();
msProjectApp.Visible = true; //show the application and not need to start a process
msProjectApp.DisplayAlerts = false;
//Save File Locally
System.IO.File.WriteAllBytes(saveFileDialog.FileName, Report.FileArray);
var fileLocation = saveFileDialog.InitialDirectory + saveFileDialog.FileName;
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
// Open Workbook Using Excel Interop Dll
Workbook wb = excel.Workbooks.Open(fileLocation);
Worksheet ws1 = wb.Worksheets.get_Item("English");
//Make Changes To WorkBook
ws1.Range["E5"].Value = StartDate;
ws1.Range["G5"].Value = EndDate;
// Save Only
wb.Save();
Remove Process.Start
excel.Visible = true;
excel.DisplayAlerts = false;
If you "own" the workbook and can set it up beforehand to play nice and are only loading in data, I find the OleDB Access SQL connection approach to be a better way to load raw data into SQL.
Is there anyway to save you entire workbook as a pdf in excel. I found this, http://msdn.microsoft.com/en-us/library/bb407651(v=office.12).aspx, but it does not exactly tell you if it saves the entire workbook as a pdf or just the active sheet. If there is no way to save the entire workbook to pdf, would printing the entire workbook be the best option, or even possible in C#? Below is what I have thus far I just need it to save as pdf so I can send in an email. Thanks for the help.
using Excel = Microsoft.Office.Interop.Excel; //Excel Reference
//Gets Excel and gets Activeworkbook and worksheet
Excel.Application oXL;
Excel.Workbook oWB;
Excel.Worksheet oSheet;
//Create New Instance in Excel
oXL = new Excel.Application();
oXL.Visible = true;
//Open Excel Workbook
oWB = oXL.Workbooks.Open("");
oWB = (Excel.Workbook)oXL.ActiveWorkbook;
oSheet = (Excel.Worksheet)oWB.ActiveSheet;
//Modify Excel Spreadsheet Based on Form
oSheet.Cells[6, 4] = maskedTextBox1.Text; //Change Value in Cell, Cell Location [y-axis, x-axis]
//Save Workbook As
oWB.SaveAs("");
//Save Workbook As PDF
//Close Workbook
oWB.Close("");
//Quit Excel
oXL.Quit();
In 2010 you can save the entire workbook in PDF by making each sheet an "Active" sheet.
Sounds strange but if you notice the print options when you do a pdf there is no option for workbook. To get around this open an excel file and fill in some data in 2-3 work sheets. Now hold your ctrl key and click on each other workbook, it will then become a "Group".
You will notice the [GROUP] name appear at the top of the excel file and now when you print the excel file it will print the entire workbook.
Try this out for yourself. In code, you just need to make each work sheet an active worksheet. I don't work much with the excel object model but it might be worth doing a macro for this and looking at the code.
I recorded a macro and here is the VBA:
Sheets(Array("Sheet1", "Sheet2", "Sheet3")).Select
Looks as though you just need to store each sheet in an array and then simply
Sheets(MyArray).Select
This will then make all sheets active and [grouped] and then you can run a print out to pdf. By recording the macro it also presented the options to print to pdf:
`ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
"C:\Users\MyAccount\Desktop\test.pdf", Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:= _
True`
In this case active sheet is your group of sheets that you have stored in an array.
I can create an instance of Excel using:
Microsoft.Office.Interop.Excel.Application gXlApp = new Microsoft.Office.Interop.Excel.Application();
gXlWb= gXlApp.Workbooks.Add(Missing.Value);
gXlApp.Visible = true;
gXlApp.DisplayAlerts = false;
BUT is there a way to "point" gXlApp at an instance of Excel that is already open?
Currently I have to start Excel from c# then open the workbook and run my code.