Showing HTML in PowerPoint

前端 未结 2 501
遇见更好的自我
遇见更好的自我 2020-12-21 17:21

My Goal: Want to show HTML in Slide which I dynamically inject into a Master Presentation.

What I\'ve achieved So far: Converted Ht

相关标签:
2条回答
  • 2020-12-21 17:36

    NOTE: For WINFORMS C#

    OK, I didn't go through the pain description you wrote in your query I believe you have shed a lot of sweat to make it work, here I am sharing the pain free solution(at least it worked for me) and I believe it should work for you too.

    Create a class as below: (I have taken this solution partially from some other SO, sorry don't remember the source)

    using System;
    using System.Text.RegularExpressions;
    using System.Windows.Forms;
    
    
        public class HtmlFragment
        {
            #region Read and decode from clipboard
    
        static public HtmlFragment FromClipboard()
    
        {
    
            string rawClipboardText = Clipboard.GetText(TextDataFormat.Html);
    
            HtmlFragment h = new HtmlFragment(rawClipboardText);
    
            return h;
    
        }
    
    
        /// <summary>
    
        /// Create an HTML fragment decoder around raw HTML text from the clipboard.
    
        /// This text should have the header.
    
        /// </summary>
    
        /// <param name="rawClipboardText">raw html text, with header.</param>
    
        public HtmlFragment(string rawClipboardText)
    
        {
    
            // This decodes CF_HTML, which is an entirely text format using UTF-8.
    
            // Format of this header is described at:
    
            // http://msdn.microsoft.com/library/default.asp?url=/workshop/networking/clipboard/htmlclipboard.asp
    
    
    
            // Note the counters are byte counts in the original string, which may be Ansi. So byte counts
    
            // may be the same as character counts (since sizeof(char) == 1).
    
            // But System.String is unicode, and so byte couns are no longer the same as character counts,
    
            // (since sizeof(wchar) == 2).
    
            int startHMTL = 0;
    
            int endHTML = 0;
    
    
            int startFragment = 0;
    
            int endFragment = 0;
    
    
            Regex r;
    
            Match m;
    
    
            r = new Regex("([a-zA-Z]+):(.+?)[\r\n]",
    
                RegexOptions.IgnoreCase | RegexOptions.Compiled);
    
    
            for (m = r.Match(rawClipboardText); m.Success; m = m.NextMatch())
    
            {
    
                string key = m.Groups[1].Value.ToLower();
    
                string val = m.Groups[2].Value;
    
    
                switch(key)
    
                {
    
                    // Version number of the clipboard. Starting version is 0.9.
    
                    case "version":
    
                        m_version = val;
    
                        break;
    
    
                    // Byte count from the beginning of the clipboard to the start of the context, or -1 if no context
    
                    case "starthtml":
    
                        if (startHMTL != 0) throw new FormatException("StartHtml is already declared");
    
                        startHMTL = int.Parse(val);
    
                        break;
    
    
                    // Byte count from the beginning of the clipboard to the end of the context, or -1 if no context.
    
                    case "endhtml":
    
                        if (startHMTL == 0) throw new FormatException("StartHTML must be declared before endHTML");
    
                        endHTML = int.Parse(val);
    
    
                        m_fullText = rawClipboardText.Substring(startHMTL, endHTML - startHMTL);
    
                        break;
    
    
                    //  Byte count from the beginning of the clipboard to the start of the fragment.
    
                    case "startfragment":
    
                        if (startFragment != 0) throw new FormatException("StartFragment is already declared");
    
                        startFragment = int.Parse(val);
    
                        break;
    
    
                    // Byte count from the beginning of the clipboard to the end of the fragment.
    
                    case "endfragment":
    
                        if (startFragment == 0) throw new FormatException("StartFragment must be declared before EndFragment");
    
                        endFragment = int.Parse(val);
    
                        m_fragment = rawClipboardText.Substring(startFragment, endFragment - startFragment);
    
                        break;
    
    
                    // Optional Source URL, used for resolving relative links.
    
                    case "sourceurl":
    
                        m_source = new System.Uri(val);
    
                        break;
    
                }
    
            } // end for
    
    
            if (m_fullText == null && m_fragment == null)
    
            {
    
                throw new FormatException("No data specified");
    
            }
    
        }
    
    
        // Data. See properties for descriptions.
    
        string m_version;
    
        string m_fullText;
    
        string m_fragment;
    
        System.Uri m_source;
    
    
        /// <summary>
    
        /// Get the Version of the html. Usually something like "1.0".
    
        /// </summary>
    
        public string Version
    
        {
    
            get { return m_version; }
    
        }
    
    
        /// <summary>
    
        /// Get the full text (context) of the HTML fragment. This includes tags that the HTML is enclosed in.
    
        /// May be null if context is not specified.
    
        /// </summary>
    
        public string Context
    
        {
    
            get { return m_fullText; }
    
        }
    
    
        /// <summary>
    
        /// Get just the fragment of HTML text.
    
        /// </summary>
    
        public string Fragment
    
        {
    
            get {  return m_fragment; }
    
        }
    
    
        /// <summary>
    
        /// Get the Source URL of the HTML. May be null if no SourceUrl is specified. This is useful for resolving relative urls.
    
        /// </summary>
    
        public System.Uri SourceUrl
    
        {
    
            get { return m_source; }
    
        }
    
    
        #endregion // Read and decode from clipboard
    
    
        #region Write to Clipboard
    
        // Helper to convert an integer into an 8 digit string.
    
        // String must be 8 characters, because it will be used to replace an 8 character string within a larger string.
    
        static string To8DigitString(int x)
    
        {
    
            return String.Format("{0,8}", x);
    
        }
    
    
        /// <summary>
    
        /// Clears clipboard and copy a HTML fragment to the clipboard. This generates the header.
    
        /// </summary>
    
        /// <param name="htmlFragment">A html fragment.</param>
    
        /// <example>
    
        ///    HtmlFragment.CopyToClipboard("<b>Hello!</b>");
    
        /// </example>
    
        public static void CopyToClipboard(string htmlFragment)
    
        {
    
            CopyToClipboard(htmlFragment, null, null);
    
        }
    
    
        /// <summary>
    
        /// Clears clipboard and copy a HTML fragment to the clipboard, providing additional meta-information.
    
        /// </summary>
    
        /// <param name="htmlFragment">a html fragment</param>
    
        /// <param name="title">optional title of the HTML document (can be null)</param>
    
        /// <param name="sourceUrl">optional Source URL of the HTML document, for resolving relative links (can be null)</param>
    
        public static void CopyToClipboard(string htmlFragment, string title, Uri sourceUrl)
    
        {
    
            if (title == null) title = "From Clipboard"; 
    
    
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
    
    
            // Builds the CF_HTML header. See format specification here:
    
            // http://msdn.microsoft.com/library/default.asp?url=/workshop/networking/clipboard/htmlclipboard.asp
    
    
            // The string contains index references to other spots in the string, so we need placeholders so we can compute the offsets.
    
            // The <<<<<<<_ strings are just placeholders. We’ll backpatch them actual values afterwards.
    
            // The string layout (<<<) also ensures that it can’t appear in the body of the html because the <
    
            // character must be escaped.
    
            string header =
    
    @"Format:HTML Format
    
    Version:1.0
    
    StartHTML:<<<<<<<1
    
    EndHTML:<<<<<<<2
    
    StartFragment:<<<<<<<3
    
    EndFragment:<<<<<<<4
    
    StartSelection:<<<<<<<3
    
    EndSelection:<<<<<<<3
    
    ";
    
    
            string pre =
    
    @"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN"">
    
    <HTML><HEAD><TITLE>" + title + @"</TITLE></HEAD><BODY><!–StartFragment–>";
    
    
            string post = @"<!–EndFragment–></BODY></HTML>";
    
    
            sb.Append(header);
    
            if (sourceUrl != null)
    
            {
    
                sb.AppendFormat("SourceURL:{0}", sourceUrl);
    
            }
    
            int startHTML = sb.Length;
    
    
            sb.Append(pre);
    
            int fragmentStart = sb.Length;
    
    
            sb.Append(htmlFragment);
    
            int fragmentEnd = sb.Length;
    
    
            sb.Append(post);
    
            int endHTML = sb.Length;
    
    
            // Backpatch offsets
    
            sb.Replace("<<<<<<<1", To8DigitString(startHTML));
    
            sb.Replace("<<<<<<<2", To8DigitString(endHTML));
    
            sb.Replace("<<<<<<<3", To8DigitString(fragmentStart));
    
            sb.Replace("<<<<<<<4", To8DigitString(fragmentEnd));
    
    
            // Finally copy to clipboard.
    
            string data = sb.ToString();
    
            Clipboard.Clear();
    
            Clipboard.SetText(data, TextDataFormat.Html);
    
        }
    
    
        #endregion // Write to Clipboard
        }
    

    Usage Explained below :

    using PowerPoint = Microsoft.Office.Interop.PowerPoint;

    var oPowerPoint = new PowerPoint.Application();
    oPowerPoint.Visible = Microsoft.Office.Core.MsoTriState.msoTrue; 
    

    I had a requirement to paste the content on the active slide so I used the below code, your logic could be different depending on your need you can ignore the below code line

     var activeSlide = (PowerPoint.Slide)oPowerPoint.ActiveWindow.View.Slide;
    

    Feed your HTML content to the below method

    HtmlFragment.CopyToClipboard(HTML CONTENT WILL COME HERE);
    

    Below code will paste the HTML into the active slide

    oPowerPoint.ActiveWindow.View.PasteSpecial();
    
    0 讨论(0)
  • 2020-12-21 17:50

    I hope you managed to find something about your issue.

    A bit late, but for future people who might come here.

    This is for the HTML -> PPT part.

    PowerPoint.Presentation presentation;
    presentation = ppApp.Presentations.Open(configuration.PPTTExportedFile, MsoTriState.msoFalse, MsoTriState.msoTrue, MsoTriState.msoTrue);       
    foreach (PowerPoint.Slide slide in presentation.Slides)
    {
        foreach (PowerPoint.Shape shape in slide.Shapes)
        {
            File.WriteAllText(temporaryFilePath, html);
            WebsiteToImage websiteToImage = new WebsiteToImage(temporaryFilePath, @"New picture path");
            websiteToImage.Generate();
            slide.Shapes.AddPicture(@"picture path", MsoTriState.msoTrue, MsoTriState.msoTrue, oldshapeleft, oldshapetop, oldshapewidth, oldshapeheight);
            fileToDelete.Add(temporaryFilePath);
            fileToDelete.Add(@""dont forget to remove tmp files");
        }
    }
    

    Convert webpage to image from ASP.NET

    If you want to do any object manipulation in Word/Excel/PowerPoint, I suggest to work with

    Console.Write("AlternativeText: ");
    Console.WriteLine(shape.AlternativeText);
    

    Because if you save in your original file an AlternativeText in your object, you can access it fast and you can even change the PATH into a simple variable.

    And if you want for example to export a HTML table, do an image from it and change the AlternativeText in order to access it easier later, while giving it an appropriate name that you can access with a 3rd software tool, because PowerPoint doesn't support HTML Tags

    Next to do:

    File.Copy(WordTemplateFile, WordExportedFile, true);
    

    Why you want to change the original? Just make a copy, and keep it as a template which you can change at any moment while creating a new changed version from it.( good for reports )

    AlternativeText is very useful if you plan to work with.

    For your replacement, you might want to use NetOffice/Microsoft Office libraries.

    foreach (NetOffice.WordApi.InlineShape s in docWord.InlineShapes)
    {
        if (s.Type==NetOffice.WordApi.Enums.WdInlineShapeType.wdInlineShapePicture &&  s.AlternativeText.Contains("any pattern you are looking for"))
        {
            <Do your manipulation with image change it>
            s.Range.InsertFile(<insert your new picture for example>);
        }
     }
    

    You loop through all your file and check if something fits your pattern.

    Good luck.

    0 讨论(0)
提交回复
热议问题