将Excel范围转换为C#数组

jk9hmnmh  于 2023-05-23  发布在  C#
关注(0)|答案(6)|浏览(206)

我想用以下代码将Excel Range转换为C# Array:

System.Array MyRange = (System.Array)range.cells.value;

for (int k = 0; k <= MyRange.Length; k++)
{
    List<service_name> _ml = new List<service_name>();
    for (int j = 1; j < dataitems.Count; j++)
    {
        // enter code here
    }
}

然后像上面的循环一样迭代它。
但这段代码不起作用,并抛出此Exception:
“无法将类型为'System.String'的对象强制转换为类型为'System.Array'。”

v7pvogib

v7pvogib1#

根据Microsoft here提供的帮助,这是我在Excel中读取和写入数组的方法。

var xlApp=new Microsoft.Office.Interop.Excel.Application();
var wb=xlApp.Workbooks.Open(fn, ReadOnly: false);
xlApp.Visible=true;
var ws=wb.Worksheets[1] as Worksheet;
var r=ws.Range["A2"].Resize[100, 1];
var array=r.Value;
// array is object[1..100,1..1]
for(int i=1; i<=100; i++)
{
    var text=array[i, 1] as string;
    Debug.Print(text);
}
// to create an [1..100,1..1] array use
var array2=Array.CreateInstance(
    typeof(object), 
    new int[] {100, 1}, 
    new int[] {1, 1}) as object[,];

// fill array2
for(int i=1; i<=100; i++)
{
    array2[i, 1] = string.Format("Text{0}",i);
}
r.Value2=array2;

wb.Close(SaveChanges: true);
xlApp.Quit();

qyyhg6bp

qyyhg6bp2#

原始帖子中的错误消息发生在范围只包含一个单元格时,因为结果值的类型是可变的,实际上可以是数组,双精度,字符串,日期和null。
一种解决方案可以是,您检查细胞计数,并在恰好一个细胞的情况下采取不同的行动。
我的解决方案创建了一个单元数组。即使有一个或多个单元格为空(这可能会导致空对象),此操作也有效。(当区域的所有单元格都为空时,Range.Cells.Value为null。)

System.Array cellArray = range.Cells.Cast<Excel.Range>().ToArray<Excel.Range>();

如果你喜欢列表而不是数组(像我一样),你可以使用以下代码:

List<Excel.Range> listOfCells = range.Cells.Cast<Excel.Range>().ToList<Excel.Range>();

范围可以是一维或二维的。
最后,如果你确实需要一个字符串数组,这里是:

string[] strArray = range.Cells.Cast<Excel.Range>().Select(Selector).ToArray<string>();

其中Selector函数如下所示:

public string Selector(Excel.Range cell)
{
    if (cell.Value2 == null)
        return "";
    if (cell.Value2.GetType().ToString() == "System.Double")
        return ((double)cell.Value2).ToString();
    else if (cell.Value2.GetType().ToString() == "System.String")
        return ((string)cell.Value2);
    else if (cell.Value2.GetType().ToString() == "System.Boolean")
        return ((bool)cell.Value2).ToString();
    else
        return "unknown";
}

我包括了“unknown”,因为我不记得Value2可以返回的所有数据类型。如果您发现任何其他类型,请改进此功能。

kyxcudwk

kyxcudwk3#

注意:此示例仅适用于多于一个单元格的范围。如果Range只是一个单元格(1x1),Excel将以特殊的方式处理它,并且range.Value2将不会返回二维数组,而是一个单一的值。正是这些类型的特殊情况,以及零和非零数组下限,会让你抓狂:

using Excel = Microsoft.Office.Interop.Excel;

private static void Test()
{
    Excel.Range range = Application.ActiveWorkbook.ActiveSheet.Range["A1:B2"]; // 2x2 array

    range.Cells[1, 2] = "Foo"; // Sets Cell A2 to "Foo"
    dynamic[,] excelArray = range.Value2 as dynamic[,]; // This is a very fast operation
    Console.Out.WriteLine(excelArray[1, 2]); // => Foo

    excelArray[1, 2] = "Bar";
    range.Value2 = excelArray; // Sets Cell A2 to "Bar", again a fast operation even for large arrays
    Console.Out.WriteLine(range.Cells[1, 2]); // => Bar

请注意,excelArray的行和列下限为1:

Console.Out.WriteLine("RowLB: " + excelArray.GetLowerBound(0)); // => RowLB: 1
    Console.Out.WriteLine("ColLB: " + excelArray.GetLowerBound(1)); // => ColLB: 1

但是,如果你在C#中声明一个newArray并赋值,那么下限将为0,但它仍然可以工作:

dynamic[,] newArray = new dynamic[2, 2]; // Same dimensions as "A1:B2" (2x2)
    newArray[0, 1] = "Foobar";
    range.Value2 = newArray; // Sets Cell A2 to "Foobar"
    Console.Out.WriteLine(range.Cells[1, 2]); // => Foobar

从范围中获取此值将为您提供下限为0的原始数组:

range.Cells[1, 2] = "Fubar";

    dynamic[,] lastArray = range.Value2 as dynamic[,];
    Console.Out.WriteLine(lastArray[0, 1]); // => Fubar

    Console.Out.WriteLine("RowLB: " + lastArray.GetLowerBound(0)); // => RowLB: 0
    Console.Out.WriteLine("ColLB: " + lastArray.GetLowerBound(1)); // => ColLB: 0
}

使用Excel Interop可能会令人生畏,因为在代码库中有许多类似的特殊情况,但我希望这有助于澄清至少这一点。

68de4m5k

68de4m5k4#

该错误意味着该值是一个字符串,因此不能直接将其转换为数组。
例如,如果值是逗号删除的字符串,则可以使用Split来获取数组:

string[] MyRange = (range.Cells.Value + "").Split(',');
for (int k = 0; k < MyRange.Length; k++)
{
    //...loop here...
}

还修复了你的循环,你会得到索引越界错误。

6psbrbz9

6psbrbz95#

迟到的谈话,但这里是一个方法来做到这一点:

static string[][] GetStringArray(Object rangeValues)
{
    string[][] stringArray = null;

    Array array = rangeValues as Array;
    if (null != array)
    {
        int rank = array.Rank;
        if (rank > 1)
        {
            int rowCount = array.GetLength(0);
            int columnCount = array.GetUpperBound(1);

            stringArray = new string[rowCount][];

            for (int index = 0; index < rowCount; index++)
            {
                stringArray[index] = new string[columnCount];

                for (int index2 = 0; index2 < columnCount; index2++)
                {
                    Object obj = array.GetValue(index + 1, index2 + 1);
                    if (null != obj)
                    {
                        string value = obj.ToString();

                        stringArray[index][index2] = value;
                    }
                }
            }
        }
    }

    return stringArray;
}

调用:

string[][] rows = GetStringArray(range.Cells.Value2);
nom7f22z

nom7f22z6#

这个问题是因为,当你的区域变成一个单元格,并且“range.value”/“range.cell.value”表示String值时,这个字符串不能放入对象数组。所以检查你的范围是否只有一个或多个单元格,并根据这一点

相关问题