How to cut a range of cells using Excel Interop - c#

I have a column and i'm looking to cut rows 3-37 and move it to the column directly to the right of it.
I tried the following and it moves the values correctly to the right but the cell styles don't copy over.
Range copyRange = ws1.Range["L5:L37"];
Range insertRange = ws1.Range["M5:M37"];
insertRange = copyRange;
I've also tried solution from here Cut and Paste Columns in Excel Range with c# but nothing seem to copy
Range copyRange = ws1.Range["L5:L37"];
Range insertRange = ws1.Range["M5:M37"];
//insertRange.Insert(copyRange.Cut());
insertRange.Insert(XlInsertShiftDirection.xlShiftToRight, copyRange.Cut());

If you want to just replace the contents of the destination cells with the contents of the source cells, and delete the contents of the source cells, then the Range.Cut method ought to do the trick if you call it with the destination range as an argument:
Range sourceRange = ws1.Range["L5:L37"];
Range destinationRange = ws1.Range["M5:M37"];
sourceRange.Cut(destinationRange);
This will not copy sourceRange to the clipboard, but it will clear the clipboard if you already have a range on the clipboard.
You can also specify only the upper left cell of the destination range, and it will do the same thing:
Range sourceRange = ws1.Range["L5:L37"];
Range destinationRange = ws1.Range["M5"];
sourceRange.Cut(destinationRange);
If you want to keep the contents of the source cells, use Copy instead of Cut.
(Note that the statement insertRange = copyRange; definitely should never copy any cells anywhere if insertRange is a local variable. That could only happen if C# supported overloaded assignment (which, to my knowledge, it does not) or if some other code somehow "sensed" the assignment.)

Related

C# - Read MergedCells range in EPPlus

How to read the value of range that is Merged with EPPlus?
Lets say the range "G15:G18" is merged. How do I retrieve the text inside that range?
I've tried this, but without success:
string txt = ws.Cells["G15:G18"].Value.ToString();
Thanks.
Looking better at the issue, I finally understood that what I was doing was actually bringing a collection of results, where only the first item has a value.
So, basically, this code:
string txt = ws.Cells["G15:G18"].Value.ToString();
would return an array like with the text for all the cells in the range.
But except for the first cell in the array, all cells are empty. Only the first cell hold the Value for the whole range.
What I did is as simple as this:
string val = ws.Cells["G15:G18"].First().Value.ToString();
It worked fine.
Unless I missed the boat, I think it might be even easier than you think... just look for the value for the first cell in the range:
string txt = ws.Cells["G15"].Value.ToString();
Also, if you know it's text or just want the text representation of the cell, you can use the Text property:
string txt = ws.Cells["G15"].Text;
I think this concept transcends EPPlus also -- you can reference it in Excel formulas, and I believe it works this way in Interop as well.

Arrays seem to be 0-based instead of 1-based when working with Range and Cells

I'm currently evaluating VSTO to replace the VBA we use with Excel 2010, so I'm absolutely new to this Excel interop thing.
While testing, I sometimes encountered issues while using ranges and cells, sometimes the arrays seem to be 1-based and sometimes they seem to be 0-based, and I didn't find any information on that.
Here is a small example :
var ws = ((Excel.Worksheet)Globals.ThisWorkbook.Application.ActiveWorkbook.Sheets[1]);
var range = ws.Range["B2:D6"];
AddName("testname", range);
range.BorderAround2(Excel.XlLineStyle.xlContinuous, Excel.XlBorderWeight.xlThick);
//Code 1
((Excel.Range)range.Cells[2, 1]).BorderAround2(Excel.XlLineStyle.xlDouble, Excel.XlBorderWeight.xlThick);
((Excel.Range)range.Cells[4, 1]).BorderAround2(Excel.XlLineStyle.xlDouble, Excel.XlBorderWeight.xlThick);
//Code 2
range.Range[range.Cells[2, 1], range.Cells[4, 1]].Interior.Color = ColorTranslator.ToOle(Color.Green);
//Code 3
range.Range[range.Cells[1, 0], range.Cells[3, 0]].Interior.Color = ColorTranslator.ToOle(Color.Red);
The code creates a named range and adds a thick border around, then adds a double border to the cells that represent the bounds of the range I want.
It sets the background to green for the range that uses the same cells, and in red for the range I want.
Here is the result :
What I wanted to do is to select the cells of the first column in the range except the first and last (so red is what I want).
But it seems that if I select the cells individually (code 1), it doesn't behave the same as if I create a range from the same cells (code 2).
To get the range I want, I have to shift all indexes by one (0-based) (code 3).
Is there a reason for that, did I miss something ? I don't see anything about that in the MSDN.
Check out the Remarks here : https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range.range.aspx. With the Range property the cells are relative to the defined range, hence the shift by 1.

Excel Range Copy Value vs Value2 Extension Method

I'm making an extension method to simplify copying range data from on worksheet to another.
I want to specify a rectangular range and the top left cell of the target range. Keeping formating is important for Dates and Currencies so I want to Use Value over Value2
//Extension Helper method
public static void CopyRangeTo(this Excel.Range from, Excel.Range to){
//resize to to match the rows and columns of from
to = to.Resize[from.Rows.Count, from.Columns.Count];
//copy the contents of the range from to range to
to.Value = from.Value;
}
//how its intended to be called
ws.Range["A1:C5"].CopyRangeTo(ws2.Range["B3"]);
//note this call doesn't work because Cells cannot be used statically
ws.Range[ws.Cells[1, 1], ws.Cells[5, 3]].CopyRangeTo(ws2.Cells[2,3]);
Currently The program works well the inital time a call the method. However if I change the worksheet at all the method seems to fail (Even if I didn't affect the ranges being used). However I have noticed that if I use Value2 instead then it is much more robust, however I lose formatting.
I may try to iterate through the cells and see if that helps, if any one has other ideas or insight between moving cells around I'd appreciated. I'd like to stay away from paste special.

Fastest way to enumerate or look for all empty Excel cells and change their style or do some other processing

Which would be potentially a best way to enumerate or iterate or simply look for empty cells or cells with specific data structure in Excel, and later once you find it do some processing on it.
I tired Range, Value, Value2, etc but it takes fairly long time when Excel Sheet is considerably larger. I believe there must be some other efficient way.
It would be nice, if you can show some example snippet.
The answer is relativley simple: get the array in one batch from excel (search SO for a how to) - test the values of the erray for empty cells and then acess only the empty cells in excel.
It is somewhat cumbersome, but the fastes way because iterating each cell is vastly slower than simply getting all data in a batch.
To find blank cells, use the .SpecialCells method of a range object.
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range.specialcells(v=office.11).aspx
The .specialCells method returns a range object of the matching criteria (i.e., xlCellTypeVisible, xlCellTypeBlanks, etc.). You can then iterate of this range to perform your formatting, etc.
Update I'm not a C# programmer, but I can show you how I would do this in VBA. Assuming interop exposes most/all of the same methods and functionality, you should hopefully be able to translate this for your purposes.
Sub ColorVisibles()
Dim rng As Range
Dim rngBlanks As Range
Dim blanksExist As Boolean
'define your range
Set rng = Range("A1:AA300")
'check to make sure there are blank cells in the range:
blanksExist = Application.WorksheetFunction.CountBlank(rng) > 0
If blanksExist Then
Set rngBlanks = rng.SpecialCells(xlCellTypeBlanks)
rngBlanks.Interior.Color = vbYellow
Else:
MsgBox "No blank cells exist in the specified range.", vbInformation
End If
End Sub

Getting NumberFormat of Range using Excel interop in C#

I am trying to use Microsoft.Office.Interop.Excel to read excel file in c#.
I want to read range of cells as it is way faster than reading cell one by one:
Range rbeg = (Range)sheet.Cells[1, i + 1];
Range rend = (Range)sheet.Cells[totalRowCount, i + 1];
Range range = sheet.get_Range(rbeg, rend);
column = (object[,])range.Value2;
The problem is when I want to get number format of cells by calling:
range.NumberFormat
I get System.DBNull. It works when I call it for single cell.
I want to distinguish between cells with numerical values and "%" values.
Any ideas?
See the documentation:
[NumberFormat] returns Null if all cells in the specified range
don't have the same number format.
What were you expecting it to do in this case?

Categories

Resources