Dynamics CRM 365:通过功能区上的按钮下载 Word 文档模板

问题描述 投票:0回答:7

目前用户必须点击省略号、word模板、最后引用才能下载word模板。

为了方便我们的用户,我们希望在按下功能区上的“打印报价”按钮时下载文档。

这可能吗?如果是这样,我将如何去做呢?我了解如何使用功能区工作台编辑功能区。我需要知道如何使用功能区下载 Word 模板。

如果解决方案是使用ribbon workbench,我可以输入什么命令来下载word模板?

ms-word dynamics-crm dynamics-crm-365 crm-ribbon-workbench document-template
7个回答
4
投票

当您单击模板弹出窗口时,它会通过调用

/AppWebServices/DocumentTemplate.asmx
动态填充,这会返回菜单的 XML。

事件主页网格中 Word 模板的弹出窗口如下所示:

<Menu Id="incident|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.incident.WordTemplates.Menu">
    <MenuSection Id="incident|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.incident.WordTemplates.Menu.CreateTemplates" Title="Create Word Template" Sequence="10" DisplayMode="Menu16">
        <Controls Id="incident|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.incident.WordTemplates.Menu.CreateTemplates.Controls">
            <Button Id="incident|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.incident.WordTemplates.Menu.CreateTemplates.Controls.00000000-0000-0000-0000-000000000000" Command="incident|NoRelationship|HomePageGrid|Mscrm.WordTemplate.CreateWordTemplate.Grid" Sequence="10" ToolTipDescription="Create Word Template" Alt="Create Word Template" LabelText="Create Word Template" />
        </Controls>
    </MenuSection>
    <MenuSection Id="incident|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.incident.WordTemplates.Menu.WordTemplates" Title="Word Templates" Sequence="20" DisplayMode="Menu16">
        <Controls Id="incident|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.incident.WordTemplates.Menu.WordTemplates.Controls">
            <Button Id="incident|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.incident.WordTemplates.Menu.WordTemplates.Controls.9b77c5b0-1033-4741-a01c-afdbdb1c3f22" Command="incident|NoRelationship|HomePageGrid|Mscrm.WordTemplate.TemplatesMenu.Grid" Sequence="10" ToolTipDescription="Case Summary" Alt="Case Summary" LabelText="Case Summary" />
        </Controls>
    </MenuSection>
</Menu>

我暂时没有办法尝试,但我会尝试“复制”最后一个

<Button>

<Button Id="incident|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.incident.WordTemplates.Menu.WordTemplates.Controls.9b77c5b0-1033-4741-a01c-afdbdb1c3f22" Command="incident|NoRelationship|HomePageGrid|Mscrm.WordTemplate.TemplatesMenu.Grid" Sequence="10" ToolTipDescription="Case Summary" Alt="Case Summary" LabelText="Case Summary" />

3
投票

可以仅使用 CRM 支持的功能来执行此操作(当然我确信使用不受支持的 javascript 也可以执行此操作,但我目前没有时间对此进行调查)。实现所需功能应采取的步骤:

  1. 创建 Action 类型的新流程,绑定到您想要的实体 创建一个模板(我在这里建议采取行动的原因是 它可以使用 JavaScript 和 CRM WebAPI 轻松调用)
  2. 在此操作中添加单步 - 调用操作并选择 内置操作“SetWordTemplate”
  3. 设置此操作的属性 - 选择您需要的模板 并将目标动态设置为当前实体(使用 Dynamic 值助手)如果您从未使用过此操作 - 它只是创建 给定的单词模板并将其作为注释添加到您的实体
  4. 现在您需要在按钮内编写逻辑(我假设您 知道如何使用 Ribbon Workbench 或其他工具添加按钮)
  5. 使用 WebAPI 调用您的操作
  6. 查找刚刚为您的实体创建的注释 附件
  7. 下载附件(可以给用户一些提示或者 只需强制下载文件,用户必须保存它)
  8. 删除注释

也许不是一线,但让你在支持区......


1
投票

ExecuteWordMerge = function (wordtemplateid, entitytypecodeint, ids, templatetype, fieldforfilename, filenameoverride) {
        try {
            Xrm.Page.ui.clearFormNotification("worderror");
            var funcpath = Xrm.Page.context.getClientUrl() + "/_grid/print/print_data.aspx";
            if (typeof ids !== "object") {
                var tids = ids;
                ids = new Array();
                ids.push(tids);
            }
            var wordTemplateId = wordtemplateid;//"f1f7b994-543b-e711-8106-c4346bac2908" test data;
            var currentEntityTypeCode = entitytypecodeint;//"10063" test data;
            var templateType = (templatetype || 9940); //9940 is global and 9941 is personal
            var fieldForFileName = (fieldforfilename || "");
            var formdata = "exportType=MergeWordTemplate&selectedRecords=" + encodeURIComponent(JSON.stringify(ids)) +
            "&associatedentitytypecode=" + currentEntityTypeCode + "&TemplateId=" + wordTemplateId + "&TemplateType=" + templateType;
            var req = new XMLHttpRequest();
            req.open("POST", funcpath, true);
            req.responseType = "arraybuffer";
            req.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
            req.setRequestHeader("Accept-Language", "en-US,en;q=0.8");
            req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            req.onreadystatechange = function () {
                if (this.readyState == 4) {/* complete */
                    req.onreadystatechange = null;
                    if (this.status >= 200 && this.status <= 299) {//200 range okay
                        var mimetype = (2 === 2) ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                        var blob = new Blob([req.response], { type: mimetype });
                        var fileNameTemplate = req.getResponseHeader('content-disposition').split('filename=')[1].replace(/'/g, "");
                        var dloadurl = URL.createObjectURL(blob);
                        var filename = (fieldForFileName !== "" && Xrm.Page.getAttribute(fieldForFileName) !== null && Xrm.Page.getAttribute(fieldForFileName).getValue() !== "") ?
                            Xrm.Page.getAttribute(fieldForFileName).getValue() : fileNameTemplate;
                        filename = filenameoverride || filename;
                        //new code, prevent IE errors
                        if (navigator.msSaveOrOpenBlob) {
                            navigator.msSaveOrOpenBlob(blob, filename);
                            return;
                        }
                        else if (window.navigator.msSaveBlob) { // for IE browser
                            window.navigator.msSaveBlob(blob, filename);
                            return;
                        }
                        var a = document.createElement("a");
                        document.body.appendChild(a);
                        a.style = "display: none";
                        a.href = dloadurl;
                        a.download = filename;
                        a.click();
                        URL.revokeObjectURL(dloadurl);
                        //window.location = dloadurl;//we can use just this instead of creating an anchor but we don't get to the name the file
                    }
                    else {
                        Xrm.Page.ui.setFormNotification("An Error occurred generating the word document, please contact support if the issue persists,code: " + this.status, "ERROR", "worderror");
                    }
                }
            };
            req.send(formdata);
        }
        catch (err) {
            Xrm.Page.ui.setFormNotification("An Error occurred generating the word document, please contact support if the issue persists. " + err.message, "ERROR", "worderror");
        }

    }


1
投票

只是为了简化@TeamEASI.com 的回答,这就是我所做的。

  1. 使用 XRMToolBox Ribbon Workbench 2016 将按钮添加到功能区。
  2. 像下面这样创建一个 JS 网络资源。

/*
* Author:      Matthew Hunt
* File:        vsi_DownloadTemplate.js
* Date:        12/20/2017
* Project:     CRM USA
* Description: DownloadTemplate() allows the user to download a document template 
* via a button on the ribbon.
*
* @param entitytypecode: the type code of the entity. In the ribbon workbench set a
* CRM parameter with value PrimaryEntityTypeCode. ex: 1063
*
* @param  templateid: the id for the template you want to download. I had to go to 
* the database to find this and pass it as a string parameter in the ribbon workbench.
* For example: 
* SELECT DocumentTemplateId, Name FROM dbo.DocumentTemplateBase WHERE Name Like '%Quote%';
* returns something like 4AB391A4-D247-E711-80D3-005056914EA2
* Unforunatly, anytime the template is updated, you'll probably have to get the new id.
*
* @param templatetype: the code for the template type. Pass this value in the ribbon 
* workbench as a int param. ex: 9940 is a documenttemplate
* 
* @param filename: the resulting name of the file that will be downloaded to the users 
* computer. Pass this value in the ribbon workbench as a string param. ex: Quote.docx
*
*/
function DownloadTemplate(entitytypecode, templateid, templatetype, filename){
    
    // retrieve the entity id from the current page
    var entityid = new Array();
    entityid.push(Xrm.Page.data.entity.getId());
    
    // try and make a request for the document template
    try{
        
        // clear the page of any previous errors
        Xrm.Page.ui.clearFormNotification("docerror");
        
        // the path that will be used to retrieve the word template
        var funcpath = Xrm.Page.context.getClientUrl() + "/_grid/print/print_data.aspx";
        
        // open the request to create the template
        var req = new XMLHttpRequest();
        req.open("POST", funcpath, true);
        req.responseType = "arraybuffer";
        req.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        req.setRequestHeader("Accept-Language", "en-US,en;q=0.8");
        req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        
        // on completion, run the bellow function
        req.onreadystatechange = function () {
            // request complete
            if (this.readyState == 4) {
                req.onreadystatechange = null;
                 // check if we got back a 200 from the request
            if (this.status >= 200 && this.status <= 299) {
                
                // add the download url to an a tag and then click the a tag 
                // to download the document
                var mimetype = (2 === 2) ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                var blob = new Blob([req.response], { type: mimetype });
                var dloadurl = URL.createObjectURL(blob);
                var a = document.createElement("a");
                
                // if ie, because ie sucks
                if (navigator.msSaveOrOpenBlob) {
                    navigator.msSaveOrOpenBlob(blob, filename);
                    
                // else a browser that doesn't suck
                } else {
                    document.body.appendChild(a);
                    a.style = "display: none";
                    a.href = dloadurl;
                    a.download = filename;
                    a.click();
                    URL.revokeObjectURL(dloadurl);
                }
                
            }
        };
        
        // compile the data to send with the request
        var formdata = "exportType=MergeWordTemplate&selectedRecords=" + encodeURIComponent(JSON.stringify(entityid)) +
        "&associatedentitytypecode=" + entitytypecode + "&TemplateId=" + templateid + "&templatetype=" + templatetype;
        
        // make the request to create the template
        req.send(formdata);
        
    }catch (err) {
        PrintError(err.message);
    }
}

/*
* PrintError() is a helper method to display any errors to the user.
*/
function PrintError(msg){
    Xrm.Page.ui.setFormNotification("An Error occurred generating the word document, please contact support if the issue persists. " + msg, "ERROR", "docerror");
}

IE 修复:.click() 在 IE11 中拒绝访问

  1. 使用 XRMToolBox Ribbon Workbench 2016 使用以下参数创建命令,以在单击按钮时执行 JS。

0
投票

对于新版本的 CRM,此 javascript 代码需要修改以删除不受支持的 API,以及一些其他更改才能与 CHROME 一起使用。

低于我的工作版本,

/*
 * Author:      Matthew Hunt
 * Changes:     Philippe Guarino
 * File:        vsi_DownloadTemplate.js
 * Date:        22/09/2021
 * Project:     CRM USA
 * Description: DownloadTemplate() allows the user to download a document template
 * via a button on the ribbon.
 *
 * @param entitytypecode: the type code of the entity. In the ribbon workbench set a
 * CRM parameter with value PrimaryEntityTypeCode. ex: 1063
 *
 * @param  templateid: the id for the template you want to download. I had to go to
 * the database to find this and pass it as a string parameter in the ribbon workbench.
 * For example:
 * SELECT DocumentTemplateId, Name FROM dbo.DocumentTemplateBase WHERE Name Like '%Quote%';
 * returns something like 4AB391A4-D247-E711-80D3-005056914EA2
 * Unforunatly, anytime the template is updated, you'll probably have to get the new id.
 *
 * @param templatetype: the code for the template type. Pass this value in the ribbon
 * workbench as a int param. ex: 9940 is a documenttemplate
 *
 * @param filename: the resulting name of the file that will be downloaded to the users
 * computer. Pass this value in the ribbon workbench as a string param. ex: Quote.docx
 *
 */

function DownloadTemplate(entitytypecode, templateid, templatetype, filename, formContext)
{
//  var formContext = executionContext.getFormContext(); // get formContext
    // retrieve the entity id from the current page
    var entityid = new Array();
    entityid.push(formContext.data.entity.getId());
    // try and make a request for the document template
    try
    {
        // clear the page of any previous errors
        formContext.ui.clearFormNotification("docerror");
        // the path that will be used to retrieve the word template
        var globalContext = Xrm.Utility.getGlobalContext();
        var funcpath = globalContext.getClientUrl() + "/_grid/print/print_data.aspx";;
        // open the request to create the template
        var req = new XMLHttpRequest();
        req.open("POST", funcpath, true);
        req.responseType = "arraybuffer";
        req.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        req.setRequestHeader("Accept-Language", "en-US,en;q=0.8");
        req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        // on completion, run the bellow function
        req.onreadystatechange = function ()
        {
            // request complete
            if (this.readyState == 4)
            {
                req.onreadystatechange = null;
                // check if we got back a 200 from the request
                if (this.status >= 200 && this.status <= 299)
                {
                    // add the download url to an a tag and then click the a tag 
                    // to download the document
                    var mimetype = (2 === 2) ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                        var blob = new Blob([req.response],
                    {
                        type: mimetype
                    });
                    

                    
                    var dloadurl = (window.URL ? URL : webkitURL).createObjectURL(blob);
                    var a = document.createElement("a");
                    // if ie, because ie sucks
                    if (navigator.msSaveOrOpenBlob)
                    {
                        navigator.msSaveOrOpenBlob(blob, filename);
                        // else a browser that doesn't suck
                    }
                    else
                    {
                        document.body.appendChild(a);
                        a.style = "display: none";
                        a.href = dloadurl;
                        a.download = filename;
                        a.click();
                        URL.revokeObjectURL(dloadurl);
                    }                
                }
            }
        };
        
    // compile the data to send with the request
            var formdata = "exportType=MergeWordTemplate&selectedRecords=" + encodeURIComponent(JSON.stringify(entityid)) +
                "&associatedentitytypecode=" + entitytypecode + "&TemplateId=" + templateid + "&templatetype=" + templatetype;
            // make the request to create the template
            req.send(formdata);
            
    }
    catch (err)
    {
        PrintError(err.message);
    }
}
/*
 * PrintError() is a helper method to display any errors to the user.
 */

function PrintError(msg)
{
      Xrm.Page.ui.setFormNotification("An Error occurred generating the word document, please contact support if the issue persists. " + msg, "ERROR", "docerror");
}

0
投票

对于所有想在 Dyn365 Online 中从 JS 生成 word 文档的人;

在互联网上,您可以找到 Dynamics 的“未记录的 SDK 消息列表”(CLICK)。它不受支持,但现在可以使用了。

由于其内部性质,它们可能会在未来的 CRM 版本中过时,而无需 Microsoft 的任何通知

感谢我准备了一个下载Word模板的示例代码(你只需要将它放在函数中,更改EntityTypeCode,templateid,filename ...等参数)

fetch(Xrm.Utility.getGlobalContext().getClientUrl() + "/api/data/v9.0/ExportWordDocument", {
  method: "POST",
  body: JSON.stringify({
    EntityTypeCode: 1084, //change to valid code
    SelectedRecords: "[\"{6F7651A2-1AE4-ED11-A7C7-000D3ABE768E}\"]", //array of records
    SelectedTemplate: {
        '@odata.type': "Microsoft.Dynamics.CRM.documenttemplate",
        documenttemplateid: "296cb76d-0b59-e811-8126-5065f38bd3c1" //change to valie templateId or retrieve id by template name earlier
    }
  }),
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json",
    "Accept-Language": "*"
  }
}).then((response) => response.json())
  .then((json) => {
        const binaryString = window.atob(json.WordFile);
        const bytes = new Uint8Array(binaryString.length);
        const arrayBuffer = bytes.map((byte, i) => binaryString.charCodeAt(i));
        
        const blob = new Blob([arrayBuffer]);
        const fileName = 'TEST.docx';
        if (navigator.msSaveBlob) {
            // IE 10+
            navigator.msSaveBlob(blob, fileName);
        } else {
            const link = document.createElement('a');
            // Browsers that support HTML5 download attribute
            if (link.download !== undefined) {
                const url = URL.createObjectURL(blob);
                link.setAttribute('href', url);
                link.setAttribute('download', fileName);
                link.style.visibility = 'hidden';
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
            }
        }
    }
);


-1
投票

要获取实体代码,请运行以下查询:

SELECT coalesce(OriginalLocalizedName,name) AS DisplayName, Name AS SchemaName, ObjectTypeCode
FROM EntityLogicalView
ORDER BY ObjectTypeCode

Template ID

SELECT DocumentTemplateId, Name FROM dbo.DocumentTemplateBase
© www.soinside.com 2019 - 2024. All rights reserved.