4

VSTOを使用し、Visual Studio 2010 Officeワークブックプロジェクトを作成して、Excelでシミュレーションツールを構築しようとしています。このワークブックのワークシートの1つには、約50万件のレコードが含まれます。理想的には、すべてのレコードを読み取り、シミュレーションでそれらを使用してから、いくつかの統計を出力したいと思います。これまでのところOutOfMemory、範囲全体を取得してからセルを一度に取得しようとしたときに例外がありました。これを行う際にすべてのデータまたは提案を読み取る方法について、他のアイデアはありますか?

これは私のコードです:

Excel.Range range = Globals.shData.Range["A2:AX500000"];

Array values = (Array)range.Cells.Value;

4

2 に答える 2

8

バッチでフェッチして、メモリの負荷がわずかに少ないモデルをメモリにアセンブルするのはどうですか?

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.
    }
}
于 2012-04-30T15:01:15.287 に答える
2

これは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; }
}
于 2012-04-30T14:59:57.460 に答える