Locking/Unlocking merged Excel cells using C# and WPF - c#

I'm trying to unlock a couple of cells using the code below. The cells are merged with each other and I don't want to disjoin them as I am working on a client's quote template and do not want to change his quote structure :) Anyway...here is the code:
Excel.Worksheet ws = wb.Worksheets[1];
ws.Range["F25:F42"].Locked = false; //Error here
I get an error saying:
We can't do that to a merged cell.
Is there a way of getting around this error so that I can unlock/lock the cells as I will?

I suggest doing this:
Excel.Worksheet ws = wb.Worksheets[1];
foreach (Excel.Range ra in ws.Range["F25:F42"]) {
ra.MergeArea.Locked = false;
}

Related

Datagridview to Excel: are you missing a cast? [duplicate]

Here I'm opening excel and writing to excel sheet. I'm changing my windows application to asp website and seen this error. I have added all the references and libraries. Don't know what I am missing here.
Getting error as mentioned below. Please help me.
Excel.Application excel = new Excel.Application();
excel.Visible = false; // to hide the processing
Excel.Workbook wb = excel.Workbooks.Add();
Excel.Worksheet sh = wb.Sheets.Add(); // Error at wb
sh.Name = "Links";
for (int i = 1; i < list.Count; i++)
{
sh.Cells[i.ToString(), "A"].Value2 = list[i]; //Error at .Value2
}
you have to create a new Worksheet with Sheets array by providing WorkSheet Name.
and also please Cast The Newly Created WorkSheet.
Replace this :
Excel.Worksheet sh = wb.Sheets.Add();
with following
Excel.Worksheet sh = (Microsoft.Office.Interop.Excel.Worksheet)wb.Sheets["Sheet1"];
To resolve your second error,
//Error at .Value2
Go to project properties. (Click Project in Menu, Click properties)
Set the Target Framework as .NET Framework 4
This should resolve your .Value2 error.

Freeze Panes in multiple worksheets 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;

delete excel worksheets programmatically

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.

When Excel file is opened externally during C# application, an exception occurs

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;

Remember hidden rows after data refresh in Excel c#

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.

Categories

Resources