I have an excel workbook with many, many sheets. I want to delete all the sheets except for three of them.
Specifically, i would like to know if there is a way to remove the sheets using sheet name instead of ordinals (sheet number).
I am using excel interop and C# to work with Excel.
Microsoft.Office.Interop.Excel.Application xlApp = null;
Excel.Workbook xlWorkbook = null;
Excel.Sheets xlSheets = null;
Excel.Worksheet xlNewSheet = null;
xlApp.DisplayAlerts = false;
for (int i = xlApp.ActiveWorkbook.Worksheets.Count; i > 0 ; i--)
{
Worksheet wkSheet = (Worksheet)xlApp.ActiveWorkbook.Worksheets[i];
if (wkSheet.Name == "NameOfSheetToDelete")
{
wkSheet.Delete();
}
}
xlApp.DisplayAlerts = true;
I know this is old but I just use the fallowing
workBook.Sheets["Sheet1"].Delete();
I know this thread is really old but for future visitors, if you know the names of the sheets you want to delete, a better way is to loop over the names of the sheets like this:
Workbook book = excelApp.Workbooks.Open("filePathHere");
string[] sheetsToDelete = {"s1", "s2"};
excelApp.DisplayAlerts = false;
foreach(string sheetToDelete in sheetsToDelete )
{
book.Worksheets[sheetToDelete].Delete();
}
excelApp.DisplayAlerts = true;
It's always good practice to avoid deleting items in a collection while iterating through it.
Related
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 have a C# program that opens an Excel file, reads a cell, closes the file, and exits Excel. Unfortunately, the Windows Task Manager still shows an Excel.exe process running. I've read just about every article concerning this issue and tried almost all of the solutions . . . and still have the same problem. I believe one of COM objects is not being released and thus hanging the process. However, I also believe that I've been very careful about instantiating the Excel objects (no double ".") and releasing them.
If I remove the "a = xlCells[1,1].Value" line, every thing releases and Excel dies cleanly after the FinalReleaseComObject of the Application instance. Why would this assignment create COM objects or interfere with them?
Excel.Application xlApp = null;
Excel.Workbooks xlWorkbooks = null;
Excel.Workbook xlWorkbook = null;
Excel.Sheets xlSheets = null;
Excel.Worksheet xlWorksheet = null;
Excel.Range xlCells = null;
string inputFile = #"C:\Temp\test.xlsx";
string a;
xlApp = new Excel.Application();
xlApp.Visible = false;
xlApp.DisplayAlerts = false;
xlWorkbooks = xlApp.Workbooks;
xlWorkbook = xlWorkbooks.Open(inputFile);
xlSheets = xlWorkbook.Sheets;
xlWorksheet = xlSheets[1];
xlCells = xlWorksheet.Cells;
a = xlCells[1,1].Value;
Marshal.FinalReleaseComObject(xlCells);
xlCells = null;
Marshal.FinalReleaseComObject(xlWorksheet);
xlWorksheet = null;
Marshal.FinalReleaseComObject(xlSheets);
xlSheets = null;
xlWorkbook.Close(false, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(xlWorkbook);
xlWorkbook = null;
xlWorkbooks.Close();
Marshal.FinalReleaseComObject(xlWorkbooks);
xlWorkbooks = null;
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
xlApp = null;
I would make two changes. First, since a Sheets item can be either a worksheet or a graph sheet, it's best to cast with As and check for null. Second, if you just want to get a range with an alphanumeric address, the get_Range() method works well. Otherwise, if you want to go by row and column indexes, then follow #Daneau's comment.
xlWorksheet = xlSheets[1] as Excel.Worksheet;
if(xlWorksheet != null)
{
xlCells = xlWorksheet.get_Range("A1");
a = xlCells[1,1].Value;
Marshal.FinalReleaseComObject(xlCells);
xlCells = null;
Marshal.FinalReleaseComObject(xlWorksheet);
xlWorksheet = null;
}
I changed up the code and added the dummy Range object.
Range tmpCell = xlCell[1,1];
a = tmpCell.Value;
Marshal.ReleaseComObject(tmpCell);
My problems went away. Much thanks, Daneau!
The real routine has several loops with the cell being evaluated. I thought it would work fine using the tmpCell for each new cell assignment, then release tmpCell at the end. That failed. Prior to each new tmpCell assignment to a xlCell[x,y], I had to release tmpCell. This worked, but is certainly cumbersome. It's difficult to believe that there's not a better way to manage this or keep track of the various COM objects.
I am trying to add a button on an excel worksheet.
According to the example from internet, I am trying to do following code.
using Excel = Microsoft.Office.Interop.Excel;
using VBIDE = Microsoft.Vbe.Interop;
private static void excelAddButtonWithVBA()
{
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlBook = xlApp.Workbooks.Open(#"PATH_TO_EXCEL_FILE");
Excel.Worksheet wrkSheet = xlBook.Worksheets[1];
Excel.Range range;
try
{
//set range for insert cell
range = wrkSheet.get_Range("A1:A1");
//insert the dropdown into the cell
Excel.Buttons xlButtons = wrkSheet.Buttons();
Excel.Button xlButton = xlButtons.Add((double)range.Left, (double)range.Top, (double)range.Width, (double)range.Height);
//set the name of the new button
xlButton.Name = "btnDoSomething";
xlButton.Text = "Click me!";
xlButton.OnAction = "btnDoSomething_Click";
buttonMacro(xlButton.Name, xlApp, xlBook, wrkSheet);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
xlApp.Visible = true;
}
But it keeps saying "Excel does not contain Button"
What reference should I include to use Button property?
As far as I can tell, Excel.Buttons and Excel.Button do not exist. Instead it is suggested that the correct reference is Microsoft.Office.Tools.Excel.Controls.Button (not Microsoft.Office.Interop.Excel as you are using). This example is from the source below
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlBook = xlApp.Workbooks.Open(#"PATH_TO_EXCEL_FILE");
Excel.Worksheet worksheet = xlBook.Worksheets[1];
Excel.Range selection = Globals.ThisAddIn.Application.Selection as Excel.Range;
if (selection != null)
{
Microsoft.Office.Tools.Excel.Controls.Button button =
new Microsoft.Office.Tools.Excel.Controls.Button();
worksheet.Controls.AddControl(button, selection, "Button");
}
Source: Adding Controls to a Worksheet at Run Time in an Application-Level Project http://msdn.microsoft.com/en-us/library/cc442817.aspx
Using Lesley.Oakey's method requires you to be using the VSTO extension methods in Microsoft.Tools.Office.Excel.
If you are not using them, then you will not be able to access the Worksheet.Controls property.
Best to just use the Worksheet.Shapes container and add a new shape. There's a great post about this here:
Add excel vba code to button using c#
I am working on MS Excel 2013 generating report where all the worksheets in workbook should have freeze pane at column 6 and row 1. I have searched on Google but could not find any solution as for freezing the pane, workbook has to be active. I have tried a lot of things but no success. I will really appreciate if someone can help me.
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open("filelocation");
foreach (Excel.Worksheet ws in workbook.Worksheets)
{
ws.Application.ActiveWindow.SplitColumn = 6;
ws.Application.ActiveWindow.SplitRow = 1;
ws.Application.ActiveWindow.FreezePanes = true;
}
excel.Visible = true;
I Hope it help others. I have used ClosedXML Library for Excel and after creating each worksheet I used
worksheet.SheetView.Freeze(1,6);
This freezes the Row 1, Col 6. You can freeze any row/column.
Here is link to ClosedXML. It's widely supported and very good documentation.
To freeze the panes on each worksheet you need to modify your for loop to add a line to activate the current sheet prior to setting the other properties. Here is my solution:
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open("filelocation");
foreach (Excel.Worksheet ws in workbook.Worksheets)
{
ws.Activate();
ws.Application.ActiveWindow.SplitColumn = 6;
ws.Application.ActiveWindow.SplitRow = 1;
ws.Application.ActiveWindow.FreezePanes = true;
}
excel.Visible = true;
I am trying to do the following using c# code:
Hide some rows in excel.
Clear all data and formats in excel sheet.
Put other data to excel sheet.
I would like the hidden rows still remain hidden.
Is it possible?
Thank You!
I've had great results using ClosedXML to manipulate excel spreadsheets.
While I haven't tried your case I've done similar things. In my case I put my private data into a new worksheet and hide that, which ClodedXML made simple.
Here's a sample code that can get you going....
//Create an Excel App
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook xlWorkBook = null;
Microsoft.Office.Interop.Excel._Worksheet xlWorksheet;
//Open a Workbook
xlWorkBook = xlApp.Workbooks.Open(#"d:\test.xlsx");
xlWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)xlWorkBook.Sheets[1];
//My Workbook contains 10 rows with some data and formatting
//I Hide rows 3, 4 & 5
Microsoft.Office.Interop.Excel.Range hiddenRange = xlWorksheet.get_Range("A3:C5");
hiddenRange.EntireRow.Hidden = true;
//Get the entire sheet and Clear everything on it including data & formatting
Microsoft.Office.Interop.Excel.Range allRange = xlWorksheet.UsedRange;
allRange.Clear();
//Now Add some new data, say a Title on the first cell, and some more data in a loop later
xlWorksheet.Cells[1, 1] = "Title";
for (int i = 6; i < 10; i++)
{
xlWorksheet.Cells[i, 1] = i.ToString();
}
xlApp.Visible = true;
Thats it....
Store them in a variable and hide them again after you have populated excel with data.