我正在尝试在C#中编写一个方法,在Excel工作簿中给定命名范围的名称,检索该范围内的值。即使命名范围不是对范围的纯引用(例如=Sheet1!A1:A10
),我也希望它能够工作,而是={1,2,3,4,5}
或=OFFSET(Sheet1!A1:A10,3)
。
我正在做以下事情:
Excel.Application xl = ...;
Excel.Name name = ...;
object value = xl.Evaluate(name.Value);
// if it's a range, turn it into an object[] or object[,]
if (value is Excel.Range) value = ((Excel.Range)value).Value2;
if (value is object[]) {
// do stuff
} else if (value is object[,]) {
// do slightly different stuff
}
我原以为像={1,2,3,4,5}
这样的名称范围只会是object[]
或object[,]
,但事实并非如此。 value.GetType()
只报告System.__ComObject
(编辑:现在我收到System.Object[*]
,但无法重现System.__ComObject
- 但它仍然没有投放到object[]
1}}),我无法进一步缩小范围。
我应该将value
投射到哪个类型?
编辑:这里有一些测试代码和输出。这可能是一个更简单的问题:“System.Object[*]
是什么,谷歌的变幻莫测不允许我搜索。
代码:
using System;
using Excel = Microsoft.Office.Interop.Excel;
namespace Test
{
class Program
{
static void Main(string[] args)
{
Excel.Application xl = new Excel.Application();
object value = xl.Evaluate("={1,2,3,4,5}");
Console.WriteLine(value);
Console.WriteLine(value is object[]);
Console.WriteLine(value.GetType());
Console.ReadLine();
xl.Quit();
}
}
}
输出:
System.Object的[*]
假
System.Object的[*]
edit2:如果我改为评估"={1;2;3;4;5}"
,那么我会得到object[,]
。咦。
答案 0 :(得分:1)
我认为这是因为Excel创建的数组不是基于0的,而是基于1的,你可以像这样转换它:
object[] ints = ((Array)value).ToArray<object>();
使用此辅助方法扩展名:
public static T[] ToArray<T>(this Array array)
{
if (array == null)
return null;
if (array.Rank != 1)
throw new NotSupportedException();
var newArray = new T[array.GetLength(0)];
var lb = array.GetLowerBound(0);
for (int i = 0; i < newArray.Length; i++)
{
newArray[i] = (T)array.GetValue(i + lb);
}
return newArray;
}
如果您使用.NET 4,则Evaluate
的返回类型可能会被定义为dynamic
。所以使用此代码:
dynamic value = xl.Evaluate("={1,2,3,4,5}"); // or var instead of dynamic
您将获得System.InvalidCastException: Unable to cast object of type 'System.Object[*]' to type 'System.Object[]
'因为新的.NET 4互操作层将自动尝试创建标准数组。所以你需要这样做(就像你在代码中那样):
object value = xl.Evaluate("={1,2,3,4,5}");
object[] ints = ((Array)value).ToArray<object>();