Office-JS API with Fetch 从服务器获取数据,替换 Word 中的字段

Office-JS API with Fetch to get data from server, replace fields in Word

我是 Office-JS 的新手 API,但我正在尝试开发一个 POC 来演示通过单击按钮将 Word 文档中的所有字段替换为从中检索到的相应数据的能力一个 API.

所以我开发了一个 API 作为 Azure 函数,我可以调用它,传递一个值,它将 return 字段名称和值作为 JSON 用于匹配传递值的记录。我已经使用 Postman 对此进行了测试。

现在我正在尝试让 Office-JS 工作。我从 VS-2022 模板开始。

我打算采用的方法是,当用户单击按钮时,应用程序将调用 API 并获取记录(数据)字段作为一组 name/value 对。

然后,我想遍历所有的(数据)字段returned,并且对于每个(数据)字段名称,检查文档中是否有(文档)字段姓名;如果是,请将(文档)字段替换为(数据)字段的值。

最后,我意识到以其他方式循环可能更有效(循环遍历文档字段,然后获取(数据)字段的值等),但我认为我可以调整它一旦我开始工作。

我也意识到在一个循环中执行 context.sync() 是不好的做法,但是再次 - 我可以在它工作后清理它。

现在,我的代码报告“错误:InvalidRequestContext:无法在不同的请求上下文中使用该对象。”

我的代码如下:


(function () {
    "use strict";

    var messageBanner;

    // The initialize function must be run each time a new page is loaded.
    Office.initialize = function (reason) {
        $(document).ready(function () {
            // Initialize the notification mechanism and hide it
            var element = document.querySelector('.MessageBanner');
            messageBanner = new components.MessageBanner(element);
            messageBanner.hideBanner();

            // If not using Word 2016, use fallback logic.
            if (!Office.context.requirements.isSetSupported('WordApi', '1.1')) {
                $("#template-description").text("This sample displays the selected text.");
                $('#button-text').text("Display!");
                $('#button-desc').text("Display the selected text");

                $('#highlight-button').click(displaySelectedText);
                return;
            }

            $("#template-description").text("This POC demonstrates template capabilities for NLRB within WORD.");
            $('#button-text').text("Merge Template!");
            $('#button-desc').text("Replaces fields with approprate data.");

            // Add a click event handler for the highlight button.
            $('#highlight-button').click(loadCaseData("08-CA-036441"));
        });
    };


    //CaseNum=08-CA-036441&DataType=1
    function loadCaseData(caseNum) {
        Word.run((context) => {
            const ul = document.getElementById('caseData'),
                url = `[URL to my API]`;

            const createNode = element => { return document.createElement(element); };
            const append = (parent, el) => { return parent.appendChild(el); };

            fetch(url)
                .then(response => { return response.json(); })
                .then(json => {
                    let caseDataResult = json;

                    // Identify fields in the document

                    // Loop through case data for field substitution
                    var range = context.document.body;
                    context.load(range, 'text');
                    var searchResults;
                    for (let fieldName in caseDataResult) {
                        var searchFieldName = "«" + fieldName + "»";
                        let fieldValue = caseDataResult[fieldName];

                        return context.sync()
                            .then(function () {
                                // Queue a search command.
                                searchResults = range.search(searchFieldName, { matchCase: true, matchWholeWord: true });

                                    // Queue a commmand to load the font property of the results.
                                    context.load(searchResults, 'text');
                            })
                            .then(context.sync)
                            .then(function () {
                                var replaceCount = searchResults.items.length;
                                if (replaceCount && replaceCount >= 1) {
                                    for (var replaceItem = 0; replaceItem < replaceCount; replaceItem++) {
                                        searchResults[replaceItem].insertText(fieldValue,
                                            Word.InsertLocation.replace);
                                    }
                                }
                            })
                            .then(context.sync);
                    }
                    return context.sync();
                })
                .catch(errorHandler);
            return context.sync();
        });
    }


    //$$(Helper function for treating errors, $loc_script_taskpane_home_js_comment34$)$$
    function errorHandler(error) {
        // $$(Always be sure to catch any accumulated errors that bubble up from the Word.run execution., $loc_script_taskpane_home_js_comment35$)$$
        showNotification("Error:", error);
        console.log("Error: " + error);
        if (error instanceof OfficeExtension.Error) {
            console.log("Debug info: " + JSON.stringify(error.debugInfo));
        }
    }

    // Helper function for displaying notifications
    function showNotification(header, content) {
        $("#notification-header").text(header);
        $("#notification-body").text(content);
        messageBanner.showBanner();
        messageBanner.toggleExpansion();
    }
})();

样本 JSON return 来自我的数据 API:

{
    "CaseAssgnedDt": "2011-07-22T17:12:19",
    "AsgnUsrExcldFlg": "N",
    "BuId": "0-R9NH",
    "CaseFiledDt": "2006-03-09T00:00:00",
    "InquiryId": "08-CA-036441",
    "ChgofccmReqFlg": "N",
    "DisputeUnitCity": "Cleveland",
    "CaseClasification": "Unclassified",
    "CaseClosedDt": null,
    "Created": "2010-10-07T15:32:29",
    "CreatedBy": "0-1",
    "CrimeSubTypeCd": null,
    "TypeCd": null,
    "DbLastUpd": "2019-10-20T17:17:14.31",
    "DbLastUpdSrc": "ScriptingService_PreInvokeMethod",
    "CaseDescription": null,
    "LastUpd": "2019-10-20T17:17:14",
    "LastUpdBy": "1-CGA",
    "LocalSeqNum": 1,
    "ModificationNum": 11,
    "CaseName": "Sample test case name",
    "ParCaseId": null,
    "PrAgencyId": "No Match Row Id",
    "PrAgentId": "No Match Row Id",
    "PrPostnId": "1-5D2V9F       ",
    "PrPrtnrId": "No Match Row Id",
    "PrRepDnrmFlg": "Y",
    "PrRepManlFlg": "Y",
    "PrRepSysFlg": "Y",
    "PrSgroupId": "No Match Row Id",
    "PrSubjectId": "No Match Row Id",
    "PrSuspctId": "No Match Row Id",
    "IaCategory": "2",
    "RewardExchangeDt": "2010-10-07T11:09:02",
    "RowId": "1-2DCA-1327",
    "CaseNumber": "08-CA-036441",
    "CaseSource": "Visit",
    "DisputeUnitState": "OH",
    "CaseStatus": "Open",
    "CaseSubType": "CA",
    "CaseSubTypeCd": null,
    "TerritoryTypeCd": "08",
    "ThreatLvlCd": "Batch",
    "CaseType": "C",
    "BlockedFlag": null,
    "CaseLongName": "Long sample test case name",
    "XCaseNumCi": null,
    "DojCaseType": null,
    "ElectionTargetDt": null,
    "HearingTargetDt": null,
    "MethodType": null,
    "XNameCi": null,
    "Num8a3Discriminatees": null,
    "Num8b2Discriminatees": null,
    "NumOfEmployees": 146,
    "PostElectionSelfCertification": null,
    "Potential10j": "N",
    "XPrPostnBrdId": "1-4P8HN1",
    "XPrPostnSpvId": "1-1RAQT2",
    "ElectionSelfCertification": null,
    "XTypeCdCi": null,
    "Moved2dh": 1,
    "IdentityVal": 5792070,
    "CdcRecordedFields": null,
    "NxgenTestCase": "N",
    "InquiryChargePetition": null,
    "ChangeCaptureDatetime": "2019-10-20T13:17:15.83",
    "RegionRecommendsPursuing10j": "N",
    "SurrogateKey": 1731295
}

非常感谢您提供的所有帮助,让这项工作顺利进行。

谢谢。

这是 context.sync 嵌套调用的另一个常见症状。首先修复嵌套。此外,当您将过滤逻辑尽可能靠近数据源时,性能会更好。考虑将 Azure 函数设计为接收字段列表并仅发回匹配名称的数据。然后您的客户端代码会大大简化,因为您可以假设返回的每个数据记录都有一个匹配字段。