Excel アドインでリンクされたエンティティ データ型を作成する

Excel アドインがブックに完全なデータセットを格納せずに外部データを表示する必要がある場合は、リンクされたエンティティ セル値を使用します。 たとえば、1 つのセルに製品、顧客、またはサプライヤーを表示し、詳細についてはリッチ カードを開き、入れ子になったデータは Excel で必要な場合にのみ読み込むことができます。

Excel では、 ストックや Geography などの組み込みのリンクされたデータ型に同じパターンが使用されます。 この記事では、Excel アドインで独自のデータ プロバイダーを構築する方法について説明します。

この記事では、次の方法について学習します。

  • リンクされたエンティティ データ ドメインを登録します。
  • コマンドまたはカスタム関数からリンクされたエンティティ セル値を挿入します。
  • リンクされたエンティティ読み込みサービス関数を実装します。
  • 更新とエラー処理を構成します。

開始する前に、次の関連記事を確認してください。

注:

リンクされたエンティティ セルの値は、Excel on the webではサポートされていません。

リンクされたエンティティ セルの値が何を行うか

リンクされたエンティティ セル値は、ブック セルを外部データ ソースに接続し、結果をエンティティ カードとして表示します。

ワークシートの Seattle Geography のリンクされたデータ型のエンティティ値データ カードのスクリーンショット。

通常のエンティティ値と同様に、リンクされたエンティティ セルの値を数式で参照できます。

=A1 を使用した数式でドット表記を使用するスクリーンショット。Seattle Geography データ型のフィールドを表示するには。

通常のエンティティ値と比較して、リンクされたエンティティ セル値はこれらの利点を提供します。

  • 入れ子になったリンクされたエンティティ セルの値は、ユーザーまたはワークシートが参照するまで取得されません。 これにより、ファイル サイズを減らし、ブックのパフォーマンスを向上させることができます。
  • Excel では、複数のセルが同じ値を効率的に参照できるように、リンクされたエンティティ セルの値をキャッシュします。

重要な用語

この記事全体を通じて、次の用語を使用します。

  • リンクエンティティデータドメイン – リンクエンティティデータドメインは、エンティティが属する全体的なカテゴリを記述します。 たとえば、従業員、組織、自動車などがあります。
  • リンクされたエンティティ セル値 – データ ドメインから作成されたインスタンス。 たとえば、Joe という名前のユーザーの従業員の値です。 カードエンティティ値として表示できます。
  • データ プロバイダー - データ プロバイダーは、1 つ以上の登録済みリンク エンティティ データ ドメインのデータ ソースとして Excel によって認識されます。
  • リンクされたエンティティ読み込みサービス関数 – リンクされているすべてのエンティティ データ ドメインは、そのドメインのデータ ソースとして機能するロード サービス関数を定義します。 リンクされたエンティティ読み込みサービス関数は、ブックのリンクされたエンティティ セル値を取得するための Excel からの要求を処理します。 これを TypeScript または JavaScript カスタム関数として実装します。

リンクされたエンティティ フローのしくみ

次の図は、アドインがリンクされたエンティティ セル値を読み込んでセルに挿入した後の動作を示しています。

アドインがデータ ドメインを登録し、リンクされたエンティティ セル値からプロパティを取得するための Excel からの要求を処理する 5 つの手順を示す図。

  1. Excel はアドインを読み込み、アドインがサポートするすべてのリンクされたエンティティ データ ドメインを登録します。 各登録には、リンクされたエンティティ ロード サービス関数の ID が含まれます。 Excel では、後でこの ID を呼び出して、リンク エンティティ データ ドメインからリンクされたエンティティ セル値のプロパティ値を要求します。 この例では、 Products という名前の 1 つのデータ ドメインが登録されています。
  2. Excel は、リンク されたエンティティ データ ドメイン コレクション内の登録済みの各リンク エンティティ データ ドメインを追跡します。 これにより、Excel は、リンクされたエンティティ セル値にデータが必要な場合に、リンクされたエンティティ読み込みサービス関数を呼び出します。
  3. アドインは、新しいリンクされたエンティティ セル値をワークシートに挿入します。 この例では、製品 Chai の新しいリンクされたエンティティ セル値を作成します。 通常、この手順は、ユーザーがアドインのボタンを選択すると、1 つ以上のリンクされたエンティティ セル値が作成される場合に発生します。 新しいリンクされたエンティティ セル値を作成すると、セルに表示される初期テキスト文字列のみが含まれます。 Excel は、リンクされたエンティティ読み込みサービス関数を呼び出して、残りのプロパティ値を取得します。 アドインは、カスタム関数からリンクされたエンティティ セル値を作成することもできます。
  4. Excel は、手順 1 で登録したリンクされたエンティティ読み込みサービス関数を呼び出します。 これは、新しいリンクされたエンティティ セル値を作成するたびに、またはデータ更新が行われる場合に発生します。 Excel では、リンクされたエンティティ読み込みサービス関数を呼び出して、すべてのプロパティ値を取得します。
  5. リンクされたエンティティ読み込みサービス関数は、Excel によって要求されたリンクエンティティ ID (Excel.LinkedEntityId) の最新のリンクされたエンティティ セル値 (Excel.LinkedEntityCellValue) を返します。 通常、リンクされたエンティティ読み込みサービス関数は、外部データ ソースに対してクエリを実行して値を取得し、リンクされたエンティティ セル値を作成します。 この例では、 製品 IDカテゴリ数量および価格 の値が返されます。

注:

Excel で複数のリンクされたエンティティ セル値が必要な場合、リンクされたエンティティ ID は、リンクされたエンティティ読み込みサービス関数にバッチとして渡されます。 その後、リンクされたエンティティ読み込みサービスは、すべての値のバッチ結果を返します。

以降のセクションでは、この記事で前に定義した用語の詳細について説明します。

データ プロバイダー

アドインはデータ プロバイダーであり、1 つ以上の登録済みデータ ドメインのデータ ソースとして Excel によって認識されます。 アドインは、リンクされたエンティティ セル値のデータを返す 1 つ以上のデータ プロバイダー関数を公開します。 Excel.LinkedEntityDataDomainCreateOptions で、dataProviderを Contoso などのテキスト文字列またはアドインの名前に設定します。 名前はアドイン内で一意である必要があります。

リンクされたエンティティ データ ドメイン

データ プロバイダー (アドイン) は、1 つ以上のデータ ドメインを登録します。 データ ドメインは、エンティティを Excel に記述します。 たとえば、データ プロバイダーは 、製品カテゴリ のデータ ドメインを提供できます。 ドメインを Excel に登録して、これらのドメインと連携してリンクされたエンティティ セル値を取得および表示し、計算を実行できるようにする必要があります。

データ ドメインは、次の属性を Excel に記述します。

  • 関連付けられているデータ プロバイダーの名前。
  • 製品など、一意に識別するドメイン ID。
  • ユーザーの表示名 ( 製品など)。
  • Excel でリンクされたエンティティ セル値が必要な場合に呼び出すリンクエンティティ読み込みサービス関数。
  • 更新の頻度を示す、指定された更新モードと間隔。

リンクされたエンティティ データ ドメインの例として、都市のリンクされたエンティティ セル値を提供する Excel の Geography データ ドメインがあります。

リンクされたエンティティ セルの値

リンクされたエンティティ セル値は、データ ドメインから作成されたインスタンスです。 たとえば、 Geography データ ドメインの Seattle の値です。 通常のエンティティ セル値のようなエンティティ値カード表示されます。

ワークシートの Seattle Geography のリンクされたデータ型のエンティティ値データ カードのスクリーンショット。

リンクされたエンティティ セルの値はデータ ドメインにリンクされているため、更新できます。 入れ子になったリンクされたエンティティ セルの値を実装する場合は、パフォーマンスを向上させるためにファイル サイズを小さくする次の動作に注意してください。

  • 入れ子になったリンクされたエンティティ セルの値は、エンティティ カードを表示するなどして、ユーザーが要求しない限り取得されません。
  • 入れ子になったリンクされたエンティティ セルの値は、ワークシートが数式など、それらを参照しない限り、ワークシートに保存されません。

リンクされたエンティティロードサービス関数

各データ ドメインには、リンクされたエンティティ セル値が必要な場合に Excel が呼び出すことができる関数が必要です。 @linkedEntityLoadServiceでタグ付けされた JavaScript または TypeScript 関数としてサービスを実装します。 最適なパフォーマンスを得るには、1 つのロード サービス関数のみを作成することをお勧めします。 Excel は、リンクされたエンティティ セル値に対するすべての要求をバッチとしてロード サービス関数に送信します。

データ ドメインを使用してデータ プロバイダーを作成する

次のセクションでは、 Contoso のデータ プロバイダーとして機能する Excel アドインの TypeScript コードを記述する方法について説明します。 この例では、アドインには、 製品カテゴリ、サプライヤーの 3 つのデータ ドメインが用意 されています

データ ドメインを登録する

まず、アドインでサポートされている各データ ドメインを登録します。 この例では、データ プロバイダー名は Contoso で、ドメインは ProductsCategoriesSuppliers です

Excel.LinkedEntityDataDomainCreateOptions を使用して、Excel で呼び出す必要があるリンクされたエンティティ読み込みサービス関数など、各ドメインを定義します。 次に、各ドメインを Workbook.linkedEntityDataDomains コレクションに 追加します。 Office アドインを初期化するときにドメインを登録します。

次のコードは、 ProductsCategoriesSuppliers の各データ ドメインを登録します。

Office.onReady(async () => {
    await Excel.run(async (context) => {
        const productsDomain: Excel.LinkedEntityDataDomainCreateOptions = {
            dataProvider: "Contoso",
            id: "products",
            name: "Products",
            // ID of the custom function that is called on demand by Excel to resolve or refresh linked entity cell values of this data domain.
            loadFunctionId: "CONTOSOLOADSERVICE",
            // periodicRefreshInterval is only required when supportedRefreshModes contains "Periodic".
            periodicRefreshInterval: 300,
            // Manual refresh mode is always supported, even if unspecified.
            supportedRefreshModes: [
                Excel.LinkedEntityDataDomainRefreshMode.periodic,
                Excel.LinkedEntityDataDomainRefreshMode.onLoad
            ]
        };

        const categoriesDomain: Excel.LinkedEntityDataDomainCreateOptions = {
            dataProvider: "Contoso",
            id: "categories",
            name: "Categories",
            loadFunctionId: "CONTOSOLOADSERVICE",
            periodicRefreshInterval: 300,
            supportedRefreshModes: [
                Excel.LinkedEntityDataDomainRefreshMode.periodic,
                Excel.LinkedEntityDataDomainRefreshMode.onLoad
            ]
        };

        const suppliersDomain: Excel.LinkedEntityDataDomainCreateOptions = {
            dataProvider: "Contoso",
            id: "suppliers",
            name: "Suppliers",
            loadFunctionId: "CONTOSOLOADSERVICE"
        };
        // Register the data domains by adding them to the collection.
        context.workbook.linkedEntityDataDomains.add(productsDomain);
        context.workbook.linkedEntityDataDomains.add(categoriesDomain);
        context.workbook.linkedEntityDataDomains.add(suppliersDomain);

        await context.sync();
    });
});

リンクされたエンティティ セル値を挿入する

リンクされたエンティティ セルの値をワークシート セルに挿入するには、2 つの方法があります。

  • リボンにコマンド ボタンを作成するか、作業ウィンドウのボタンを作成します。 ユーザーがボタンを選択すると、コードによってリンクされたエンティティ セル値が挿入されます。
  • リンクされたエンティティ セル値を返すカスタム関数を作成します。

次の例では、選択したセルに新しいリンクされたエンティティ セル値を挿入します。 このコードは、リボン コマンドまたは作業ウィンドウのボタンから呼び出すことができます。

次の要件に留意してください。

  • 返すリンクされたエンティティ セル値には、268436224serviceIdを指定する必要があります。 これにより、リンクされたエンティティ セルの値が Excel アドインに関連付けられていることが Excel に通知されます。
  • cultureを指定する必要があります。 Excel は、ブックが別のカルチャで開かれたときに元のカルチャを維持できるように、リンクされたエンティティ読み込みサービス関数にこの値を渡します。
  • text プロパティは、リンクされたエンティティ データ値が更新されている間、セル内のユーザーに表示されます。 これにより、更新が完了している間にユーザーに空白のセルが表示されるのを防ぎます。
async function insertProduct() {
    await Excel.run(async (context) => {
        const productLinkedEntity: Excel.LinkedEntityCellValue = {
            type: Excel.CellValueType.linkedEntity,
            id: {
                entityId: "P1", // Don't use exclamation marks in this value.
                domainId: "products", // Don't use exclamation marks in this value.
                serviceId: 268436224,
                culture: "en-US",
            },
            text: "Chai",
        };
        context.workbook.getActiveCell().valuesAsJson = [[productLinkedEntity]];
        await context.sync();
    });
}

注:

entityIDまたはdomainId値に感嘆符を使用しないでください。

次のコード サンプルは、カスタム関数を使用してリンクされたエンティティ セル値を挿入する方法を示しています。 ユーザーは、任意のセルに =CONTOSO.GETPRODUCTBYID("productid") を入力することで、リンクされたエンティティ セルの値を取得できます。 前のコード サンプルのメモもこのコード サンプルに適用されます。

/**
 * Custom function that shows how to insert a LinkedEntityCellValue.
 * @customfunction
 * @param {string} productID Unique ID of the product.
 * @return {any} LinkedEntityCellValue for the requested product, if found.
 */
function getProductById(productID: string): any {
    const product = getProduct(productID);
    if (product === null) {
        throw new CustomFunctions.Error(CustomFunctions.ErrorCode.notAvailable, "Invalid productID");
    }
    const productLinkedEntity: Excel.LinkedEntityCellValue = {
        type: Excel.CellValueType.linkedEntity,
        id: {
            entityId: product.productID,
            domainId: "products",
            serviceId: 268436224,
            culture: "en-US",
        },
        text: product.productName
    };

    return productLinkedEntity;
}

リンクされたエンティティ読み込みサービス関数を実装する

アドインは、リンクされたエンティティ のセル値にプロパティ値が必要な場合に、Excel からの要求を処理するためのリンクされたエンティティ読み込みサービス関数を提供する必要があります。 関数は、 @linkedEntityLoadService JSDoc タグで識別されます。

次のコード例は、次の方法を示しています。

  • ロード サービス関数によって使用されるヘルパー関数を作成して、 LinkedEntityCellValue オブジェクトを生成します。
  • Excel から製品カテゴリサプライヤーのデータ ドメインに対するデータ要求を処理する関数を作成します。

ヘルパー関数を作成する

次のコード サンプルは、製品のリンクされたエンティティ セル値を作成するヘルパー関数を示しています。 この関数は、特定の製品 ID のリンクされたエンティティを作成するために、 contosoLoadService ロード サービス関数によって呼び出されます。 コードについては、次の点に注意してください。

  • typeid、およびtextプロパティには、前のinsertProductの例と同じ設定が使用されます。
  • これには、Product NameUnit Priceなど、Products データ ドメインに固有の追加のプロパティが含まれます。
  • 製品のカテゴリの遅延入れ子になったリンク エンティティが作成されます。 カテゴリのプロパティは、必要になるまで要求されません。
/** Helper function to create a linked entity from product properties. */
function makeProductLinkedEntity(productID: string): any {
    // Search the product data in the data source for a matching product ID.
    const product = getProduct(productID);
    if (product === null) {
        // Return null if no matching product is found.
        return null;
    }

    const productLinkedEntity: Excel.LinkedEntityCellValue = {
        type: "LinkedEntity",
        text: product.productName,
        id: {
            entityId: product.productID,
            domainId: productsDomainId,
            serviceId: addinDomainServiceId,
            culture: defaultCulture
        },
        properties: {
            "Product ID": {
                type: "String",
                basicValue: product.productID
            },
            "Product Name": {
                type: "String",
                basicValue: product.productName
            },
            "Quantity Per Unit": {
                type: "String",
                basicValue: product.quantityPerUnit
            },
            // Add Unit Price as a formatted number.
            "Unit Price": {
                type: "FormattedNumber",
                basicValue: product.unitPrice,
                numberFormat: "$* #,##0.00"
            },
            Discontinued: {
                type: "Boolean",
                basicValue: product.discontinued
            }
        },
        layouts: {
            compact: {
                icon: "ShoppingBag"
            },
            card: {
                title: { property: "Product Name" },
                sections: [
                    {
                        layout: "List",
                        properties: ["Product ID"]
                    },
                    {
                        layout: "List",
                        title: "Quantity and price",
                        collapsible: true,
                        collapsed: false,
                        properties: ["Quantity Per Unit", "Unit Price"]
                    },
                    {
                        layout: "List",
                        title: "Additional information",
                        collapsed: true,
                        properties: ["Discontinued"]
                    }
                ]
            }
        }
    };

    // Add image property to the linked entity and then add it to the card layout.
    if (product.productImage) {
        productLinkedEntity.properties["Image"] = {
            type: "WebImage",
            address: product.productImage
        };
        productLinkedEntity.layouts.card.mainImage = { property: "Image" };
    }

    // Add a deferred nested linked entity for the product category.
    const category = getCategory(product.categoryID.toString());
    if (category) {
        productLinkedEntity.properties["Category"] = {
            type: "LinkedEntity",
            text: category.categoryName,
            id: {
                entityId: category.categoryID.toString(),
                domainId: categoriesDomainId,
                serviceId: addinDomainServiceId,
                culture: defaultCulture
            }
        };

        // Add nested product category to the card layout.
        productLinkedEntity.layouts.card.sections[0].properties.push("Category");
    }

    // Add a deferred nested linked entity for the supplier.
    const supplier = getSupplier(product.supplierID.toString());
    if (supplier) {
        productLinkedEntity.properties["Supplier"] = {
            type: "LinkedEntity",
            text: supplier.companyName,
            id: {
                entityId: supplier.supplierID.toString(),
                domainId: suppliersDomainId,
                serviceId: addinDomainServiceId,
                culture: defaultCulture
            }
        };

        // Add nested product supplier to the card layout.
        productLinkedEntity.layouts.card.sections[2].properties.push("Supplier");
    }

    return productLinkedEntity;
}

次のコード サンプルは、カテゴリのリンクされたエンティティ セル値を作成するヘルパー関数を示しています。 この関数は、特定のカテゴリ ID のリンクされたエンティティを作成するために、 contosoLoadService ロード サービス関数によって呼び出されます。

/** Helper function to create a linked entity from category properties. */
function makeCategoryLinkedEntity(categoryID: string): any {
    // Search the sample JSON category data for a matching category ID.
    const category = getCategory(categoryID);
    if (category === null) {
        // Return null if no matching category is found.
        return null;
    }

    const categoryLinkedEntity: Excel.LinkedEntityCellValue = {
        type: "LinkedEntity",
        text: category.categoryName,
        id: {
            entityId: category.categoryID,
            domainId: categoriesDomainId,
            serviceId: addinDomainServiceId,
            culture: defaultCulture
        },
        properties: {
            "Category ID": {
                type: "String",
                basicValue: category.categoryID,
                propertyMetadata: {
                    // Exclude the category ID property from the card view and auto-complete.
                    excludeFrom: {
                        cardView: true,
                        autoComplete: true
                    }
                }
            },
            "Category Name": {
                type: "String",
                basicValue: category.categoryName
            },
            Description: {
                type: "String",
                basicValue: category.description
            }
        },
        layouts: {
            compact: {
                icon: "Branch"
            }
        }
    };

    return categoryLinkedEntity;
}

次のコード サンプルは、サプライヤーのリンクされたエンティティ セル値を作成するヘルパー関数を示しています。 この関数は、特定のサプライヤー ID のリンクされたエンティティを作成するために、 contosoLoadService ロード サービス関数によって呼び出されます。

/** Helper function to create linked entity from supplier properties. */
function makeSupplierLinkedEntity(supplierID: string): any {
    // Search the sample JSON category data for a matching supplier ID.
    const supplier = getSupplier(supplierID);
    if (supplier === null) {
        // Return null if no matching supplier is found.
        return null;
    }

    const supplierLinkedEntity: Excel.LinkedEntityCellValue = {
        type: "LinkedEntity",
        text: supplier.companyName,
        id: {
            entityId: supplier.supplierID,
            domainId: suppliersDomainId,
            serviceId: addinDomainServiceId,
            culture: defaultCulture
        },
        properties: {
            "Supplier ID": {
                type: "String",
                basicValue: supplier.supplierID
            },
            "Company Name": {
                type: "String",
                basicValue: supplier.companyName
            },
            "Contact Name": {
                type: "String",
                basicValue: supplier.contactName
            },
            "Contact Title": {
                type: "String",
                basicValue: supplier.contactTitle
            }
        },
        cardLayout: {
            title: { property: "Company Name" },
            sections: [
                {
                    layout: "List",
                    properties: ["Supplier ID", "Company Name", "Contact Name", "Contact Title"]
                }
            ]
        }
    };

    return supplierLinkedEntity;
}

ヘルパー関数を使用してロード サービス関数を実装する

次のコードは、ヘルパー関数を呼び出してリンクされたエンティティ セル値を作成するリンクされたエンティティ読み込みサービス関数を示しています。 コードについては、次の点に注意してください。

  • ロード サービス関数は、受信 LinkedEntityLoadServiceRequest オブジェクトを解析して、ドメイン ID とエンティティ ID を抽出します。 これらの ID は、エンティティが属するデータ ドメインを識別するために使用され、適切なヘルパー関数を呼び出して、リンクされたエンティティ セル値を作成できます。
  • ヘルパー関数は、すべてのプロパティが設定された完全な LinkedEntityCellValue オブジェクトを作成します。
  • ロード サービス関数は、リンクされたエンティティ セル値を含む LinkedEntityLoadServiceResult オブジェクトを、要求された順序と同じ順序で返します。
// Linked entity data domain constants
const productsDomainId = "products";
const categoriesDomainId = "categories";
const suppliersDomainId = "suppliers";

// Linked entity cell value constants
const addinDomainServiceId = 268436224;
const defaultCulture = "en-US";

/**
 * Custom function which acts as the "service" or the data provider for a LinkedEntityDataDomain, that is
 * called on demand by Excel to resolve and refresh LinkedEntityCellValue's of that LinkedEntityDataDomain.
 * @customfunction
 * @linkedEntityLoadService
 * @param {any} request Request to resolve and refresh LinkedEntityCellValue objects.
 * @return {any} Resolved or refreshed LinkedEntityCellValue objects that were requested in the passed-in request.
 */
function contosoLoadService(request: any): any {
    const notAvailableError = new CustomFunctions.Error(CustomFunctions.ErrorCode.notAvailable);
    console.log(`Fetching linked entities from request: ${request} ...`);

    try {
        // Parse the request that was passed-in by Excel.
        const parsedRequest: Excel.LinkedEntityLoadServiceRequest = JSON.parse(request);
        // Initialize result to populate and return to Excel.
        const result: Excel.LinkedEntityLoadServiceResult = { entities: [] };

        // Identify the domainId of the request and call the corresponding function to create
        // linked entity cell values for that linked entity data domain.
        for (const { entityId } of parsedRequest.entities) {
            let linkedEntityResult = null;
            switch (parsedRequest.domainId) {
                case productsDomainId: {
                    linkedEntityResult = makeProductLinkedEntity(entityId);
                    break;
                }
                case categoriesDomainId: {
                    linkedEntityResult = makeCategoryLinkedEntity(entityId);
                    break;
                }
                case suppliersDomainId: {
                    linkedEntityResult = makeSupplierLinkedEntity(entityId);
                    break;
                }
                default:
                    throw notAvailableError;
            }

            if (!linkedEntityResult) {
                // Throw an error to signify to Excel that resolution/refresh of the requested linkedEntityId failed.
                throw notAvailableError;
            }

            result.entities.push(linkedEntityResult);
        }

        return result;
    } catch (error) {
        console.error(error);
        throw notAvailableError;
    }
}

次のコード サンプルには、前のコード サンプルで使用できるサンプル データが含まれています。

/// Sample product data.
const products = [
    {
        productID: "P1",
        productName: "Chai",
        supplierID: "S1",
        categoryID: "C1",
        quantityPerUnit: "10 boxes x 20 bags",
        unitPrice: 18,
        discontinued: false,
        productImage: "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Masala_Chai.JPG/320px-Masala_Chai.JPG"
    }
];

/// Sample product category data.
const categories = [
    {
        categoryID: "C1",
        categoryName: "Beverages",
        description: "Soft drinks, coffees, teas, beers, and ales"
    }];

/// Sample product supplier data.
const suppliers = [
    {
        supplierID: "S1",
        companyName: "Exotic Liquids",
        contactName: "Ema Vargova",
        contactTitle: "Purchasing Manager"
    }];

データ更新オプション

データ ドメインを登録すると、ユーザーは [ Data>Refresh All] を選択するなど、いつでも手動で更新できます。 次の更新モードの 1 つ以上を構成することもできます。

  • manual: ユーザーが更新を選択した場合にのみ、データを更新します。 既定のモード。 手動更新は、更新モードが onLoad または periodicに設定されている場合でも、常に使用できます。
  • onLoad: データ ドメインが登録されたときにデータを更新します。これは通常、アドインの読み込み時に発生します。 その後、ユーザーはデータを手動で更新します。 ブックが開いたときにデータを更新する場合は、ドキュメントを開くときに読み込むようにアドインを構成します。 詳細については、「 ドキュメントが開いたときに Office アドインでコードを実行する」を参照してください。
  • periodic: データ ドメインが登録されたときにデータを更新し、指定した間隔で再び更新します。 たとえば、最小値である 300 秒ごとに更新できます。 Excel は、1 分単位でのみ更新されるため、間隔を最も近い分に丸めます。

次のコード例は、読み込み時に更新するようにデータ ドメインを構成し、5 分ごとに更新を続行する方法を示しています。

const productsDomain: Excel.LinkedEntityDataDomainCreateOptions = {
    dataProvider: domainDataProvider,
    id: "products",
    name: "Products",
    // ID of the custom function that is called on demand by Excel to resolve or refresh linked entity cell values of this data domain.
    loadFunctionId: loadFunctionId,
    // periodicRefreshInterval is only required when supportedRefreshModes contains "Periodic".
    periodicRefreshInterval: 300, // equivalent to 5 minutes.
    // Manual refresh mode is always supported, even if unspecified.
    supportedRefreshModes: [
        Excel.LinkedEntityDataDomainRefreshMode.periodic,
        Excel.LinkedEntityDataDomainRefreshMode.onLoad
    ]
};

次のいずれかの方法を使用して、リンクされたエンティティ データ ドメインに対してプログラムで更新を要求することもできます。

  • LinkedEntityDataDomain.refresh() - リンクされたエンティティ データ ドメインのすべての LinkedEntityCellValue オブジェクトを更新します。
  • LinkedEntityDataDomainCollection.refreshAll() - コレクション内のすべてのリンクされたエンティティ データ ドメインのすべての LinkedEntityCellValue オブジェクトを更新します。

refresh メソッドは、非同期的に行われる更新を要求します。 更新の結果を確認するには、 onRefreshCompleted イベントをリッスンします。 次のコード サンプルは、 onRefreshCompleted イベントをリッスンする例を示しています。

await Excel.run(async (context) => {
    const dataDomains = context.workbook.linkedEntityDataDomains;
    dataDomains.onRefreshCompleted.add(onLinkedEntityDomainRefreshed);

    await context.sync();
});

async function onLinkedEntityDomainRefreshed(eventArgs: Excel.LinkedEntityDataDomainRefreshCompletedEventArgs): Promise<any> {
    console.log(`Linked entity domain refreshed: ${eventArgs.id}`);
    console.log(`Refresh status: ${eventArgs.refreshed}`);
    console.log(`Refresh error: ${eventArgs.errors}`);
    return null;
}

リンクされたエンティティ セルの値を照会する

注:

loadLinkedEntityCellValue API は、ExcelApi 1.21 以降でサポートされています。

リンクされたエンティティのドメイン ID とエンティティ ID がある場合は、 loadLinkedEntityCellValue メソッドを呼び出すことでブックに追加せずに読み込むことができます。 メソッドは非同期であり、 onLinkedEntityCellValueLoaded イベントを介して結果を返します。 loadLinkedEntityCellValueを呼び出す前に、このイベントのイベント ハンドラーを登録する必要があります。 イベント ハンドラー に渡される LinkedEntityCellValueLoadedEventArgs オブジェクトには、読み込まれた LinkedEntityCellValue とエラー情報が含まれています。

次のコード サンプルは、イベント ハンドラーを登録して実装し、 loadLinkedEntityCellValueを呼び出す方法を示しています。

// Linked entity cell value constants
const addinDomainServiceId = 268436224;
const defaultCulture = "en-US";

/**
 * Registers an event handler for the onLinkedEntityCellValueLoaded event.
 * This event occurs when a linked entity cell value has been loaded.
 */
async function registerEvent() {
    await Excel.run(async (context) => {
        const linkedEntityDataDomains = context.workbook.linkedEntityDataDomains;
    
        // Register the event handler
        linkedEntityDataDomains.onLinkedEntityCellValueLoaded.add(handleLinkedEntityLoaded);
    
        await context.sync();
        console.log("Event handler registered successfully. You'll be notified when linked entities are loaded.");
    });
}

/**
 * Event handler that's called when a linked entity cell value is loaded.
 * @param event - The event object containing the loaded LinkedEntityCellValue.
 */
async function handleLinkedEntityLoaded(event: Excel.LinkedEntityCellValueLoadedEventArgs) {
    await Excel.run(async (context) => {
        const loadedLinkedEntityCellValue: Excel.LinkedEntityCellValue = event.linkedEntityCellValue;

        // Queue operations on the loaded entity value here.

        await context.sync();
    });
}

/**
 * Loads a linked entity cell value.
 * @param domainId - The domain specific to the service used for the linked entity cell value.
 * @param entityId - The linked entity cell value's identifier.
 */
async function loadLinkedEntity(domainId: string, entityId: string ) {
  await Excel.run(async (context) => {
    // Specify the linked entity ID to load.
    const linkedEntityId: Excel.LinkedEntityId = {
      entityId: entityId,
      domainId: domainId,
      serviceId: addinDomainServiceId,
      culture: defaultCulture,
    };

    // Load the linked entity cell value.
    context.workbook.linkedEntityDataDomains.loadLinkedEntityCellValue(linkedEntityId);
    await context.sync();

    // The onLinkedEntityCellValueLoaded event occurs once the linked entity cell value is loaded.
  });
}

リンクされたエンティティ読み込みサービスでのエラー処理

Excel がアドインを呼び出してリンクされたエンティティ セル値のデータを取得すると、エラーが発生する可能性があります。 アドインが読み込まれていない場合など、Excel がアドインにまったく接続できない場合は、 #CONNECT! エラーがユーザーに表示されます。

リンクされたエンティティ読み込みサービス関数でエラーが発生した場合は、CustomFunctions.ErrorCode.notAvailableCustomFunctions.Errorをスローする必要があります。 これにより、Excel はユーザーに #CONNECT! を表示します。

次のコードは、リンクされたエンティティ読み込みサービス関数でエラーを処理する方法を示しています。

async function contosoLoadService(request: any): Promise<any> {
    const notAvailableError = new CustomFunctions.Error(CustomFunctions.ErrorCode.notAvailable);
    try {
        // Create and return a new linked entity cell value.
        let linkedEntityResult = ...
      ...
        if (!linkedEntityResult) {
            // Throw an error to signify to Excel that resolution or refresh of the requested linkedEntityId failed.
            throw notAvailableError;
        }
      ...
    } catch (error) {
        console.error(error);
        throw notAvailableError;
    }
}

リンクされたエンティティ読み込みサービスのデバッグ

Office アドインのデバッグの概要に関するページのガイダンスに従って、ほとんどのリンクされたエンティティ アドイン機能をデバッグできます。ただし、リンクされたエンティティ読み込みサービス関数は、共有ランタイムまたは JavaScript 専用ランタイム (カスタム関数ランタイムとも呼ばれます) で実行できます。 JavaScript 専用ランタイムで関数を実装する場合は、 非共有ランタイムでカスタム関数デバッグを使用します

リンクされたエンティティ読み込みサービス関数は、使用するランタイムに関係なく、カスタム関数アーキテクチャを使用します。 ただし、通常のカスタム関数とは大きな違いがあります。

リンクされたエンティティ読み込みサービス関数には、カスタム関数とは次の違いがあります。

  • 数式で使用するためにエンド ユーザーには表示されません。
  • JSDoc タグの @streaming@volatileはサポートされていません。 これらのタグが使用されている場合、ユーザーに #CALC! エラーが表示されます。

リンクされたエンティティ読み込みサービス関数には、カスタム関数と次の類似点があります。

Excel 2019 以前の動作

リンクされたエンティティ セル値をサポートしていない古いバージョンの Excel で、リンクされたエンティティ セル値を含むワークシートを開いた場合、Excel はセル値をエラーとして表示します。 この動作は仕様です。 この動作は、リンクされたエンティティ セル値を挿入または更新するたびに、 basicTypeError に設定し、 basicValue#VALUE! に設定する理由でもあります。 このエラーは、Excel が古いバージョンで使用するフォールバックです。

ベスト プラクティス

  • entityIDまたはdomainId値に感嘆符を使用しないでください。
  • リンクされたエンティティ データ ドメインを Office.onReady 初期化コードに登録すると、アドインが読み込まれるとすぐにリンクされたエンティティ セルの値をユーザーが更新できるようになります。
  • アドインを発行した後は、リンクされたエンティティ データ ドメイン ID を変更しないでください。 同じ論理オブジェクト間で一貫性のある ID を使用すると、パフォーマンスが向上します。
  • 新しいリンクされたエンティティ セル値を作成するときは、常に text プロパティを指定します。 この値は、Excel がデータ プロバイダー関数を呼び出して残りのプロパティ値を取得している間に表示されます。 それ以外の場合、データが取得されるまで空白のセルが表示されます。

関連項目