2017-05-04 55 views
0

开发一个Word插件,你可以选择一个docx文件,并将它插入到新的空白文档中 - 一个templateHandler类型。Word插件不能在线使用word

每个docx文件都有一个包含多个RTF - contentControrrs的页脚。在加载文档(insertFileFromBase64)之前,代码中有一个thisDocument.body.clear()。

在当地wordclient有加载不同的文档没有问题,但在网上的话,我就得到一个body.clear错误(): 与Word不在线支持的行动

编辑:代码调整为使页眉和页脚与docx-file分离,并使用insertOoxml插入。当你打开插件时,它们会被初始化。 body.clear()不再是一个问题。

在页脚中还有contenControllers的结果。他们可以在网络版本中退出。

编辑:他们现在可见,因为页脚是从docx单独加载。 现在只有一个很大的问题就是 - 当打开插件时,您只能在文档的一行中进行编辑。如果你敲击文字,它会变得不可见。如果您通过从插件加载一个docx文件更改为另一个docx文件,则文本在body中不可见。

我使用office.js 1.1我跑的office365是开发商的evaluationversion:V 1609(建设7369.2127)

这是main.js的内容:

console.log("mains.js is present! "); 

(function() { 
"use strict"; 

// Initialize 
Office.initialize = function (reason) { 
    $(document).ready(function() { 
     app.initialize(); 
     // Use this to check whether the new API is supported in the Word client. 
     if (Office.context.requirements.isSetSupported("WordApi", "1.1")) { 

      console.log('Den här koden är optimerad för Word 2016.'); 

      // Load the doc names from the service into the UI. 
      getDocNames(); 
      console.log("Getting Documents"); 



      addFooter(); 
      //console.log("Adding Footer"); 

      addHeader(); 
      //console.log("Adding Header"); 

      //getDataFromSelection(); 
      //getAllContentControls(); 

      // Setup the event handlers for UI. 
      $('#selectDocument').change(selectDocumentHandler); 
      $('#changeContent').click(contentControlHandler); //TODO:validateFields 
      $('#clearContent').click(clearContent); 
      $('#get-data-from-selection').click(getDataFromSelection); 

     } 
     else { 
      console.log('Du måste använda Word 2016 för att det här ska fungera.'); 
     } 
    }); 
}; 
function clearContent() { 
    $('input[type=text]').val(''); 
} 

     // Function for getting header and footer 

function getHeaderFooter(fileName) { 

    var myOOXMLRequest = new XMLHttpRequest(); 

    var myXML; 

    myOOXMLRequest.open('GET', fileName, false); 

    myOOXMLRequest.send(); 

    if (myOOXMLRequest.status === 200) { 

     myXML = myOOXMLRequest.responseText; 
     return myXML; 
    } 
Office.context.document.setSelectedDataAsync(myXML, { coercionType: 'ooxml' }); 
    //return ""; 
} 

/* Word JS functions */ 

function addHeader() { 
    // Run a batch operation against the Word object model. 
    Word.run(function (context) { 

     // Create a proxy sectionsCollection object. 
     var sections = context.document.sections; 
     //mySections.body.clear(); 
     // Queue a commmand to load the sections. 
     context.load(sections, 'body/style'); 

     return context.sync().then(function() { 

      var header = sections.items[0].getHeader("primary"); 
      //header.clear(); 
      var templateHeader = getHeaderFooter('/xml/simrisHeader.xml'); 

      header.insertOoxml(templateHeader, Word.InsertLocation.replace); 

      return context.sync().then(function() { 
       console.log("Added a header to the first section."); 
      }); 
     }); 
    }) 
     .catch(function (error) { 
      console.log('Error: ' + JSON.stringify(error)); 
      if (error instanceof OfficeExtension.Error) { 
       console.log('Debug info: ' + JSON.stringify(error.debugInfo)); 
      } 
     }); 
} 

function addFooter() { 
    Word.run(function (context) { 

     var sections = context.document.sections; 
     //context.document.clear(); 
     context.load(sections, 'body/style'); 
     return context.sync().then(function() { 

      var footer = sections.items[0].getFooter("primary"); 
      //context.footer.clear(); 

      var templateFooter = getHeaderFooter('/xml/simrisFooter.xml'); 

      footer.insertOoxml(templateFooter, Word.InsertLocation.replace); 
      // var contentControls = footer.contentControls; 
      //getAllContentControls(); 

      return context.sync().then(function() { 
       console.log("Added a footer to the first section."); 
      }); 
     }) 
      .catch(function (error) { 
       console.log('Error: ' + JSON.stringify(error)); 
       if (error instanceof OfficeExtension.Error) { 
        console.log('Debug info: ' + JSON.stringify(error.debugInfo)) 
       } 
      }); 

    }); 
} 

    function displayContents(myBase64) { 
     Word.run(function (context) { 

      var thisDocument = context.document; 

      thisDocument.body.clear(); 

      var mySelection = thisDocument.getSelection(); 

      mySelection.insertFileFromBase64(myBase64, "replace"); 

      return context.sync() 
       .then(function() 
        getAllContentControls();   
       }); 
     }) 
      .catch(function (error) { 
       app.showNotification('Error: ' + JSON.stringify(error)); 
       if (error instanceof OfficeExtension.Error) { 
        app.showNotification('Debug info: ' + JSON.stringify(error.debugInfo)); 
       } 
      }); 
    } 

// Using the Word JS API. Gets all of the content controls that are in the loaded document. 
function getAllContentControls() { 
    Word.run(function (context) { 

     var thisDocument = context.document; 

     var contentControls = thisDocument.contentControls; 

     contentControls.load('tag, title'); 

     return context.sync(contentControls).then(function() { 

      var uniqueFields = removeDuplicateContentControls(contentControls); 

      // Create HTML inputfields based on the content controls. 
      createFields(uniqueFields); 

     }) 
    }) 
     .catch(function (error) { 
      app.showNotification('Error: ' + JSON.stringify(error)); 
      if (error instanceof OfficeExtension.Error) { 
       app.showNotification('Debug info: ' + JSON.stringify(error.debugInfo)); 
      } 
     }); 
} 

// Using the Word JS API. Set the values from the INPUT elements into the associated 
// content controls to make the doc. 
function contentControlHandler() { 

    var entryFields = document.getElementById("entryFields").querySelectorAll("input"); 

    // Loading the contentcontrols again. 
    Word.run(function (context) { 

     // Create a proxy object for the document. 
     var thisDocument = context.document; 

     // Create a proxy object for the contentcontrol collection in the document. 
     var contentControls = thisDocument.contentControls; 

     // Queue a command to load the contentcontrols collection with the tag and title properties. 
     contentControls.load('tag, title'); 

     return context.sync() 
      .then(function() { 

       var i, j; 

       // Map each input element to the associated content control. 
       for (i = 0; i < entryFields.length; i++) { 
        for (j = 0; j < contentControls.items.length; j++) { 
         // Matching content control tag with the tag set as the id on each input element. 
         if (contentControls.items[j].tag === entryFields[i].id && entryFields[i].value != 0) { 
          contentControls.items[j].insertText(entryFields[i].value.trim(), Word.InsertLocation.replace) 
         } 
        } 
       } 
      }) 
      .then(context.sync); 

    }) 
     .catch(function (error) { 
      app.showNotification('Error: ' + JSON.stringify(error)); //console.log 
      if (error instanceof OfficeExtension.Error) { 
       app.showNotification('Debug info: ' + JSON.stringify(error.debugInfo)); //console.log 
      } 
     }); 
} 

// Handles the doc selection in the add-in UI. Results in a call to the service to get 
// a docx file that contains a doc. The doc gets displayed in the Word UI. 
function selectDocumentHandler() { 

    // Form the URL to get the docx file. Need to remove the host information by slicing 
    // off the host information beginning at ?_host_Info. 
    var fileName = this.value; 
    var currentUrl = location.href.slice(0, location.href.indexOf('?')); 
    var getFileUrl = currentUrl + 'getfile?filename=' + fileName; 

    // Call the helper to get the selected file then insert the file into Word. 
    httpGetAsync(getFileUrl, function (response) { 
     displayContents(response); 
    }); 
} 

/* UI functions */ 

function getDocNames() { 

    // Form the URL to get the docx file list. Need to remove the host information by slicing 
    // off the host information beginning at ?_host_Info. 
    var currentUrl = location.href.slice(0, location.href.indexOf('?')); 
    var getFileNamesUrl = currentUrl + 'getfilenames'; 

    // Call the helper to get the file list and then create the dropdown listbox from the results. 
    httpGetAsync(getFileNamesUrl, function (rawResponse) { 

     // Helper that processes the response so that we have an array of filenames. 
     var response = processResponse(rawResponse); 

     // Get a handle on the empty drop down list box. 
     var select = document.getElementById("selectDocument"); 

     // Populate the drop down listbox.  
     for (var i = 0; i < response.length; i++) { 
      var opt = response[i]; 
      var el = document.createElement("option"); 
      el.text = opt; 
      el.value = opt; 
      select.appendChild(el); 
     }; 

     //$(".ms-Dropdown").Dropdown(); 
    }); 
} 

// Creates HTML inputfields 
function createFields(uniqueFields) { 

    // Get the DIV where we will add out INPUT-controls. 
    var entryFields = document.getElementById("entryFields"); 

    // Clear the contents in case it has already been populated with INPUT controls. 
    while (entryFields.hasChildNodes()) { 
     entryFields.removeChild(entryFields.lastChild); 
    } 

    // Create a unique INPUT element for each unique contentcontrol-tag. 
    for (var i = 0; i < uniqueFields.length; i++) { 

     var newLabel = document.createElement("label"); 
     newLabel.appendChild(document.createTextNode(uniqueFields[i].title + ': ')); 
     document.getElementById('entryFields').appendChild(newLabel); 

     var input = document.createElement("input"); 

     newLabel.className = 'ms-label'; 

     input.type = "text"; 

     input.id = uniqueFields[i].tag; 

     input.className = 'ms-TextField-field'; 

     entryFields.appendChild(input); //, input.value 

     entryFields.appendChild(document.createElement("br")); 

    } 

} 

// Get data from AAD and displays user information 
function getDataFromSelection() { 
    var baseEndpoint = 'https://graph.microsoft.com'; 
    var authContext = new AuthenticationContext(config); 

    Office.context.document.getSelectedDataAsync(Office.CoercionType.Text, 
     function (result) { 
      if (result.status === Office.AsyncResultStatus.Succeeded) { 

       authContext.acquireToken(baseEndpoint, function (error, token) { 
        if (error || !token) { 
         app.showNotification("Ingen token: ", "Du får logga in igen."); // + error 
        } 
        var email = authContext._user.userName; 
        var url = "https://graph.microsoft.com/v1.0/" + config.tenant + "https://stackoverflow.com/users/" + email; 

        var html = "<ul>"; 
        $.ajax({ 
         beforeSend: function (request) { 
          request.setRequestHeader("Accept", "application/json"); 
         }, 
         type: "GET", 
         url: url, 
         dataType: "json", 
         headers: { 
          'Authorization': 'Bearer ' + token, 
         }, 
         success: function (response) { 
          console.log('Hämtar inehåll och populerar Kontroller!'); 
          //utilize your callback function 
          postDataToContentControlers(response); 
         } 
        }).done(function (response) { 
         html += getPropertyHtml("Namn", response.displayName); 
         html += getPropertyHtml("Titel", response.jobTitle); 
         html += getPropertyHtml("Avdelning", response.officeLocation); 
         html += getPropertyHtml("Telefon jobb", response.businessPhones); 
         $("#results").html(html); 
        }).fail(function (response) { 
         app.showNotification('Inloggningen slutade att fungera!', 'Du får logga ut och prova att logga in igen'); //response.responseText 
        }); 
       }); 
      } else { 
       app.showNotification('Error:', 'Något gick fel. Du får logga in igen.'); //result.error.message 
      } 
     } 
    ); 
} 

function getPropertyHtml(key, value) { 
    return "<li><strong>" + key + "</strong> : " + value + "</li>"; 
} 

function postDataToContentControlers(response) { 
    // Loading the contentcontrols again. 
    Word.run(function (context) { 

     // Create a proxy object for the document. 
     var thisDocument = context.document; 

     // Create a proxy object for the contentcontrol collection in the document. 
     var contentControls = thisDocument.contentControls; 

     // Queue a command to load the contentcontrols collection with the tag and title properties. 
     contentControls.load('tag, title'); 

     return context.sync() 
      .then(function() { 

       var i, j; 

       var responseArrayKey = Object.keys(response).map(function (v) { return v }); 

       // Map each data element to the associated content control. 
       for (i = 0; i < responseArrayKey.length; i++) { 

        for (j = 0; j < contentControls.items.length; j++) { 

         console.log("responseArrayKey: ", responseArrayKey); 
         // Matching content control tag with the index of each responseArray. 
         if (contentControls.items[j].tag === responseArrayKey[i]) { 

          var responseArrayValue = Object.keys(response).map(function (k) { return response[k] }); 

          contentControls.items[j].insertText(responseArrayValue[i], Word.InsertLocation.replace) 

         } 
        } 
       } 
      }) 
      .then(context.sync); 
    }) 
     .catch(function (error) { 
      app.showNotification('Error: ' + JSON.stringify(error)); //console.log 
      if (error instanceof OfficeExtension.Error) { 
       app.showNotification('Debug info: ' + JSON.stringify(error.debugInfo)); //console.log 
      } 
     }); 
} 

/* Helper functions */ 

// Helper that deduplicates the set of contentcontrols. 
function removeDuplicateContentControls(contentControls) { 

    var i, 
     len = contentControls.items.length, 
     uniqueFields = [], 
     currentContentControl = {}; 

    for (i = 0; i < len; i++) { 
     currentContentControl[contentControls.items[i].tag] = contentControls.items[i].title; 
    } 

    for (i in currentContentControl) { 

     var obj = { 
      tag: i, 
      title: currentContentControl[i] 
     }; 

     uniqueFields.push(obj); 
    } 

    return uniqueFields; 
} 

// Helper for calls to the service. 
function httpGetAsync(theUrl, callback) { 
    var request = new XMLHttpRequest(); 
    request.open("GET", theUrl, false); 
    request.onreadystatechange = function() { 
     if (request.readyState === 4 && request.status === 200) 
      callback(request.responseText); 
    } 
    request.send(null); 
} 

    // Function for getting the HeaderTemplate 

    function getHeaderTemplate(fileName) { 

    var myOOXMLRequest = new XMLHttpRequest(); 

    var myXML; 

    myOOXMLRequest.open('GET', fileName, false); 

    myOOXMLRequest.send(); 

    if (myOOXMLRequest.status === 200) { 

     myXML = myOOXMLRequest.responseText; 
     return myXML; 
    } 

    return ""; 
} 

// Helper that processes file names into an array. 
function processResponse(rawResponse) { 

    // Remove quotes. 
    rawResponse = rawResponse.replace(/"/g, ""); 

    // Remove opening brackets. 
    rawResponse = rawResponse.replace("[", ""); 

    // Remove closing brackets. 
    rawResponse = rawResponse.replace("]", ""); 

    // Return an array of file names. 
    return rawResponse.split(','); 
} 

// Helper function for treating errors 
function errorHandler(error) { 
    showNotification(error, JSON.stringify(error.debugInfo)); 
    console.log("Error: " + error); 
    if (error instanceof OfficeExtension.Error) { 
     console.log("Debug info: " + JSON.stringify(error.debugInfo)); 
    } 
} 

function validateFields() { 
    //TODO: validating fields 
    console.log('Validating fields'); 
} 

})(); 
index.html

内容manifest

获取文档

内容与

的NodeJS处理

希望有人有问题的答案。谢谢=)

+1

你能提供你使用的代码吗? –

+0

我只是在你回答的同一时刻用一些代码编辑它。那么我把更多=) – MangeD66

回答

0

我是来自MS工程师的Word Rich Rich API的工程师。

而我已经在displayContents中试过了你的脚本代码。如上所述,此处的脚本在加载文件(调用insertFileFromBase64)之前将调用body.clear()。 body.clear()操作不允许在单词在线。

我想可能有一些内容在线上不支持字,如字段范围,表行内容控制。

如果您可以提供您正在使用的docx文件,那么我们最好帮助验证此观点并找到根本原因。

+0

[链接](https://mdproduktion.se/codeandstuff/mainTemplate.docx) – MangeD66

+0

Klick上面的链接=) – MangeD66

0

感谢您提供docx文件。

正文中的内容控制之前的“选项卡”不受支持,并且它使内容控件不受支持。因此,body.clear()是不允许的,因为里面有一些不受支持的东西。

我建议你删除本地wordclient中的“Tab”,并在线上传docx文件。 Body.clear()将以这种方式很好地工作。

PS:段落中心可用于帮助对齐内容控制中心。

+0

谢谢@Jiajia它的工作更好,但我实际上已更改模板位 - 仍然在头部下面有contentControl。现在我为页眉和页脚执行InsertOoxml。稍后我会调整代码,以便您可以看到。我现在得到的错误是:调试信息:{“code”:“NotAllowed”,“message”:“Word Online不支持该操作,请查看OfficeExtension.Error.debugInfo获取更多信息。”,“errorLocation”: “Body.insertOoxml。这是当我点击选择另一个docx文件 – MangeD66

+0

当涉及到doc文件。有5个不同的文件,现在只有contentControl在顶部,只是在标题下。当然,在我有imagelogo和文本在顶部之前,它通常不会在Word在线显示,与footer相同,contentConrtols也不会显示或填充inputFields – MangeD66

+0

现在我知道页脚或header.xml:s filecontent导致了这个问题,7个contentControls在页脚或图像和文本在header中,我用开源的Word-Add-in-Get-Set-EditOpen-XML-master插件提取xml信息。也许我需要对这些文件进行一些修改,我怎么知道?我只是将xml文件的内容替换掉了h开发人员应该能够工作的xml示例 - 而且他们这样做。唯一不起作用的是当你想改变我留下的1个contentController中的文本时。当我点击按钮时,它只启动文档的保存处理... – MangeD66