Can anyone suggest, how to check if xls file empty or not?
I have tried FileInfo("fname").Length == 0 But it's not working.
Thanks
An "empty" Excel file will still have an Excel file header, which is why your test for a size of 0 is failing.
You can use Excel Interop to see what the UsedRange is:
http://social.msdn.microsoft.com/Forums/en-US/exceldev/thread/b9cdfbd7-5ae9-41f7-b7e8-ebc00e835d45#546316e8-8745-42e8-9c0d-063d1373dfbe
for .xls you can try this - it works for me.
FileUpload1.SaveAs(Server.MapPath("~/FileUpload/") + path.Value);
Workbook book = Workbook.Load(Server.MapPath(("~/FileUpload/") + FileUpload1.FileName));
Worksheet sheet = book.Worksheets[0];
sheetCount.Value = sheet.Cells.LastRowIndex.ToString();
foreach (Worksheet ws in book.Worksheets)
{
if (ws.Cells.Rows.Count != 0)
{
ddlSheets.Items.Add(ws.Name.ToString());
}
}
I think there is not simple solution similar to one you have stated.
You will have to actually programatically read the file by some Excel parser and check if there are some data.
Using Excel Interop I have created this function. It works as Ribbon add-in, however you can replace Globals.ThisAddIn with Excel.Application.
private bool IsEmptyFolder(Excel.Workbook wb)
{
try
{
foreach(Excel.Worksheet sheet in wb.Worksheets)
{
if (Globals.ThisAddIn.Application.WorksheetFunction.CountA(sheet.Cells) != 0) return false;
}
return true;
}
catch
{
return false;
}
}
If it finds any worksheet with a value in a cell, it returns false. Otherwise it returns true (the workbook is empty).
Related
I am using a script task to delete particular rows in an Excel in SSIS. Previously it was working fine, then when I try to implement everything again I am getting error in the .Delete() codes. Find my code below,
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
var dir = new System.IO.DirectoryInfo(#"D:\Data_Processing\Input");
var fullFilePath = dir.GetFiles("*.xlsx").Select(f => f.FullName).FirstOrDefault();
if (fullFilePath != null)
{
Microsoft.Office.Interop.Excel.Workbook workBook = excelApp.Workbooks.Open(fullFilePath);
foreach (Worksheet sheet in workBook.Worksheets)
{
sheet.Rows[8].Delete();
sheet.Rows[7].Delete();
sheet.Rows[6].Delete();
sheet.Rows[5].Delete();
sheet.Rows[4].Delete();
sheet.Rows[3].Delete();
sheet.Rows[2].Delete();
sheet.Rows[1].Delete();
}
workBook.Save();
workBook.Close(false);
excelApp.Application.Quit();
System.IO.File.Move(fullFilePath, #"D:\HC_Report.xlsx");
Dts.Variables["User::FileExistsFlg"].Value = 1;
}
else
{
Dts.Variables["User::FileExistsFlg"].Value = 0;
}
Dts.TaskResult = (int)ScriptResults.Success;
And when I try to add Microsoft.Office.Interop.Excel in the References it is coming with a different icon as below
Can anyone please help with this ?
Thanks,
I have manually added the .dll file from this location C:\WINDOWS\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll and then the error disappeared.
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'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();
I read a lot about how to communicate from C# to Excel and saw some good references.
The thing is I'm looking for an easy way to update existing excel file while it is still open, using
the most advanced way (linq for example) and not OLEDB.
This should be few lines of code describing how can I read current cell, update his value and take into consideration the file might not be exist, but if it does exist and open, it will just update the file without giving the notification the file is already exist. If the file doesn't exist it will create a new one.
SO:
1. connect to an excel file, check if it exist, if not create one
2. read from cell
3. update cell
4. do this while the excel sheet can be still open wild.
I already visited the following places:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/ef11a193-54f3-407b-9374-9f5770fd9fd7/writing-to-excel-using-c
Updating an excel document programmatically
Update specific cell of excel file using oledb
I used the following code:
if (File.Exists(#"C:\\temp\\test.xls"))
{
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbooks workBooks = excelApp.Workbooks;
Microsoft.Office.Interop.Excel.Workbook workBook = workBooks.Open(#"C:\\temp\\test.xls");
Microsoft.Office.Interop.Excel.Worksheet workSheet = workBook.Worksheets.get_Item(1);
int nColumns = workSheet.UsedRange.Columns.Count;
int nRows = workSheet.UsedRange.Rows.Count;
for (int i = 2; i < nRows; i++)
{
workSheet.Columns["1","A"] = "test";
}
workBook.Save();
workBook.Close();
}
So I use VSTO Contrib to help out with COM Interop and memory management and that's why you see .WithComCleanup().
To open up a spreadsheet:
try
{
using (var xlApp = new Microsoft.Office.Interop.Excel.Application().WithComCleanup())
using (var wrkbooks = xlApp.Resource.Workbooks.WithComCleanup())
using (var wrkbook = wrkbooks.Resource.Open(filePath, false, true).WithComCleanup())
{
If the excel file is already open, then to get around the Read-Only follow this tip:
wrkbooks.Resource.Open(filePath, false, FALSE).WithComCleanup())
Here's how I iterate though the sheets (note that some Excel sheets are ChartSheets):
foreach (object possibleSheet in xlApp.Resource.Sheets)
{
Microsoft.Office.Interop.Excel.Worksheet aSheet = possibleSheet as Microsoft.Office.Interop.Excel.Worksheet;
if (aSheet == null)
continue;
Here is a quick way to get a reference to the sheet you're interested in:
activeSheet = wrkbook.Resource.Sheets[sheetToImport];
You read and write to cells just as you've identified:
for (int i = 2; i < nRows; i++)
{
activeSheet.Columns["1","A"] = "test";
}
Here is how I close Excel:
MathematicaAPI.XlHelper.CloseExcel((Worksheet)activeSheet, (Workbook)wrkbook.Resource , (Workbooks)wrkbooks.Resource);
public static void CloseExcel(Worksheet activeSheet, Workbook wrkbook, Workbooks wrkbooks)
{
//http://support.microsoft.com/kb/317109 -> excel just wont close for some reason
if (activeSheet != null)
{
Marshal.FinalReleaseComObject(activeSheet);
activeSheet = null;
}
if (wrkbook != null)
{
wrkbook.Saved = true;
wrkbook.Close(Microsoft.Office.Interop.Excel.XlSaveAction.xlDoNotSaveChanges);
}
if (wrkbooks != null)
{
wrkbooks.Close();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
Sometimes Excel just wont close and you have to kill it (after trying to close it properly of course) - I dont recommend this, but if you cant track down the un-disposed memory and all else fails then...
if (xlApp != null)
{
ExcelDataSourceHelper.GetWindowThreadProcessId(new IntPtr(xlApp.Resource.Hwnd), ref excelProcessId);
}
if (excelProcessId > 0)
{
XlHelper.KillProcess(excelProcessId);
}
public static void KillProcess(int excelProcessId)
{
if (excelProcessId > 0)
{
System.Diagnostics.Process ExcelProc = null;
try
{
ExcelProc = System.Diagnostics.Process.GetProcessById(excelProcessId);
if (ExcelProc != null)
{
ExcelProc.Kill();
}
}
catch
{ }
}
}
Note: I reduce the chances of needing to kill Excel by using VSTO Contrib with Using's.
OK thank you all for trying to solve the issue
The solution was using Excel 2011/2013 Add-In which can communicate excel as a plugin
create an application-level add-in for Microsoft Office Excel. The features that you create in this kind of solution are available to the application itself, regardless of which workbooks are open.
You can visit MSDN
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 {}
}
}