I'm using the following library:
http://mikesknowledgebase.azurewebsites.net/pages/CSharp/ExportToExcel.htm
Here is my code:
private void exportExcelBtn_Click(object sender, EventArgs e)
{
if (dataGridView1.Rows.Count == 0)
{
MessageBox.Show("There's nothing to export", "Info", MessageBoxButtons.OK);
return;
}
DataTable save = Utilities.DataGridView2DataTable(dataGridView1, "TestingReport");
string outputFile = Utilities.saveDoc(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), save);
if (outputFile != null)
{
DialogResult opt = MessageBox.Show("Export successful. Would you like to view the file?", "Information", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
if (opt == DialogResult.Yes)
{
System.Diagnostics.Process.Start(outputFile);
}
}
}
I am using this same exact code in two different projects, however in one project the excel files it creates are corrupted/unreadable.
When extracting the contents of the .xlsx file, the first thing I notice is that the [Content_Types].xml file present in the working project isn't in the output from the project that isn't working. Also, the workbook.xml files created are both 0kb whereas the working project files actually have data in them.
I have tried doing Console.WriteLine.
I'm also using this code to convert my DataGridView to a DataTable so it can be written to excel: https://www.crealoq.com/solved/how-to-convert-datagridview-to-datatable-using-csharp
I've gone through and added Console.WriteLine(...) to verify that data is actually being returned from this function and everything looks fine.
EDIT:
The only difference I've noticed is that when I click the button to save the excel, and then choose NOT to view it right then, when I go to unzip the excel document, the app that returns a valid excel document lets me unzip it, however when I try to unzip the one that ISN'T working, it says the file is currently opened..
If your first column header is called "id" that could be causing problems. You can try prepending "`" to any column called "id"
Problem was that I had changed a part of code in CreateExcelFile.cs
This had the same effect as not closing a StreamWriter after being finished with it, and then missing a bunch of text because of that. I changed this block of code b/c it wasn't working without the WindowsBase.dll. After referencing that DLL and changing the code back I'm able to successfully export my datagridview to excel
I made something similar, also with a DataGridView.
First I get the values from the column I need(in my case it was only 1 column)
List<float> values = new List<float>();
for (int y = 0; y < rows; y++)
valores.Add(float.Parse(valoresMonitoreo[0, y].Value.ToString()));
Then the export function
private void export()
{
Microsoft.Office.Interop.Excel.Application oXL;
Microsoft.Office.Interop.Excel._Workbook oWB;
Microsoft.Office.Interop.Excel._Worksheet oSheet;
object misvalue = System.Reflection.Missing.Value;
try
{
oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = true;
oWB = (Microsoft.Office.Interop.Excel._Workbook)(oXL.Workbooks.Open(libro));
oWB.Sheets[x].Select();
//x is the number of the sheet where you want to save data.
oSheet = (Microsoft.Office.Interop.Excel._Worksheet)oWB.ActiveSheet;
//This goes into a for
oSheet.get_Range(tmp, misvalue).Value2 = values[x]; //tmp is a string, which contains letter and number of the cell "A1". misvalue is an object variable
oWB.Save();
oWB.Close();
oXL.Visible = false;
oXL.UserControl = false;
oXL.Application.Quit();
}
catch(Exception exc){}
}
You must use Microsoft.Office.Interop.Excel reference.
Try Flushing and Closing the HttpResponse request. This worked for me.
response.OutputStream.Flush();
response.OutputStream.Close();
response.Flush();
response.Close();
Related
I create a excel file using C#, and set the ConflictResolution parameter toExcel.XlSaveConflictResolution.xlLocalSessionChanges in SaveAs() function.
I also set the app.UserControl to false, but the prompt dialog will always show up.
what should I do to disable the dialog
string fileName = "f:\\ok.xlsx";
object missing = Type.Missing;
Excel.Application app = new Excel.Application();
app.Visible = false;
app.UserControl = false;
Excel.Workbook book = app.Workbooks.Add(missing);
Excel.Worksheet sheet = book.ActiveSheet as Excel.Worksheet;
sheet.Name = "s1";
sheet.Cells[1 , 1] = "id";
book.SaveAs(fileName , Excel.XlFileFormat.xlWorkbookDefault ,
missing , missing , missing , missing ,
Excel.XlSaveAsAccessMode.xlNoChange ,
Excel.XlSaveConflictResolution.xlLocalSessionChanges ,
missing , missing , missing , missing);
book.Close(missing , missing , missing);
app.Quit();
In order to disable Excel's alerts when writing a file, simply use .DisplayAlerts = false;
Example code that I currently use to save my Excel files:
public void SaveExcelFile(Excel.Application app, string exportPath)
{
try
{
//Stops from asking to overwrite
app.DisplayAlerts = false;
Excel._Worksheet sheet = app.ActiveSheet;
//Save and close
sheet.SaveAs(exportPath);
}
catch (Exception ex)
{
//If something fails, show the error
Console.WriteLine("ERROR: Failed to save Excel file! " + ex);
}
finally
{
//Makes sure that there aren't any lingering Excel processes
app.Quit();
}
}
Works like a charm for me. The important part of this snippet is the app.DisplayAlerts = false; line. This will stop from asking if you want to save the file or overwrite an existing file of the same name. If you aren't wanting to overwrite files automatically in a fear of losing data, then I don't recommend disabling the alerts.
Note: wrapping it all in a try-catch isn't always the best practice. For the complexity of the program that uses this method, I know where the error may occur (.SaveAs(exportPath); in case the supplied exportPath doesn't exist or is a mistype or whatever other reason for it to throw the error). Would probably be best to only wrap the sheet.SaveAs(exportPath); in the try-catch just to be certain.
I wrote a program in C# that is supposed to convert each worksheet in my excel workbook to a csv and save it in their own files. The problem I'm having is that when I open each file, they all have the same content as the very last worksheet. Here is my code:
public void Main()
{
Excel.Application excelApp = new Excel.Application();
Excel.Workbook workbook = excelApp.Workbooks.Open(#"C:\Users\user\Desktop\Book1.xlsx");
foreach (Excel.Worksheet sht in workbook.Worksheets)
{
sht.Select();
System.Diagnostics.Debug.WriteLine(sht.Name.ToString());
workbook.SaveAs(string.Format("{0}{1}.csv", #"C:\Users\user\Desktop\", sht.Name), Excel.XlFileFormat.xlCSV, Excel.XlSaveAsAccessMode.xlNoChange);
}
workbook.Close(false);
Dts.TaskResult = (int)ScriptResults.Success;
}
Any help would be great, thanks!
Update 1
I don't know if it's worth mentioning that I'm trying to do this through a script task in SSIS. So it's just one script task that I run that contains the code above.
Trying to figure out the issue
In normal cases, the code you provided will work perfectly. It may encounter some issue in case that the excel application has shown a message box, need permissions to enable editing, there are permissions issue to access other worksheets since they are protected ...
First of all, open the excel manually and check that you can access all worksheets and perform save operations manually. If you didn't encountered any issue, then you should prevent excel from showing message boxes or other promotion while using Interop.Excel library.
In addition, check that the Csv does not already exists in the destination path.
Try using a similar code:
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Visible = false;
excelApp.DisplayAlerts = false;
Microsoft.Office.Interop.Excel.Workbook workbook = excelApp.Workbooks.Open(#"D:\Book1.xlsx");
workbook.DoNotPromptForConvert = true;
workbook.CheckCompatibility = false;
foreach (Microsoft.Office.Interop.Excel.Worksheet sht in workbook.Worksheets)
{
sht.Select();
System.Diagnostics.Debug.WriteLine(sht.Name.ToString());
if (System.IO.File.Exists(string.Format("{0}{1}.csv", #"D:\", sht.Name)))
{
System.IO.File.Delete(string.Format("{0}{1}.csv", #"D:\", sht.Name);
}
workbook.SaveAs(string.Format("{0}{1}.csv", #"D:\", sht.Name),
Microsoft.Office.Interop.Excel.XlFileFormat.xlCSV, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange);
}
//workbook.Close(false);
workbook.Close(false, Type.Missing, Type.Missing);
excelApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
I tested the following code and it converted all Worksheets successfully.
I am trying to export Excel files to PDF. I am having success with this using the Microsoft.Office.Interop namespace. I am now trying to find out how to exclude tabs that are marked hidden, so that they are not within the PDF> Hase anyone done this or knows how to do this? My code is shown below that I am currently using.
string inFile = #"C:\Users\casey.pharr\Desktop\testPDF\3364850336.xls";
string outFile = #"C:\Users\casey.pharr\Desktop\testPDF\3364850336_noHidden_out.pdf";
string tempFile = #"C:\Users\casey.pharr\Desktop\testPDF\temp.xls";
try
{
//first copy original file to temp file to work with
File.Copy(inFile,tempFile, true);
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = false;
app.DisplayAlerts = false;
Microsoft.Office.Interop.Excel.Workbook wkb = app.Workbooks.Open(tempFile);
for(int x = app.Sheets.Count-1; x-1 > 1; x--)
{
Excel._Worksheet sheet = (Excel._Worksheet)app.Sheets[x];
//now delete hidden worksheets from work book. This is why we are using tempFile
if (sheet.Visible == Microsoft.Office.Interop.Excel.XlSheetVisibility.xlSheetHidden || sheet.Visible == Microsoft.Office.Interop.Excel.XlSheetVisibility.xlSheetVeryHidden && sheet != null)
{
//is sheet hidden. If so remove it so not part of converted file
sheet.Delete();
}
}
wkb.ExportAsFixedFormat(Microsoft.Office.Interop.Excel.XlFixedFormatType.xlTypePDF, outFile);
wkb.Close(false);
app.Quit();
//return outputLocation;
The error that occurs on calling .Delete() is below:
Exception from HRESULT: 0x800A03EC
enter code here
So we can convert the pdf's fine, but not remove or exclude hidden worksheets. I went the route to try to delete them then convert the entire file, but not working.
I wrote a C# application that queries a DB and puts the results in an excel file. The program itself works fine. However if I open a second completely unrelated excel file while the application is running, an exception occurs and the process stops.
Now, in the program itself I've set the visibility to false, and after opening the second unrelated Excel file, the one that was being generated is suddenly open and visible, and then I get the exception.
Anyone know what is causing the problem or how to resolve it?
The relevant parts of the code is as follows, the exception occurs at the line worksheet.get_Range(currCol.GetString() + excelRow, Missing.Value).Formula = item.ToString();
The exception itself is : "Exception from HRESULT: 0x800AC472"
Application exc = new Application();
//Makes the Excel file not visible
exc.Visible = false;
exc.UserControl = false;
exc.DisplayAlerts = false;
Workbooks workbooks = exc.Workbooks;
Workbook workbook = workbooks.Add(XlWBATemplate.xlWBATWorksheet);
Sheets sheets = workbook.Worksheets;
Worksheet worksheet = (Worksheet)sheets.get_Item(1);
int excelRow = 1;
ExcelChar currCol = new ExcelChar('A');
System.Data.DataTable testTable = dbConnection.searchQuery("Select * from testTable").Copy();
if (worksheet == null)
{
Console.WriteLine("ERROR: worksheet == null");
}
foreach (System.Data.DataRow row in testTable.Rows)
{
foreach (var item in row.ItemArray)
{
worksheet.get_Range(currCol.GetString() + excelRow, Missing.Value).Formula = item.ToString();
currCol.Add(1);
}
excelRow++;
currCol = new ExcelChar('A');
}
Take a look at this thread.
It looks like your error is VBA_E_IGNORE, in which case you need to register an IMessageFilter implementation so you can implement retry logic.
I've seen this issue in the past, when using the same instance of Excel with interop and interactively - for example when instatiating an Excel Application object using:
Marshal.GetActiveObject("Excel.Application")
In your case, you're creating a new instance of Excel using:
exc = new Application();
What you should try to do is to make sure you close this instance as quickly as possible. This is not always easy, because of the problem described in this KB article. Otherwise you might consider something other than COM Interop to write to Excel (e.g. OLEDB or a third party library such as Aspose or EPPlus).
When Excel is busy - e.g. has a modal dialog displayed, or is busy loading a workbook, it will not respond to incoming COM messages, so it returns an error which is translated into this exception. An IMessageFilter implementation (specifically: RetryRejectedCall) will typically retry a few times, then either fail or prompt the user to retry ("Server busy").
When using the Office InterOp services, you must close the objects you've created in reverse order.
private static void Excel_FromDataTable(DataTable dt)
{
// Global missing variable.
object missing = System.Reflection.Missing.Value;
// Creates an excel object,
Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
// Then a workbooks object,
Excel.Workbooks workbooks = excel.Workbooks;
// Then adds a workbook object,
Excel.Workbook workbook = workbooks.Add(true);
// Then adds a worksheet object,
Excel.Worksheet activeSheet = workbook.ActiveSheet;
// Then names the worksheet to what we need.
activeSheet.Name = "scbyext";
// Add column headings,
int iCol = 0;
// for each row of data,
int iRow = 0;
foreach (DataRow r in dt.Rows)
{
iRow++;
// Then add each row's cell data.
iCol = 0;
foreach (DataColumn c in dt.Columns)
{
iCol++;
excel.Cells[iRow, iCol] = r[c.ColumnName];
}
}
// Disable Excel prompts.
excel.DisplayAlerts = false;
// Save the workbook to the correct folder.
workbook.SaveAs("C:\\Escaped\\Path",
Excel.XlFileFormat.xlExcel8, missing, missing,
false, false, Excel.XlSaveAsAccessMode.xlNoChange,
missing, missing, missing, missing, missing);
// Release the objects we made, in reverse order, to allow Excel to quit correctly.
ReleaseObj(activeSheet);
ReleaseObj(workbook);
ReleaseObj(workbooks);
excel.Quit();
ReleaseObj(excel);
}
If you don't, the process will stay stuck open. I'm not sure what it's doing when it stays stuck, but by the end of the day the CPU Time used by it can get quite high.
I had a similar problem. I was creating an excel file using C# with a lot of charts that took a long time to create. If a user opened an existing excel file while my C# file was still being written it caused an exception to be thrown and my application would crash.
I fixed it with the following:
xlApp = new Application();
xlApp.IgnoreRemoteRequests = true;
Our application has distribution functionality. It takes several Excel 2007 spreadsheets, copies them into a single sheet, then emails them to the users. The problem is that images and charts are not copying over. I have tried everything I can find on here and various other sources, but sadly nothing seems to work. Our application is written using VSTO, and I have also tried OpenXML, but nothing seems to work. In fact trying to copy over in OpenXML corrupted the files so badly that Excel could not read or recover them. Here's the code we use (note: we have ExcelWrapper simply calls the same functions on the Excel App but hides all the optional items).
private void CreateWorkbook(string filePath, string batchReportsPath)
{
//place the xlsx file into a workbook.
//call getfilesnames
Excel.Workbook bookToCopy;
Excel.Workbook newWorkbook;
Excel.Worksheet tempSheet = new Excel.Worksheet();
newWorkbook = ExcelWrapper.WorkbooksAdd(ExcelApp.Workbooks);
if (File.Exists(filePath))
File.Delete(filePath);
ExcelWrapper.WorkbookSaveAs(newWorkbook, filePath);
List<string> filePaths = new List<string>(Directory.GetFiles(batchReportsPath));
filePaths.ForEach(delegate(string reportPath)
{
string reportPathAndName = reportPath;
bookToCopy = ExcelWrapper.WorkbooksOpen(ExcelApp.Workbooks, reportPathAndName);
int nextSheetNumber = newWorkbook.Sheets.Count;
((Excel.Worksheet)sheetToSend.Sheets[1]).Copy(Type.Missing, newWorkbook.Sheets[nextSheetNumber]);
ExcelWrapper.WorkbookClose(bookToCopy);
});
newWorkbook.Save();
ExcelWrapper.WorkbookClose(newWorkbook);
bookToCopy= null;
tempSheet = null;
newWorkbook = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
I have tried every promising option and searched both the VSTO and OpenXML object models and I am stumped. Please stackoverflow community, you're my only hope.
UPDATE: Here's the answer folks:
//Copy all the images, Charts, shapes
foreach (Excel.Shape o in copySheet.Shapes)
{
if (o.Type == Microsoft.Office.Core.MsoShapeType.msoPicture)
o.CopyPicture();
else
o.Copy();
newWorkbook.Save();
}
You need to do the save after each copy to get the Paste to finalize. Thanks for your input.
You'll need to check the WORKSHEET object of the worksheet you're looking to copy, then run through all the "*Objects" properties, and, for each of those collections, write code to manually copy all the elements in that collection to the new sheet.
For example, you've got:
ChartObjects
ListObjects
OleObjects
Shapes (Which might get copied along with the sheet, I'm not sure).
Perhaps you can get there by a copy/paste? Here's an example that copies cell data, charts and images: MSDN
Good luck!
I don't have an answer but I can give you some pointers. First, this is not an openxml question, it's a vsto question. Second, images and charts are attached to a spreadsheet, they are not content in it (a subtle distinction). There is probably a property of all charts and one of all images attached to the sheet. Copy that across.
(I use the IExtensibility interface instead of VSTO so I know what's in the underlying API, but not the property names - sorry.)
This is how I do it -- moves the entire worksheet from source workbook to a brand new workbook:
public static void MoveWorksheet()
{
public static Excel.Application oXL;
public static Excel._Worksheet ws;
if (File.Exists(Global.Variables.GlobalVariables.recap))
{
//workbookToOpen is location and name
oXL.Workbooks.Open(workbookToOpen, Missing.Value, true);
object ws = null;
try
{
ws = wb.Sheets["Sheet 1"];
if (ws != null)
{
((Worksheet)ws).UsedRange.Interior.ColorIndex = Constants.xlNone;
((Worksheet)ws).Copy();
oXL.ActiveWorkbook.SaveAs("SaveAsFileName" + ".xlsx");
oXL.ActiveWorkbook.Close(true);
}
}
catch {}
}
}