HTML content in Word report layout

EvREvR Member Posts: 178
edited 2016-10-23 in NAV Three Tier
Hi all,

I'm trying to add some HTML to a Word layout. The only 2 valid options I have in the XML Mapping Pane are 'Rich Text' and 'Plain Text'.
But both options just display the HTML as the literal HTML string, not as actual rendered HTML.

Has anyone ever done this before?
I find it hard to believe that Word layouts actually have worse support for HTML than RDLC ;)

Gr, Erik

Answers

  • gerdhuebnergerdhuebner Member Posts: 155
    The only possibility, I found for adding dynamic HTML content into a Word layout. is a small extension called Wordlayout+.
    With this AddIn, RichText Content Controls can be used to implement HTML formatting and code, but a kind of converter has to be implemented within a NAV codeunit for each HTML tag to be supported, because there seems to be no native support of HTML within Word. Here you can find an example, which implements bold and italic tags:
    https://massivedynamicsblog.wordpress.com/2016/09/18/wordlayout-and-rich-text-content-controls/
  • PConijnPConijn Member Posts: 31
    Hi @EvR

    I have a similar (but not identical) question (located here) and have not been able to resolve it. If you find an answer to this one, please let me know. It might answer my question as well.
    Kind Regards,

    Peter Conijn

    -The Learning Network-

  • NavNabNavNab Member Posts: 181
    Hello @EvR @PConijn
    Apparently, what you're trying to do can be done by "CustomXMLPart" in C#. I doubt if Microsoft Interop for NAV handles this.
    On another note, here is a blog that explains how you can do it manually. If you're brave enough you can automate all the steps for NAV and share the code with the community :smiley:
  • PConijnPConijn Member Posts: 31
    edited 2018-03-28
    Hi @NavNab,

    I was indeed able to solve my issue using the CustomXml.

    First step was to find the correct XPath in the XML, then use that to search the Data InStream in codeunit 9561 for the Word Blob we stored (which is place in the xml in a Base64 format).

    I could then save that base64 data as the original Word document and use the Word Interop libraries to get the WordDocument.Content range.

    Using that same XPath value, I was then able to replace the correct content control with the content of the WordDocument.Content range of the stored Word blob.

    Caveats
    At this point it does require the report to use the actual table with the stored blob (so no variables), given that the XPath search string is hard-coded to the table and field name (in our case Block_BuildingBlocks), but that does not present practical issues at this point.

    My solution will still need to be tested more thoroughly, such as how it handles a repeating section (and I have a vacation to enjoy), but I will see if I can isolate and share the code.

    But to get @EvR started, I'll post the business end of my code:
    LOCAL FillBuildingBlockInWord(pTxtXPath : Text;pTxtBuildingBlockPath : Text)
    //Loop through the content controls in the printed Word Report layout
    FOREACH netWordContentControl IN netWordContentControls DO BEGIN
    
      //If the XPaths match, find the Word Block and replace the content control with it
      IF netWordContentControl.XMLMapping.XPath = pTxtXPath THEN BEGIN
    
        lNetContentControlRange := netWordContentControl.Range; //The range of the report Word Layout content control
    
        //Open the building block Word document we saved earlier
        lNetBBWordApp := lNetBBWordAppClass.ApplicationClass;
        lNetBBWordApp.Visible := FALSE;
        lNetBBWordDoc := netWordHelper.CallOpen(lNetBBWordApp, pTxtBuildingBlockPath, FALSE, FALSE);
        lNetBBContentRange := lNetBBWordDoc.Content; //Get the contents of the building block document
    
        //Try to add the building block content to the word document; if successful, delete the content contol (while leaving the data)
        IF TryAddContent(lNetContentControlRange, lNetBBContentRange) THEN
          netWordContentControl.Delete(FALSE);
    
        //Close the building block document
        netWordHelper.CallClose(lNetBBWordDoc, FALSE);
        CLEAR(lNetBBWordApp);
      END;
    END; //ForEach
    

    TryAddContent function:
    LOCAL [TryFunction] TryAddContent(VAR pRefNetWordRange : DotNet "Microsoft.Office.Interop.Word.Range" RUNONCLIENT;VAR pRefNetBuildingBlockRange : DotNet "Microsoft.Office.Interop.Word.Range" RUNONCLIENT)
    pRefNetWordRange.InsertXML(pRefNetBuildingBlockRange.XML(FALSE), lNetObject);
    
    Kind Regards,

    Peter Conijn

    -The Learning Network-

Sign In or Register to comment.