C++で列挙子(エナムレーター)を使用する方法と用途
列挙子は、コンテナまたはコレクションを横断する能力を提供するオブジェクトです。列挙子はコレクション内のデータを読むことができますが、基礎となるコレクションの変更はできません。一方、IEnumerableは、GetEnumeratorメソッドを定義し、IEnumeratorインターフェースを返すインターフェースで、このインターフェースはコレクションへの読み取り専用アクセスを可能にします。
Aspose.CellsのAPIはたくさんの列挙子を提供していますが、この記事では主に以下にリストされている3つのタイプについて説明しています。
- セル列挙子
- 行列挙子
- 列列挙子
列挙子の使用方法
セル列挙子
セル列挙子へのアクセス方法にはさまざまな方法があり、アプリケーションの要件に基づいてこれらのメソッドのいずれかを使用できます。セル列挙子を返すメソッドは次のとおりです。
上記のすべての方法は、初期化されたセルコレクションをトラバースする列挙子を返します。
以下のコード例は、CellsコレクションのIEnumeratorインターフェースの実装を示しています。
#include <iostream>
#include <memory>
#include "Aspose.Cells.h"
using namespace Aspose::Cells;
int main()
{
    Aspose::Cells::Startup();
    // Source directory path
    U16String srcDir(u"..\\Data\\01_SourceDirectory\\");
    // Load a file in an instance of Workbook
    Workbook book(srcDir + u"sample.xlsx");
    // Get the enumerator from Cells collection
    auto cellEnumerator = book.GetWorksheets().Get(0).GetCells().GetEnumerator();
    // Traverse cells in the collection
    while (cellEnumerator.MoveNext())
    {
        auto cell = cellEnumerator.GetCurrent();
        std::cout << cell.GetName().ToUtf8() << " " << cell.GetValue().ToString().ToUtf8() << std::endl;
    }
    // Get enumerator from an object of Row
    auto rowEnumerator = book.GetWorksheets().Get(0).GetCells().GetRows().Get(0).GetEnumerator();
    // Traverse cells in the given row
    while (rowEnumerator.MoveNext())
    {
        auto cell = rowEnumerator.GetCurrent();
        std::cout << cell.GetName().ToUtf8() << " " << cell.GetValue().ToString().ToUtf8() << std::endl;
    }
    // Get enumerator from an object of Range
    auto rangeEnumerator = book.GetWorksheets().Get(0).GetCells().CreateRange(u"A1:B10").GetEnumerator();
    // Traverse cells in the range
    while (rangeEnumerator.MoveNext())
    {
        auto cell = rangeEnumerator.GetCurrent();
        std::cout << cell.GetName().ToUtf8() << " " << cell.GetValue().ToString().ToUtf8() << std::endl;
    }
    Aspose::Cells::Cleanup();
}
行列挙子
行の列挙子は RowCollection.GetEnumerator メソッドを使用してアクセス可能です。以下のコード例は、RowCollection のための IEnumerator インターフェースの実装を示しています。
#include <iostream>
#include "Aspose.Cells.h"
using namespace Aspose::Cells;
int main()
{
    Aspose::Cells::Startup();
    // Source directory path
    U16String srcDir(u"..\\Data\\01_SourceDirectory\\");
    // Load a file in an instance of Workbook
    Workbook book(srcDir + u"sample.xlsx");
    // Get the enumerator for RowCollection
    auto rowsEnumerator = book.GetWorksheets().Get(0).GetCells().GetRows().GetEnumerator();
    // Traverse rows in the collection
    while (rowsEnumerator.MoveNext())
    {
        auto row = rowsEnumerator.GetCurrent();
        std::cout << row.GetIndex() << std::endl;
    }
    Aspose::Cells::Cleanup();
}
列の取得
列は ColumnCollection.Get メソッドを使用してアクセス可能です。以下のコード例は、ColumnCollection の Get メソッドの実装を示しています。
#include <iostream>
#include <memory>
#include "Aspose.Cells.h"
using namespace Aspose::Cells;
int main()
{
    Aspose::Cells::Startup();
    U16String srcDir(u"..\\Data\\01_SourceDirectory\\");
    Workbook book(srcDir + u"sample.xlsx");
    auto cells = book.GetWorksheets().Get(0).GetCells();
    auto columns = cells.GetColumns();
    for (int i = 0; i < columns.GetCount(); ++i)
    {
        auto col = columns.Get(i);
        std::cout << col.GetIndex() << std::endl;
    }
    Aspose::Cells::Cleanup();
    return 0;
}
列挙子の使用場所
列挙子の利点を議論するために、実際の例を使って説明しましょう。
シナリオ
特定の Worksheet 内のすべてのセルを走査し、その値を読み取ることがアプリケーションの要件です。これを実現する方法はいくつかあります。以下にいくつか例を示します。
表示範囲を使用する
#include <iostream>
#include "Aspose.Cells.h"
using namespace Aspose::Cells;
int main()
{
    Aspose::Cells::Startup();
    // Source directory path
    U16String srcDir(u"..\\Data\\01_SourceDirectory\\");
    // Path of input excel file
    U16String inputFilePath = srcDir + u"sample.xlsx";
    // Load a file in an instance of Workbook
    Workbook book(inputFilePath);
    // Get Cells collection of first worksheet
    Cells cells = book.GetWorksheets().Get(0).GetCells();
    // Get the MaxDisplayRange
    Range displayRange = cells.GetMaxDisplayRange();
    // Loop over all cells in the MaxDisplayRange
    for (int row = displayRange.GetFirstRow(); row < displayRange.GetRowCount(); row++)
    {
        for (int col = displayRange.GetFirstColumn(); col < displayRange.GetColumnCount(); col++)
        {
            // Read the Cell value
            std::cout << displayRange.Get(row, col).GetStringValue().ToUtf8() << std::endl;
        }
    }
    Aspose::Cells::Cleanup();
}
MaxDataRowおよびMaxDataColumnを使用する
#include <iostream>
#include "Aspose.Cells.h"
using namespace Aspose::Cells;
using namespace std;
int main()
{
    Aspose::Cells::Startup();
    // Source directory path
    U16String srcDir(u"..\\Data\\01_SourceDirectory\\");
    // Load a file in an instance of Workbook
    Workbook book(srcDir + u"sample.xlsx");
    // Get Cells collection of first worksheet
    auto cells2 = book.GetWorksheets().Get(0).GetCells();
    // Get maximum data row and column
    int maxDataRow = cells2.GetMaxDataRow();
    int maxDataColumn = cells2.GetMaxDataColumn();
    // Loop over all cells
    for (int row = 0; row <= maxDataRow; row++)
    {
        for (int col = 0; col <= maxDataColumn; col++)
        {
            // Read the Cell value
            auto currentCell = cells2.GetCell(row, col);
            if (!currentCell.IsNull())
            {
                cout << currentCell.GetStringValue().ToUtf8() << endl;
            }
        }
    }
    Aspose::Cells::Cleanup();
    return 0;
}
上記のアプローチのそれぞれがほとんど同じロジックを使用していることがわかります。つまり、コレクション内のすべてのセルをループしてセルの値を読み取ります。これにはいくつかの理由で問題が生じる可能性があります。
- GetMaxRow()、GetMaxDataRow()、GetMaxColumn()、GetMaxDataColumn()、GetMaxDisplayRange() などのAPIは、対応する統計情報を収集するのに追加の時間が必要です。行×列のデータマトリックスが大きい場合、これらのAPIを使用するとパフォーマンスに影響を及ぼす可能性があります。
- ほとんどの場合、指定された範囲内のすべてのセルがインスタンス化されていません。そのような状況では、行列内のすべてのセルを確認することは、初期化されたセルのみを確認する場合と比べて効率的ではありません。
- Cells row、columnとしてセルにアクセスすることは、範囲内のすべてのセルオブジェクトをインスタンス化することになり、最終的にOutOfMemoryExceptionを引き起こす可能性があります。
結論
上記の事実に基づいて、列挙子を使用すべき可能なシナリオが以下に示されています。
- セルコレクションの読み取り専用アクセスが必要な場合、つまり、セルの確認のみが必要な場合。
- 多数のセルを走査する必要がある場合。
- 初期化されたセル/行/列のみを走査する必要がある場合。