I have the following code in an Excel Add-In in C#:
long lngArrayLength = 14;
long lngArrayLength2 = array2.Length;
Excel.Range rngValues1 = (Excel.Range)wsNew.Cells[2, 1];
Excel.Range rngValues2 = (Excel.Range)wsNew.Cells[lngArrayLength2 + 1, lngArrayLength];
Excel.Range rngValues = wsNew.get_Range(rngValues1, rngValues2);
rngValues.Value = array2;
For reference, array2 has ten elements, each of which has 14 sub-elements. Example:
array2 = { (0, "a0", "b0", "c0"... "n0"), ... {9, "a9", "b9", "c9"... "n9) }
rngValues above is sized as {[1..10,1..14]}
Every time I try to run, I get the following error:
Exception from HRESULT: 0x800A03EC
I have ruled out:
1) File format, saving Book1 as .xlsx does not help
2) Reaching the column or row limit, does the same thing with thousands of elements or 10 of them
3) [0] vs [1] - indexed arrays and/or ranges, doesn't seem to matter/help
I am still having trouble debugging this... Is it possible this has something to do with the dimensions of the array vs the range? How would I determine if that's the case or not?
UPDATE 1:
I created a loop that populates an array with data:
for (i = 1; i <= lngRows; i++)
{
for (j = 1; j <= lngCols; j++)
{
strTest[i-1, j-1] = "test (" + i.ToString() + "," + j.ToString() + ")";
}
}
...and this works fine.
It now occurs to me that may of the elements in the array contain NULL values.
I'm thinking this may be the problem... Is it?
UPDATE 2:
Okay, so I now wrote a small routine to convert any NULLs to 0 (b/c the data type is decimal? (nullable decimal) and I guess I really need decimal instead:
public decimal replaceNullDec(decimal? decInput)
{
if (decInput != null)
{
decimal rtn = (decimal)decInput;
return rtn;
}
else
{
decimal rtn = 0;
return rtn;
}
}
So, now I have confirmed that all the NULLs are being replaced, but I'M STILL GETTING THE ERROR when writing the array to a range...
UPDATE 3:
Okay, so then I thought that maybe it's a data type issue, so I rewrote the code to convert all the elements in the array to strings instead before writing to the sheet. I now get data, but instead of the actual values, I get text telling me the original TYPE (which in this case is a custom class called Response).
The interesting thing I noticed is that I'm getting 10 COLUMNS of text, and 4 COLUMNS of #N/A.
This makes me think that maybe I need to transpose the array?
Driving me crazy, but still trying.
Any help would be GREAT!
UPDATE 4:
Okay, I believe I'm getting closer. In digging into how to transpose a 2d array in C#, I was getting some errors that lead me to believe I DON'T actually have a 2d array, but instead an "array of arrays" (which is what I thought a 2d array was, honestly) and it's probably the conversion of my List to Array using the ToArray() method that's an issue.
Here's that code:
object[] array2 = listAllData.ToArray();
So the next question becomes "how to convert a list to a 2d array?"
ANSWER:
The issue came down to the fact that I was NOT writing a 2D array to the range, but instead I was building an array of Response objects and trying to write that to a range.
More details on the solution are found in this related post:
How to Convert 2D List to 2D Array in C#
Related
I'm making an Othello/Reversi game where I use a 2d array to hold the memory for each space on the board.
In order to check for valid moves i'm using an if statement where I use r+1 in order to check the next space along on the same row. However as the array is only [8, 8] large, when I encounter a situation where r is 8 I get an error because it is trying to check the 9th element in the array. This gives me an index out of bounds error.
Was wondering what the best way to fix this would be? I thought maybe swapping to a list but i'm unsure if that will work as well for a 2d array?
public box[,] grid = new box[8, 8];
if ((grid[r + 1, c].value == currentPlayer)
{
return true;
}
You just have to check that r + 1 is a legal index. Having a list won't help as you'll still be checking beyond the bounds of the list. So you simply need:
if (r + 1 > 7) return false;
as you know the size of your array. However to avoid "magic numbers" you'd be better off getting the upper bound of the first dimension of the array:
if (r + 1 > grid.GetUpperBound(0)) return false;
You can do the same for checking that c is within bounds:
if (c < 0 || c > grid.GetUpperBound(1)) return false;
I need to create a 2D array where size of column is fixed as 6 but size of row may vary . How to give dynamic row size in 2D array ?
Below is the code I tried but no luck.
int n;
string num = console.ReadLine();
Int32.TryParse(num,out n);
int[,] ar = new int[n,6] ;
There's nothing wrong with the way you're constructing the mulitidimentional array. The following code is valid so I suspect your error is somewhere else:
int n = 9;
int[,] ar = new int[n,6];
I'm guessing your input is not coming through correctly so add some error checks to figure out what went wrong. First, Console.ReadLine() has to be capitalized or it wont compile. Next, make sure TryParse is actually functioning properly (it returns a bool indicating success or failure:
int n;
string num = Console.ReadLine();
if (num == null) {
// ERROR, No lines available to read.
}
if (!Int32.TryParse(num,out n)) {
// ERROR, Could not parse num.
}
int[,] ar = new int[n,6];
If issues persist, people generally appreciate more descriptive explanations than "I tried but no luck." Make sure to inform people viewing your question that it was a compilation error or a runtime error and be as specific as you can.
I would use a Dictionary as so.
Dictionary<int,List<int>> numbers = new Dictionary<int,List<int>>();
And you could add an item like this:
numbers.Add(1,new List<int>(){1,2,3,4,5,6});
And to add numbers to a particular row.
numbers[1].Add(7);
And to access a number in a specific row and column.
numbers[1][2] = 34;
I have a problem very much like the one mentioned here:
ArgumentOutOfRangeException Was Unhandled
I believe that contiguousLines[columnNum].Add(...) is what is causing the error because I am indexing with columnNum
List<line> freeLines = new List<line>();
List<List<line>> contiguousLines = new List<List<line>>();
while(freeLines.Count > 0)
{
int columnNum = contiguousLines.Count;
contiguousLines[columnNum].Add(freeLines[0]);
freeLines.RemoveAt(0);
for(int i = 0; i < freeLines.Count; i++)
{
int last = contiguousLines[columnNum].Count;
if(contiguousLines[columnNum][last].upDown(freeLines[i]))
{
contiguousLines[columnNum].Add(freeLines[i]);
freeLines.RemoveAt(i);
i = -1;
}
}
// Further code that pulls individual elements from freeLines and
// is intended to place them into contiguousLines.
}
The function upDown just compares Start and End points of the lines to see if one (freeLines[i]) is the downstream of the other (contiguousLines[columnNum]).
System.ArgumentOutOfRangeException was unhandled
Message=Index was out of range. Must be non-negative and less than the size of
the collection. Parameter name: index
What is the proper syntax when dealing with a List of Lists?
(Note: I don't often program in C# and this project is something I wrote and have working in C++ only to be later informed C# would play better with the rest of the utilities for my job. In C++ I used vectors for my containers, but apparently copy/pasting the logic won't work as there is some nuance of Lists that I am unaware of.)
I suppose it is also possible to just make a ContiguousLine class that holds a list of Lines, then add to a List<ContiguousLine> from freeLines. Even if that were to be a better solution, I am still curious why I can not address a List of Lists of Lines in this way.
int last = contiguousLines[columnNum].Count;
As lists are 0-indexed, you're 1 over.
you need to add a List first before access the column
contiguousLines.Add(new List<line>());
contiguousLines[columnNum].Add(freeLines[0]);
Got a silly question im struggling with.
Im trying to step through a C# Multidimensional array using nested for loops, but i cant get the result i want and im thinking its just a stupid problem with my code.
string search = txtString.Text;
int iLoop;
int jloop;
int iResult = -1;
for (iLoop = 0; iLoop < sounds.GetLength(0) ; iLoop++)
{
for (jloop = 0; jloop < sounds.GetLength(1) ; jloop++)
{
string result;
result = sounds[iLoop,jloop];
if (result == search)
{
iResult = iloop;
}
}
}
if (iResult == -1)
{
MessageBox.Show("Result not found");
}
else
{
MessageBox.Show("Result found at position " + iResult);
}
}
It searches the array, and returns a positive result if the answer is found, but the result position is always "Result found at position 1".
What have i done wrong?
You are storing only one dimension (iResult). It can always be 1, but second dimension (jresult) can vary.
And just reminder for future projects in different languages. Try no to use if (result == search) for strings. Use Equal or Compare methods.
There are two indices to look up: jloop and iLoop , probably you will get various jloop values in the 2D array
Also check the name on the parameter you use, sometimes you call it iLoop, others iloop.
Be consistent! :)
I guess the answer is always in row 1, you just pring the i value, print also the j value jLoop.
Keep in mind that this code snippet will continue searching even after it has found a match. So in fact what you are finding is the last position of the matched text.
As an aside, perhaps instead of reporting only the matching iLoop, you could report both the matching iLoop and jLoop. Or, you can report a single index as iLoop * sounds.GetLength(0) + jLoop
I know how to write single cell into excel but when im trying it on array excel sheet is filling with only last value
this is my range
Excel.Range ServiceName = (Excel.Range)_sheet.get_Range(_sheet.Cells[38, "B"] as Excel.Range, _sheet.Cells[45, "B"] as Excel.Range);
_ServiceName is List which contains 1,2,3,4,5,6
for (int i = 0; i < _ServiceName.Count; i++)
{
ServiceNameArray[0, i] = _ServiceName[i];
}
this i my trying to write into excel but as i said it there is only last item (6) in excel book
for (int i = 0; i < _ServiceName.Count; i++)
{
ServiceName.set_Value(Type.Missing, ServiceNameArray[0,i]);
}
does anyone have an idea?
Davide Piras is right. And you're doing a few other strange things there, I can elaborate by request.
For now I just want to point out that you can directly assign the .Value property of a Range to an array:
ServiceName.Value2 = _ServiceName.toArray();
This is much, much faster for bigger amounts of data.
(Side note: If you want to do the same with Formulas, for some strange reason you have to take an extra step (doubling the time):
range.Formula = array;
range.Formula = range.Formula;
unless there is a better way I don't know about yet.)
I see you looping on the ServiceName array to get all values one after the other but not see you changing the focused cell inside the cellrange at every loop iteration. Of course, I would say, you see only the last value, because you are writing all values one over the other always in the same place.