How can I convert a boxed two-dimensional array to a two-dimensional string array in one step?
Asked Answered
R

3

1

Is there a way to convert a boxed two-dimensional array to a two-dimensional string array in one step using C#/.NET Framework 4.0?

using ( MSExcel.Application app = MSExcel.Application.CreateApplication() ) {
    MSExcel.Workbook book1 = app.Workbooks.Open( this.txtOpen_FilePath.Text );
    MSExcel.Worksheet sheet1 = (MSExcel.Worksheet)book1.Worksheets[1];
    MSExcel.Range range = sheet1.GetRange( "A1", "F13" );
    object value = range.Value; //the value is boxed two-dimensional array
}

I'm hopeful that some form of Array.ConvertAll might be made to work but so far the answer has eluded me.

Riggs answered 19/5, 2011 at 22:48 Comment(5)
What is the actual type of value? Is it just Object[][]?Soninlaw
According to the documentation, it is System.object: msdn.microsoft.com/en-us/library/…Riggs
Sorry, I meant the runtime type, not the type of the property. If you call GetType() on that value, what is it?Soninlaw
What is the result of value.GetType()?Angrist
GetType() returns "System.Object[,]" for value.Riggs
M
1

No, I do not think you can make the conversion in one step, but I might be wrong. But you can of course create a new array and copy from the old one to the new one:

object value = range.Value; //the value is boxed two-dimensional array
var excelArray = value as object[,];
var height = excelArray.GetLength(0);
var width = excelArray.GetLength(1);
var array = new string[width, height];
for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; j++)
        array[i, j] = excelArray[i, j] as string;
}

Edit:

Here is a two-dimensional overload of Array.ConvertAll which is not that much more complicated than the code above:

public static TOutput[,] ConvertAll<TInput, TOutput>(TInput[,] array, Converter<TInput, TOutput> converter)
{
    if (array == null)
    {
        throw new ArgumentNullException("array");
    }
    if (converter == null)
    {
        throw new ArgumentNullException("converter");
    }
    int height = array.GetLength(0);
    int width = array.GetLength(1);
    TOutput[,] localArray = new TOutput[width, height];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
            localArray[i, j] = converter(array[i, j]);
    }
    return localArray;
}
Mert answered 19/5, 2011 at 23:6 Comment(5)
That was the approach I was going to resort to if I couldn't do it in one step. The intent is to use a built-in .NET function, if I can find one. Array.ConvertAll should be able to do it, according to its documentation, but I haven't been able to get it to work yet.Riggs
Adding an idea I think you will like.Mert
@Driver, according to the doc, ConvertAll() takes “ one-dimensional, zero-based Array”.Angrist
This solution worked for me, but I did have to make a couple of changes. 1) The excelArray begins at [1,1], while the new array begins at [0,0]. Thus, I had to change one line in the for loop to account for this offset: array[i, j] = excelArray[i+1, j+1].ToString(); 2) height/width needed to be swapped in the line that creates the array: var array = new string[height, width]; Otherwise, this worked exactly as I needed--thanks!Riggs
Glad I could help. These types of arrays are uncommon but they are supported by the framework. To handle the general case you would need to use GetLowerBound: msdn.microsoft.com/en-us/library/…Mert
A
1

You can write your own ConvertAll for two-dimensional arrays:

public static TOutput[,] ConvertAll<TInput, TOutput>(
    this TInput[,] array, Func<TInput, TOutput> converter)
{
    int length0 = array.GetLength(0);
    int length1 = array.GetLength(1);

    var result = new TOutput[length0, length1];

    for (int i = 0; i < length0; i++)
        for (int j = 0; j < length1; j++)
            result[i, j] = converter(array[i, j]);

    return result;
}
Angrist answered 19/5, 2011 at 23:25 Comment(1)
This is very close to what I'm looking for, but I had hoped that the .NET Framework by now includes something like this already. Array.ConvertAll starts complaining if I specify more than one dimension, which was surprising.Riggs
F
0
string[][] strings = ((object[][])range.Value)
    .Select(x => x.Select(y => y.ToString()).ToArray()).ToArray();

Edit: The clarification about object[,] instead of object[][] obviously makes this approach obsolete. An interesting problem; multidimensional arrays are quite limited.

Fumikofumitory answered 19/5, 2011 at 22:59 Comment(2)
Why in the world would you use AsQueryable here?Leela
Ha. I think I got into that habit when I was first learning LINQ. It is quite silly, now that you mention it. Edited.Fumikofumitory

© 2022 - 2024 — McMap. All rights reserved.