Aspose.Cells for C++ でピボットテーブルにフィルターフィールドを追加する

はじめに

フィルターフィールドは、ピボット本体に表示されるソースデータのどの部分集合かを制御するピボットフィールドです。Excel でレンダリングされたピボットの上部には、エンドユーザーが選択できるドロップダウンとして表示されます。利用可能なフィルター項目を 1 つ選択すると、そのフィルター項目に属するレコードだけが要約されるようにピボット本体が再構築されます。ピボットフィールドが PivotFieldType.Row、PivotFieldType.Column または PivotFieldType.Data としてではなく、PivotFieldType.Page として登録されると、フィルターフィールドになります。

フィルターフィールドを追加する

AddFieldToArea を使用してフィルターフィールドを追加する

次の例では、小さな Fruit / Year / Amount データセットを作成し、Fruit を行領域、Amount をデータ領域、Year をフィルター領域に割り当てて、E3 セルにピボットテーブルを作成します。その後、ピボットを更新し、ワークブックを保存します。

#include "Aspose.Cells.h"
using namespace Aspose::Cells;
using namespace Aspose::Cells::Pivot;
int main() {
    Aspose::Cells::Startup();
    // 新しいワークブックを作成します
    Workbook workbook;
    Worksheet worksheet = workbook.GetWorksheets().Get(0);
    worksheet.SetName(u"Data");
    Cells cells = worksheet.GetCells();
    // ヘッダー行を設定します
    cells.Get(u"A1").PutValue(u"Fruit");
    cells.Get(u"B1").PutValue(u"Year");
    cells.Get(u"C1").PutValue(u"Amount");
    // 9行のサンプルデータ(Fruit、Year、Amount)を入力します
    const char* fruits[] = { "apple", "banana", "apple", "grape", "orange", "banana", "grape", "apple", "orange" };
    int years[]   = { 2020, 2021, 2021, 2020, 2022, 2020, 2021, 2022, 2021 };
    int amounts[] = { 100, 200, 150, 120, 180, 90, 130, 170, 110 };
    for (int i = 0; i < 9; ++i)
    {
        cells.Get(i + 1, 0).PutValue(U16String(fruits[i]));
        cells.Get(i + 1, 1).PutValue(years[i]);
        cells.Get(i + 1, 2).PutValue(amounts[i]);
    }
    // セル E3 を基準位置としてピボットテーブルを追加します
    PivotTable pivotTable = worksheet.GetPivotTables().Add(u"A1:C10", 2, 4);
    // フィールドを各領域に追加します:Fruitを行、Amountをデータ、Yearをページフィールドとして指定します
    pivotTable.AddFieldToArea(PivotFieldType::Row, u"Fruit");
    pivotTable.AddFieldToArea(PivotFieldType::Data, u"Amount");
    pivotTable.AddFieldToArea(PivotFieldType::Page, u"Year");
    // ピボットテーブルのデータを更新して計算します
    pivotTable.CalculateData();
    // ワークブックを保存します
    workbook.Save(u"pageFieldSample.xlsx");
    Aspose::Cells::Cleanup();
    return 0;
}

PageFields.Add を使用してフィルターフィールドを追加する

すでに PivotField インスタンスを操作している場合は、それを直接 PivotTable.PageFields.Add に渡すことができます。ピボットテーブルとフィルターフィールドは前の例とまったく同様に構成されます。異なるのは、最終的なフィルター領域への登録のみが下位レベルの API 呼び出しに置き換えられるという点です。

#include "Aspose.Cells.h"
#include <string>
using namespace Aspose::Cells;
using namespace Aspose::Cells::Pivot;
int main() {
    Aspose::Cells::Startup();
    Workbook workbook;
    Worksheet sheet = workbook.GetWorksheets().Get(0);
    Cells cells = sheet.GetCells();
    // ヘッダー
    cells.Get(u"A1").PutValue(u"Fruit");
    cells.Get(u"B1").PutValue(u"Year");
    cells.Get(u"C1").PutValue(u"Amount");
    // サンプルデータ(9行)
    cells.Get(u"A2").PutValue(u"apple");     cells.Get(u"B2").PutValue(u"2020"); cells.Get(u"C2").PutValue(100);
    cells.Get(u"A3").PutValue(u"apple");     cells.Get(u"B3").PutValue(u"2021"); cells.Get(u"C3").PutValue(150);
    cells.Get(u"A4").PutValue(u"apple");     cells.Get(u"B4").PutValue(u"2022"); cells.Get(u"C4").PutValue(200);
    cells.Get(u"A5").PutValue(u"grape");     cells.Get(u"B5").PutValue(u"2020"); cells.Get(u"C5").PutValue(300);
    cells.Get(u"A6").PutValue(u"grape");     cells.Get(u"B6").PutValue(u"2021"); cells.Get(u"C6").PutValue(400);
    cells.Get(u"A7").PutValue(u"grape");     cells.Get(u"B7").PutValue(u"2022"); cells.Get(u"C7").PutValue(500);
    cells.Get(u"A8").PutValue(u"blueberry"); cells.Get(u"B8").PutValue(u"2020"); cells.Get(u"C8").PutValue(250);
    cells.Get(u"A9").PutValue(u"blueberry"); cells.Get(u"B9").PutValue(u"2021"); cells.Get(u"C9").PutValue(350);
    cells.Get(u"A10").PutValue(u"blueberry");cells.Get(u"B10").PutValue(u"2022");cells.Get(u"C10").PutValue(450);
    // E3にA1:C10を範囲とするピボットテーブルを追加
    PivotTableCollection pivotTables = sheet.GetPivotTables();
    int pivotIndex = pivotTables.Add(U16String(u"A1:C10"), U16String(u"E3"), U16String(u"PivotTable1"));
    PivotTable pivotTable = pivotTables.Get(pivotIndex);
    // 果物 -> 行、金額 -> データ
    pivotTable.AddFieldToArea(PivotFieldType::Row, U16String(u"Fruit"));
    pivotTable.AddFieldToArea(PivotFieldType::Data, U16String(u"Amount"));
    // 低レベルアプローチ:BaseFields内の既存のYear PivotFieldを検索し、
    // PageFields.Add(PivotField)を使用してページ領域に登録する。
    PivotFieldCollection baseFields = pivotTable.GetBaseFields();
    int baseFieldCount = baseFields.GetCount();
    for (int i = 0; i < baseFieldCount; ++i) {
        PivotField f = baseFields.Get(i);
        if (f.GetName().ToUtf8() == "Year") {
            pivotTable.GetPageFields().Add(f);
            break;
        }
    }
    // 新しいページフィールドが保存されたワークブックに反映されるように更新する
    pivotTable.CalculateData();
    workbook.Save(u"output.xlsx");
    Aspose::Cells::Cleanup();
    return 0;
}

単一選択フィルター(1 つのフィルター項目を表示する)

デフォルトの単一選択動作では、フィルターフィールドは単一のドロップダウンとして表示され、PivotField.CurrentPageItem の整数値は、ピボット本体をどのフィルター項目で制御するかを指定します。特定のインデックスを割り当てると、その項目だけが選択されます。特殊な番兵値 0x7FFD(10 進数で 32765)を割り当てると、フィルターがクリアされ、すべてのフィルター項目が同時に要約されます。単一選択はデフォルトであるため、明示的に有効にする必要はありません。

すべての項目を表示する

CurrentPageItem を特殊な値 0x7FFD に設定すると、フィルターをクリアした場合と同じ結果になります。ピボット本体には、フィルターが適用されていないかのように、すべてのフィルター項目が要約されます。

#include "Aspose.Cells.h"
using namespace Aspose::Cells;
using namespace Aspose::Cells::Pivot;
int main() {
    Aspose::Cells::Startup();
    Workbook workbook;
    Worksheet sheet = workbook.GetWorksheets().Get(0);
    Cells cells = sheet.GetCells();
    cells.Get(u"A1").PutValue(u"Fruit");
    cells.Get(u"B1").PutValue(u"Year");
    cells.Get(u"C1").PutValue(u"Amount");
    U16String fruits[6] = {u"Apple", u"Apple", u"Banana", u"Banana", u"Cherry", u"Cherry"};
    int years[6] = {2022, 2023, 2022, 2023, 2022, 2023};
    int amounts[6] = {100, 150, 80, 120, 200, 250};
    for (int r = 0; r < 6; r++) {
        cells.Get(r + 1, 0).PutValue(fruits[r]);
        cells.Get(r + 1, 1).PutValue(years[r]);
        cells.Get(r + 1, 2).PutValue(amounts[r]);
    }
    PivotTableCollection pivotTables = sheet.GetPivotTables();
    PivotTable pivotTable = pivotTables.Add(u"=A1:C7", 2, 4);
    pivotTable.AddFieldToArea(PivotFieldType::Row, u"Fruit");
    pivotTable.AddFieldToArea(PivotFieldType::Data, u"Amount");
    pivotTable.AddFieldToArea(PivotFieldType::Page, u"Year");
    pivotTable.CalculateData();
    pivotTable.GetPageFields().Get(0).SetCurrentPageItem(0x7FFD);
    workbook.Save(u"output.xlsx");
    Aspose::Cells::Cleanup();
    return 0;
}

特定の項目を 1 つ表示する

CurrentPageItem を実際の項目のインデックスに設定すると、その項目だけが選択されます。このインデックスは、フィルターフィールドのソート済みの項目一覧における項目の位置です。したがって、例えば 1 は、ソート後の 2 番目の項目を選択します。

#include "Aspose.Cells.h"
using namespace Aspose::Cells;
using namespace Aspose::Cells::Pivot;
int main() {
    Aspose::Cells::Startup();
    Workbook workbook;
    Worksheet sheet = workbook.GetWorksheets().Get(0);
    Cells cells = sheet.GetCells();
    cells.Get(u"A1").PutValue(U16String("Fruit"));
    cells.Get(u"B1").PutValue(U16String("Year"));
    cells.Get(u"C1").PutValue(U16String("Amount"));
    cells.Get(u"A2").PutValue(U16String("Apple"));
    cells.Get(u"B2").PutValue(U16String("2020"));
    cells.Get(u"C2").PutValue(U16String("100"));
    cells.Get(u"A3").PutValue(U16String("Apple"));
    cells.Get(u"B3").PutValue(U16String("2021"));
    cells.Get(u"C3").PutValue(U16String("150"));
    cells.Get(u"A4").PutValue(U16String("Banana"));
    cells.Get(u"B4").PutValue(U16String("2020"));
    cells.Get(u"C4").PutValue(U16String("200"));
    cells.Get(u"A5").PutValue(U16String("Banana"));
    cells.Get(u"B5").PutValue(U16String("2021"));
    cells.Get(u"C5").PutValue(U16String("250"));
    PivotTableCollection pivotTables = sheet.GetPivotTables();
    int pivotIndex = pivotTables.Add(U16String("A1:C5"), U16String("E3"), U16String("PivotTable1"));
    PivotTable pivotTable = pivotTables.Get(pivotIndex);
    pivotTable.AddFieldToArea(PivotFieldType::Row, U16String("Fruit"));
    pivotTable.AddFieldToArea(PivotFieldType::Data, U16String("Amount"));
    pivotTable.AddFieldToArea(PivotFieldType::Page, U16String("Year"));
    pivotTable.GetPageFields().Get(0).SetCurrentPageItem(1);
    pivotTable.CalculateData();
    workbook.Save(u"output.xlsx");
    Aspose::Cells::Cleanup();
    return 0;
}

複数選択フィルター

複数選択フィルターでは、フィルターのドロップダウンがチェックボックス一覧になり、ユーザーが複数のフィルター項目を同時に選択できます。Aspose.Cells は、連携して機能する 2 つのプロパティを提供します。複数選択 UI を有効にするには、まず PivotField.IsMultipleItemSelectionAllowed を true に設定する必要があります。有効化すると、PivotItem.IsHidden によって、チェックボックス一覧に表示される項目を制御できます。そのため、すべての項目を表示することも、特定の項目だけをホワイトリストに含めることもできます。

#include "Aspose.Cells.h"
#include <string>
#include <vector>
using namespace Aspose::Cells;
using namespace Aspose::Cells::Pivot;
int main() {
    Aspose::Cells::Startup();
    Workbook workbook;
    Worksheet sheet = workbook.GetWorksheets().Get(0);
    Cells cells = sheet.GetCells();
    // サンプルデータ: 果物 | 年 | 数量
    cells.Get(0, 0).PutValue(u"Fruit");
    cells.Get(0, 1).PutValue(u"Year");
    cells.Get(0, 2).PutValue(u"Amount");
    std::vector<std::vector<std::string>> data = {
        {"apple",  "2019", "100"},
        {"apple",  "2020", "150"},
        {"apple",  "2021", "200"},
        {"banana", "2019", "110"},
        {"banana", "2020", "160"},
        {"banana", "2021", "210"},
        {"grape",  "2019", "120"},
        {"grape",  "2020", "170"},
        {"grape",  "2021", "220"}
    };
    for (int i = 0; i < (int)data.size(); i++) {
        cells.Get(i + 1, 0).PutValue(U16String(data[i][0].c_str()));
        cells.Get(i + 1, 1).PutValue(std::stoi(data[i][1]));
        cells.Get(i + 1, 2).PutValue(std::stoi(data[i][2]));
    }
    Worksheet pivotSheet = workbook.GetWorksheets().Add(u"Pivot");
    PivotTableCollection pivots = pivotSheet.GetPivotTables();
    PivotTable pivotTable = pivots.Add(u"A1:C10", 2, 4);
    pivotTable.AddFieldToArea(PivotFieldType::Row, u"Fruit");
    pivotTable.AddFieldToArea(PivotFieldType::Data, u"Amount");
    pivotTable.AddFieldToArea(PivotFieldType::Page, u"Year");
    // — ページフィールドで複数選択を有効にする
    pivotTable.GetPageFields().Get(0).SetIsMultipleItemSelectionAllowed(true);
    // パート A — すべての項目を選択する(すべての項目を表示可能にする)
    PivotItemCollection pivotItems = pivotTable.GetPageFields().Get(0).GetPivotItems();
    int itemCount = pivotItems.GetCount();
    for (int i = 0; i < itemCount; i++) {
        pivotItems.Get(i).SetIsHidden(false);
    }
    // パート B — ソース値に基づいて特定の項目だけを選択する
    for (int i = 0; i < itemCount; i++) {
        U16String val = pivotItems.Get(i).GetStringValue();
        std::string s = val.ToUtf8();
        if (s == "2020" || s == "grape" || s == "blueberry") {
            pivotItems.Get(i).SetIsHidden(false);
        } else {
            pivotItems.Get(i).SetIsHidden(true);
        }
    }
    pivotTable.CalculateData();
    workbook.Save(u"output.xlsx");
    Aspose::Cells::Cleanup();
    return 0;
}

注: PivotItem.IsHidden を使って複数選択フィルターを設定する場合、少なくとも 1 つの PivotItem を表示状態(IsHidden == false)に保つ必要があります。すべての項目を非表示にすると、Excel はファイルを開いたときにクラッシュするか、空のピボットを描画します。複数選択のホワイトリストには、ソースデータから少なくとも 1 つの項目が含まれていることを必ず確認してください。

どの API とどのモードを使用すべきか?

以下の表は、各 API とモードをいつ使用すべきかを示しています。すべてのシナリオを詳しく読まずに、適切な組み合わせを選択できます。

シナリオ / ユースケース 推奨 API 使用するプロパティ 注記
ソース列名でフィルターフィールドを追加する(最も一般的) PivotTable.AddFieldToArea(PivotFieldType.Page, "fieldName") 該当なし 1 行で追加できる高レベルの API です。PivotField への参照が必要な場合を除き、これを使用します。
PivotField オブジェクトをすでに保有している場合にフィルターフィールドを追加する PivotTable.PageFields.Add(PivotField) 該当なし フィールドオブジェクトを別の場所で取得した場合、または再利用する必要がある場合に使用します。
単一のフィルター項目に絞り込む(デフォルトモード) PivotField.CurrentPageItem 特定のインデックスを設定 例えば、1 はソート済みリストの 2 番目の項目を表示します。
すべての項目を表示する / フィルターをクリアする PivotField.CurrentPageItem 0x7FFD に設定 この特殊な値 0x7FFD(10 進数で 32765)は、「すべての項目」を表す番兵値です。
Excel で複数選択 UI を有効にする PivotField.IsMultipleItemSelectionAllowed true に設定 IsHidden 呼び出しを機能させる前に必要です。
複数選択一覧内の個別の項目を非表示にする / 表示する PivotItem.IsHidden 項目ごとに設定 少なくとも 1 つの項目を表示状態(IsHidden == false)に保つ必要があります。