C# 在VSTO项目中从Excel工作簿读取50万条记录
我正在尝试使用VSTO并通过创建VisualStudio2010 Office工作簿项目在Excel中构建一个模拟工具。此工作簿中的一个工作表将包含大约50万条记录。理想情况下,我希望读取模拟中使用它们的所有记录,然后输出一些统计数据。到目前为止,当我尝试获取整个范围,然后一次性将单元格从中取出时,出现了C# 在VSTO项目中从Excel工作簿读取50万条记录,c#,excel,vsto,C#,Excel,Vsto,我正在尝试使用VSTO并通过创建VisualStudio2010 Office工作簿项目在Excel中构建一个模拟工具。此工作簿中的一个工作表将包含大约50万条记录。理想情况下,我希望读取模拟中使用它们的所有记录,然后输出一些统计数据。到目前为止,当我尝试获取整个范围,然后一次性将单元格从中取出时,出现了OutOfMemory异常。有人对我如何阅读所有数据或建议有其他想法吗 这是我的代码: Excel.Range Range=Globals.shData.Range[“A2:AX500000”]
OutOfMemory
异常。有人对我如何阅读所有数据或建议有其他想法吗
这是我的代码:
Excel.Range Range=Globals.shData.Range[“A2:AX500000”]代码>
数组值=(数组)range.Cells.Value代码>这不是Excel的问题,而是一般的C#问题。与其收集内存中的所有行,不如生成行并迭代计算统计数据
比如说
class Program
{
static void Main(string[] args)
{
var totalOfAllAges = 0D;
var rows = new ExcelRows();
//calculate various statistics
foreach (var item in rows.GetRow())
{
totalOfAllAges += item.Age;
}
Console.WriteLine("The total of all ages is {0}", totalOfAllAges);
}
}
internal class ExcelRows
{
private double rowCount = 1500000D;
private double rowIndex = 0D;
public IEnumerable<ExcelRow> GetRow()
{
while (rowIndex < rowCount)
{
rowIndex++;
yield return new ExcelRow() { Age = rowIndex };
}
}
}
/// <summary>
/// represents the next read gathered by VSTO
/// </summary>
internal class ExcelRow
{
public double Age { get; set; }
}
类程序
{
静态void Main(字符串[]参数)
{
var totalOfAllAges=0D;
var rows=新的ExcelRows();
//计算各种统计数字
foreach(行中的var项。GetRow())
{
总居住面积+=项目使用年限;
}
WriteLine(“所有年龄段的总数为{0}”,totalOfAllAges);
}
}
内部类ExcelRows
{
私有双行计数=1500000D;
私有双行索引=0D;
公共IEnumerable GetRow()
{
while(行索引<行计数)
{
rowIndex++;
返回新的ExcelRow(){Age=rowIndex};
}
}
}
///
///表示VSTO收集的下一次读取
///
内部类ExcelRow
{
公共双年龄{get;set;}
}
如何分批获取,并在内存中组装一个内存稍少的模型
var firstRow = 2;
var lastRow = 500000;
var batchSize = 5000;
var batches = Enumerable
.Range(0, (int)Math.Ceiling( (lastRow-firstRow) / (double)batchSize ))
.Select(x =>
string.Format(
"A{0}:AX{1}",
x * batchSize + firstRow,
Math.Min((x+1) * batchSize + firstRow - 1, lastRow)))
.Select(range => ((Array)Globals.shData.Range[range]).Cells.Value);
foreach(var batch in batches)
{
foreach(var item in batch)
{
//reencode item into your own object collection.
}
}
您是否通过将范围分配给数组收到异常?是的。我取回了System.Array中的Cells.Value属性向机器添加更多内存?我会尝试这里提供的解决方案:这可能也很相关:这对理解大小/内存限制也很有用,尽管在这种情况下,我指的是C++,实际上是想把数据存储在CSV中,然后用ADO加载它,这样我就可以使用光标并一次运行一个块的模拟。这与光标的净效果相同,并且避免了与另一个文件的额外工作。这是一个很好的主意。我想用ADO.Net来做这个。