共用方式為


透過 Power BI 視覺效果選取項目,將互動功能新增至視覺效果中

Power BI 提供兩種方式來與視覺效果互動 - 選取和篩選。 以下範例示範如何從一個視覺效果中選取一個項目,並通知報表中的其他視覺效果有關新的選取項目狀態。

介面會對應至 Selection 物件:

export interface ISelectionId {
    equals(other: ISelectionId): boolean;
    includes(other: ISelectionId, ignoreHighlight?: boolean): boolean;
    getKey(): string;
    getSelector(): Selector;
    getSelectorsByColumn(): SelectorsByColumn;
    hasIdentity(): boolean;
}

使用選取項目管理員來選取資料點

視覺效果主機物件提供了建立選取項目管理員執行個體的方法。 選取項目管理員對於以下每個動作都有對應的方法:

  • 選取
  • 清除選取項目
  • 顯示操作功能表
  • 儲存目前的選取項目
  • 檢查選取項目狀態

建立選取項目管理員的執行個體

若要使用選取項目管理員,請建立選取項目管理員的執行個體。 通常,視覺效果會在視覺效果物件的 constructor 區段中建立一個選取項目管理員執行個體。

export class Visual implements IVisual {
    private target: HTMLElement;
    private host: IVisualHost;
    private selectionManager: ISelectionManager;
    // ...
    constructor(options: VisualConstructorOptions) {
        this.host = options.host;
        // ...
        this.selectionManager = this.host.createSelectionManager();
    }
    // ...
}

建立選取項目產生器的執行個體

建立選取項目管理員執行個體時,您必須為視覺效果的每個資料點都建立 selections。 視覺主機物件的 createSelectionIdBuilder 方法會為每個資料點產生選取項目。 此方法會傳回一個具有介面 powerbi.visuals.ISelectionIdBuilder 之物件的執行個體:

export interface ISelectionIdBuilder {
    withCategory(categoryColumn: DataViewCategoryColumn, index: number): this;
    withSeries(seriesColumn: DataViewValueColumns, valueColumn: DataViewValueColumn | DataViewValueColumnGroup): this;
    withMeasure(measureId: string): this;
    withMatrixNode(matrixNode: DataViewMatrixNode, levels: DataViewHierarchyLevel[]): this;
    withTable(table: DataViewTable, rowIndex: number): this;
    createSelectionId(): ISelectionId;
}

此物件具有對應的方法來為不同類型的資料檢視對應建立 selections

注意

方法 withTablewithMatrixNode 是在 Power BI 視覺效果的 API 2.5.0 中引進。 如果您需要針對資料表或矩陣資料檢視對應使用選取項目,請更新至 API 2.5.0 版或更高版本。

建立類別資料檢視對應的選取項目

讓我們來檢閱選取項目如何呈現範例語意模型的分類資料檢視對應:

製造商 類型
克萊斯勒 國內車輛 28883
克萊斯勒 國內卡車 117131
克萊斯勒 進口車輛 0
克萊斯勒 進口卡車 6362
Ford 國內車輛 50032
Ford 國內卡車 122446
Ford 進口車輛 0
Ford 進口卡車 0
GM 國內車輛 65426
GM 國內卡車 138122
GM 進口車輛 197
GM 進口卡車 0
Honda 國內車輛 51450
Honda 國內卡車 46115
Honda 進口車輛 2932
Honda 進口卡車 0
Nissan 國內車輛 51476
Nissan 國內卡車 47343
Nissan 進口車輛 5485
Nissan 進口卡車 1430
Toyota 國內車輛 55643
Toyota 國內卡車 61227
Toyota 進口車輛 20799
Toyota 進口卡車 23614

視覺效果會使用下列資料檢視對應:

{
    "dataRoles": [
        {
            "displayName": "Columns",
            "name": "columns",
            "kind": "Grouping"
        },
        {
            "displayName": "Rows",
            "name": "rows",
            "kind": "Grouping"
        },
        {
            "displayName": "Values",
            "name": "values",
            "kind": "Measure"
        }
    ],
    "dataViewMappings": [
        {
            "categorical": {
                "categories": {
                    "for": {
                        "in": "columns"
                    }
                },
                "values": {
                    "group": {
                        "by": "rows",
                        "select": [
                            {
                                "for": {
                                    "in": "values"
                                }
                            }
                        ]
                    }
                }
            }
        }
    ]
}

在上述範例中,Manufacturercolumns,而 Typerows。 按 rows 對值進行分組來建立數列 (Type)。

視覺效果應該能夠按 ManufacturerType 來分割資料。

例如,如果使用者按 Manufacturer 選取 Chrysler,則其他視覺效果應該會顯示下列資料:

製造商 類型
克萊斯勒 國內車輛 28883
克萊斯勒 國內卡車 117131
克萊斯勒 進口車輛 0
克萊斯勒 進口卡車 6362

當使用者按 Type 選取 Import Car (依數列選取資料) 時,則其他視覺效果應該會顯示以下資料:

製造商 類型
克萊斯勒 進口車輛 0
Ford 進口車輛 0
GM 進口車輛 197
Honda 進口車輛 2932
Nissan 進口車輛 5485
Toyota 進口車輛 20799

顯示具有選取項目的視覺效果的螢幕擷取畫面。

若要顯示分割的資料,請填入視覺效果的資料籃,如下所示:

顯示視覺效果資料籃的螢幕擷取畫面。

在上述範例中,Manufacturer 是類別 (資料行)、Type 是數列 (資料列),而 Sales 是數列的 Values

注意

顯示數列時需要 Values,因為根據資料檢視對應,Values 會按 Rows 資料分組。

建立類別的選取項目

// categories
const categories = dataView.categorical.categories;

// create label for 'Manufacturer' column
const p = document.createElement("p") as HTMLParagraphElement;
p.innerText = categories[0].source.displayName.toString();
this.target.appendChild(p);

// get count of category elements
const categoriesCount = categories[0].values.length;

// iterate all categories to generate selection and create button elements to use selections
for (let categoryIndex = 0; categoryIndex < categoriesCount; categoryIndex++) {
    const categoryValue: powerbi.PrimitiveValue = categories[0].values[categoryIndex];

    const categorySelectionId = this.host.createSelectionIdBuilder()
        .withCategory(categories[0], categoryIndex) // we have only one category (only one `Manufacturer` column)
        .createSelectionId();
    this.dataPoints.push({
        value: categoryValue,
        selection: categorySelectionId
    });
    console.log(categorySelectionId);

    // create button element to apply selection on click
    const button = document.createElement("button") as HTMLButtonElement;
    button.value = categoryValue.toString();
    button.innerText = categoryValue.toString();
    button.addEventListener("click", () => {
        // handle click event to apply correspond selection
        this.selectionManager.select(categorySelectionId);
    });
    this.target.appendChild(button);
}

在上述範例程式碼中,我們會逐一查看所有類別。 在每次反覆運算中,我們都會透過呼叫選取項目建立器的 withCategory 方法來呼叫 createSelectionIdBuilder 以建立每個類別的下一個選取項目。 createSelectionId 方法會用作傳回所產生之 selection 物件的最後方法。

withCategory 方法中,我們會傳遞 category 的資料行,在範例中,它的 Manufacturer 和類別元素的索引。

建立數列的選取項目

// get groupped values for series
const series: powerbi.DataViewValueColumnGroup[] = dataView.categorical.values.grouped();

// create label for 'Type' column
const p2 = document.createElement("p") as HTMLParagraphElement;
p2.innerText = dataView.categorical.values.source.displayName;
this.target.appendChild(p2);

// iterate all series to generate selection and create button elements to use selections
series.forEach( (ser: powerbi.DataViewValueColumnGroup) => {
    // create selection id for series
    const seriesSelectionId = this.host.createSelectionIdBuilder()
        .withSeries(dataView.categorical.values, ser)
        .createSelectionId();

    this.dataPoints.push({
        value: ser.name,
        selection: seriesSelectionId
    });

    // create button element to apply selection on click
    const button = document.createElement("button") as HTMLButtonElement;
    button.value =ser.name.toString();
    button.innerText = ser.name.toString();
    button.addEventListener("click", () => {
        // handle click event to apply correspond selection
        this.selectionManager.select(seriesSelectionId);
    });
    this.target.appendChild(button);
});

建立資料表資料檢視對應的選取項目

下列範例顯示資料表資料檢視對應:

{
    "dataRoles": [
        {
            "displayName": "Values",
            "name": "values",
            "kind": "GroupingOrMeasure"
        }
    ],
    "dataViewMappings": [
        {
            "table": {
                "rows": {
                    "for": {
                        "in": "values"
                    }
                }
            }
        }
    ]
}

若要為資料表資料檢視對應的每個資料列建立選取項目,請呼叫選取項目建立器的 withTable 方法。

public update(options: VisualUpdateOptions) {
    const dataView = options.dataViews[0];
    dataView.table.rows.forEach((row: DataViewTableRow, rowIndex: number) => {
        this.target.appendChild(rowDiv);
        const selection: ISelectionId = this.host.createSelectionIdBuilder()
            .withTable(dataView.table, rowIndex)
            .createSelectionId();
    }
}

視覺效果程式碼會逐一查看資料表的資料列,而每個資料列都會呼叫 withTable 資料表方法。 withTable 方法的參數是 table 物件和資料表資料列的索引。

建立矩陣資料檢視對應的選取項目

public update(options: VisualUpdateOptions) {
    const host = this.host;
    const rowLevels: powerbi.DataViewHierarchyLevel[] = dataView.matrix.rows.levels;
    const columnLevels: powerbi.DataViewHierarchyLevel[] = dataView.matrix.rows.levels;

    // iterate rows hierarchy
    nodeWalker(dataView.matrix.rows.root, rowLevels);
    // iterate columns hierarchy
    nodeWalker(dataView.matrix.columns.root, columnLevels);

    function nodeWalker(node: powerbi.DataViewMatrixNode, levels: powerbi.DataViewHierarchyLevel[]) {
        const nodeSelection = host.createSelectionIdBuilder().withMatrixNode(node, levels);

        if (node.children && node.children.length) {
            node.children.forEach(child => {
                nodeWalker(child, levels);
            });
        }
    }
}

在範例中,nodeWalker 會遞歸呼叫每個節點和子節點。

nodeWalker 會在每個呼叫上建立 nodeSelection 物件。 每個 nodeSelection 都代表對應節點的 selection

選取資料點以分割其他視覺效果

在此範例中,我們為按鈕元素建立了一個點擊處理常式。 此處理常式會呼叫選取項目管理員的 select 方法,並傳遞選取項目物件。

button.addEventListener("click", () => {
    // handle click event to apply correspond selection
    this.selectionManager.select(categorySelectionId);
});

select 方法的介面:

interface ISelectionManager {
    // ...
    select(selectionId: ISelectionId | ISelectionId[], multiSelect?: boolean): IPromise<ISelectionId[]>;
    // ...
}

select 方法可以接受選取項目的陣列。 這可讓您的視覺效果一次選取數個資料點。 第二個參數 multiSelect 負責多重選取。 如果 multiSelect 為 true,則 Power BI 在套用目前的選取項目時不會清除先前的選取項目狀態。 如果值為 false,則會覆寫先前的選取項目。

使用 multiSelect 的一個典型範例是處理點擊事件上的 Ctrl 按鈕狀態。 當按住 Ctrl 按鈕時,您可以選取多個物件。

button.addEventListener("click", (mouseEvent) => {
    const multiSelect = (mouseEvent as MouseEvent).ctrlKey;
    this.selectionManager.select(seriesSelectionId, multiSelect);
});