I want to copy an 1D array to a column range in excel. I'm using interop for this purpose.
I have already tried these things:
range.get_Resize(Ary.Length, 1).Value2 = Ary;
range.set_Value(Excel.XlRangeValueDataType.xlRangeValueDefault, Ary);
and as simple as range.Value = Ary;
I have tried using even range.value2, but these things copy the very first index value in the array to the entire range.
So say suppose, if there are 200 rows in the range and the array contains integers 101-300, than only 101 is copied throughout the range with the above tried methods.
Can anyone please help me with this? It would be more helpful if someone can explain me this strange behavior! Thanks in advance.
Note: I know I can do it through a for loop, but that takes time. I would surely like to know a method which takes less than a minute to iterate a million rows.
I seriously don't know what exactly is wrong with the above methods. But I found the solution:
Excel.Range range = sheetSource.UsedRange.Columns[columnIndx];
range.Value = application.WorksheetFunction.Transpose(Ary);
Related
I need to parse an Excel file. First I wrote an extension in Visual Basic inside the Excel file, all worked good. Now I need to port it to C# so it can be a separate application. While the functions I use are the same, the result is not the same...
When I choose from the GUI which Worksheet to parse, I do something like:
range = (workbook.Worksheets.get_Item(itemIndex) as Excel.Worksheet).UsedRange;
Then, for the first row I need to parse I do something like:
range.get_Range(range.Cells.get_Item(6, 2),
range.Cells.get_Offset(6,2).get_End(Excel.XlDirection.xlToRight)))
And I get the right result with all the fields I need.
The second time when I need to get another row, I do:
range.get_Range(range.Cells.get_Item(13, 3),
range.Cells.get_Offset(13, 3).get_End(Excel.XlDirection.xlToRight)))
This time it gives me all the elements except the last one. And I have more functions like this, some with XlDirection.xlDown and all of them return me the range without the last element.
I tried to swap the functions, thinking may be I need to release range and then acquire it again or something(wanted to check if it's always working only for the first function being executed) but it is always working only for the first example, whenever the function is being executed...
This is even stranger because it worked in VBA Excel.
I also tired with Excel.Application get_Range and Excel.Worksheet get_Range...
Anyone knows why this happens?
I managed to solve this strange behavior. It's not the correct way of getting out the data.
The correct way would be: range.get_Range(range.Cells[6, 2], (range.Cells[6, 2] as Excel.Range).get_End(Excel.XlDirection.xlToRight)) - for the first example.
Hope it helps somebody...
My C# code manipulates Excel Ranges using Microsoft.Office.Interop.Excel library. I need to assign a Formula Array to a selected Range. I've tried a variety of methods recommended online, including Microsoft recommendations, but so far was unable to make it work properly.
I observe 2 issues:
Issue 1.
Assignment looks fine on surface: it does not fail, cell objects in the range show .ArrayFormula property assigned, on the spreadsheet formula in every cell appears in curly brackets. However, the Formula Array is actually disjointed: each cell in the range can be changed separately, which normal Formula Array would not permit. It behaves as if every cell had its own, single-cell Formula Array, independent from others. Regardless of my best efforts, this is ALWAYS the case.
Is there actually a properly working solution for this issue?
Issue 2.
My Array Formula contains a reference to another Range (Range A), which I need to refer to in R1C1 style. I need Array Formula in every cell in the target Range point to the same Range A. Somehow I always end up with every cell in target Range having its own version of the formula, referring to shifted "Range A" area. How do I make the reference stay in place, regardless of a cell?
N.B. You may assume that Issue 2 is causing Issue 1, but this is not the case: for example, when array formula is simple, like "=SIN(1)", the Issue 1 still occurs.
I would really appreciate any WORKING suggestions. Thanks a lot in advance.
No one seemed interested, however I found a solution and will answer to my own question.
Apparently, assignment of an Excel Array Formula within C# code works only if the formula is in A1 style, not in R1C1 style. In my case, I was starting with a R1C1-style formula, so it required conversion to A1 style. This is achieved by assigning the original R1C1-style formula to the top left cell of the target range:
topLeftCell.Formula = myR1C1Formula;
// topLeftCell.FormulaR1C1 = myR1C1Formula also works
Assignment to that particular cell will ensure that A1-style formula contains correct references. Get back the converted formula as a string:
string formulaA1 = topLeftCell.Formula;
Get reference to the whole target range by rezising the top left cell:
Excel.Range newArrayRange = topLeftCell.Resize[height, width];
Resize operation must precede the following assignment. Finally, assign the A1-style formula to the FormulaArray property of the whole target range:
newArrayRange.FormulaArray = formulaA1;
This works perfectly without issues or side-effects.
I'm an intermediate C# programmer, but I'm just starting out with Office automation, specifically Excel for now. I've got to say, the Office API is lacking, or at least it forces you to think about problems differently. One thing that's driving me nuts is cell numbers, such as A1 and B5 and so on. I'm forced to manipulate them often, but there's no easy way to do this. For example, if I'm on column C7 and want to copy or move something to B7, I can't just use --C7. Instead I have to figure out the numerical value of C, decrement it, turn it back into a letter then concatenate it with the row number again.
I could write methods to do this myself (e.g. decrementColumn(), decrementRow(), addColumns( String currentCellName, int howManyToAdd) ), but I don't want to reinvent the wheel. Does a library of functions exist for such oft-needed conversions or am I going to have to roll my own?
To copy/move values easily, you can use the .Offset method, which returns a Range.
For example, if the range/cell you are working with is C7, where rng represents this Range object:
rng.Offset(0,-1).Value = rng.Value
This returns the range, offset by -1 colums.
rng.Offset(10,15) would return a cell/range 10 rows below, and 15 columns right, etc.
You may also look at R1C1 address style in Excel, although I have never been fond of that. This link for Excel 2007 but should be mostly appropriate for any version of Excel.
http://msdn.microsoft.com/en-us/library/office/ee264226(v=office.12).aspx
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
I have an Excel workbook which has 3 worksheets with a named range defined for address A1:F10 in each sheet and have some values.
I wanted to have a range defined and set all the 3 worksheet range values to this.
Example
TempRange = Test1Range + Test2Range + Test3Range
Any help would be appreciated
IF all four ranges are the same size, then you can add 'em up with an array formula. Select the entire area of "TempRange", and type
=Test1Range + Test2Range + Test3Range
... and then, to enter it, hit CTRL+SHIFT+ENTER, not plain ENTER.
It's been a long time, and I use OpenOffice these days, so I might have details wrong. The general idea works, though, so even if this exact thing isn't right, googling for "Excel array formula" will probably turn up some helpful information.
I found the answer
Application.Union(Range1,Range2)