【转载】Word中使用代码高亮插件

Word中使用代码高亮插件

 

一年前我写了一个word2010的代码高亮插件,但当时那个版本有一个问题:在用word发布博客的时候,高亮的代码在博客中的格式乱了。今天有空改了一下这个插件,虽然还是有些瑕疵,但至少发布到博客后,格式不会乱了。主要改进是用ol和li代替了pre,虽然发布到博客后,ol中设置的style和class依然会被改动,但可以在博客中用css来纠正。

下载插件和源代码:SyntaxHighlighter4Word.zip

下面说一下这个插件的用法。

下载文件后,解压,然后双击bin\word2010\Kong.SyntaxHighlighter.Word2010.vsto或bin\word2007\Kong.SyntaxHighlighter.Word2007.vsto,即可完成安装,当然前提是你装了.net framework 4.0。安装成功后的提示如下:

【转载】Word中使用代码高亮插件

安装插件后,会在word中多一个功能区(支持word2007和word2010):

【转载】Word中使用代码高亮插件

点击"设置"按钮,弹出设置界面:

【转载】Word中使用代码高亮插件

这里简化了配置,去掉了前一个版本中的一些设置。

点击"插入代码"按钮,弹出如下界面:

【转载】Word中使用代码高亮插件

可以选择C#、Java、Xml、Javascript等多种语言。

在word效果如下:

【转载】Word中使用代码高亮插件

发布到博客后的效果如下:

  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Windows.Forms;

  6. using Kong.SyntaxHighlighter.Winform;

  7. using Microsoft.Office.Tools.Ribbon;

  8.    

  9. namespace Kong.SyntaxHighlighter.Word

  10. {

  11.     public partial class Ribbon1

  12.     {

  13.         private void Ribbon1_Load(object sender, RibbonUIEventArgs e)

  14.         {

  15.    

  16.         }

  17.     }

  18. }

    我在Word中生成这段代码的时候,用了ol和li,并且设置了ol以及li的style,这样在word中就可以显示边框以及交替行的颜色,同时给ol设了一个class=codeBlock,妄想在发布到博客后可以通过这个样式名codeBlock来自定义自己喜欢的样式。我在word中生成的代码大概是这个样子:

  19. <ol class="codeBlock" ...

    但是word把这段代码发布到博客后,会去除掉这个class,无语。。。

    所以我们在博客中,不得设置所有ol的style,幸好博客园的文章都是在一个id为cnblogs_post_body的div下的,所以我在我博客中加了下面的style:

  20. #cnblogs_post_body ol

  21.  {

  22.      border1px dotted #000066;

  23.      line-height150%;

  24.      word-breakbreak-word;

  25.      font-familyConsolas, Verdana !important;

  26.      border-radius5px;

  27.      width90%;

  28.      background-color#E3E3FF;

  29.      list-style-positionoutside;

  30.      margin-left0px;

  31.  }

  32.  #cnblogs_post_body ol font

  33.  {

  34.      font-size12px !important;

  35.  }

  36.  #cnblogs_post_body ol li

  37.  {

  38.      background-color#fff;

  39.      padding-left5px;

  40.      border-left1px solid #8A8AFF;

  41.      margin-left5px !important;

  42.  }

  43.  #cnblogs_post_body ol li:nth-child(even)

  44.  {

  45.      background-color#f5f5f5;

  46.  }

    补充一下,这段文本是加在这里的:

    【转载】Word中使用代码高亮插件

       

    插件的使用就介绍到这里,下面简单介绍一下插件的实现。

    如何开发office的add in,园子里已经有很多文章了,我就不介绍了,因为我自己也不懂。

    如何实现代码高亮?我用的是Wilco.SyntaxHighlighting,有兴趣的同学可以google一下,我提供的下载包里也有它的源码。

    代码高亮后,如何粘帖到word里?原理就是把代码高亮后的文本以html格式复制到剪贴板里,然后调用word的方法去粘帖:

  47. private void InsertButton_Click(object sender, RibbonControlEventArgs e)

  48. {

  49.     var dialog = new MainForm();

  50.     if (dialog.ShowDialog() == DialogResult.OK)

  51.     {

  52.         dialog.CopyToClipboard();

  53.         Globals.ThisAddIn.Application.Selection.Paste();

  54.     }

  55. }

    以html格式复制到剪贴板的实现,我是从网上找了一段代码来做的,核心逻辑如下:

  56.         public static void CopyToClipboard(string htmlFragment, string title, Uri sourceUrl)

  57.         {

  58.             if (title == null) title = "From Clipboard";

  59.    

  60.             System.Text.StringBuilder sb = new System.Text.StringBuilder();

  61.    

  62.             string header =

  63.     @"Format:HTML Format

  64. Version:1.0

  65. StartHTML:<<<<<<<1

  66. EndHTML:<<<<<<<2

  67. StartFragment:<<<<<<<3

  68. EndFragment:<<<<<<<4

  69. StartSelection:<<<<<<<3

  70. EndSelection:<<<<<<<3

  71. ";

  72.    

  73.             string pre =

  74.     @"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN"">

  75. <HTML><HEAD><TITLE>" + title + @"</TITLE></HEAD><BODY><!--StartFragment-->";

  76.    

  77.             string post = @"<!--EndFragment--></BODY></HTML>";

  78.    

  79.             sb.Append(header);

  80.             if (sourceUrl != null)

  81.             {

  82.                 sb.AppendFormat("SourceURL:{0}", sourceUrl);

  83.             }

  84.             var enc = Encoding.UTF8; //中文乱码问题

  85.             int startHTML = enc.GetByteCount(sb.ToString());

  86.    

  87.             sb.Append(pre);

  88.             int fragmentStart = enc.GetByteCount(sb.ToString());

  89.    

  90.             sb.Append(htmlFragment);

  91.             int fragmentEnd = enc.GetByteCount(sb.ToString());

  92.    

  93.             sb.Append(post);

  94.             int endHTML = enc.GetByteCount(sb.ToString());

  95.    

  96.             // Backpatch offsets

  97.             sb.Replace("<<<<<<<1", To8DigitString(startHTML));

  98.             sb.Replace("<<<<<<<2", To8DigitString(endHTML));

  99.             sb.Replace("<<<<<<<3", To8DigitString(fragmentStart));

  100.             sb.Replace("<<<<<<<4", To8DigitString(fragmentEnd));

  101.    

  102.             Clipboard.Clear();

  103.             var dataObj = new DataObject();

  104.             dataObj.SetData(DataFormats.Html, new MemoryStream(enc.GetBytes(sb.ToString())));

  105.             Clipboard.SetDataObject(dataObj, true);

  106.         }

  107.    

  108.         #endregion // Write to Clipboard

  109.     }

    这个类名叫做HtmlFragment,可以在我提供的下载包里找到。

    另外,我这个插件在生成高亮代码时,可以清除掉代码段首尾的空行,也可以清除掉每一行的公共空格,比如下面的代码:

    【转载】Word中使用代码高亮插件

    在插入后会变成这个样子:

  110. private void Test()

  111. {

  112.     var i = 0;

  113.     //do something

  114. }

    我用了几条正则表达式来实现这个功能,代码如下:

  115. private string GetHtml(string content)

  116. {

  117.     _highlighter.Parser = _htmlParser;

  118.     string html = _highlighter.Parse(content);

  119.     _highlighter.Parser = _parser;

  120.     if (html != null)

  121.     {

  122.         html = html.Replace("\t", " ");

  123.         //清除首尾空行

  124.         html = Regex.Replace(html, @"(^\s*\n)|(\n\s*$)", "", RegexOptions.Singleline);

  125.    

  126.         //清除掉公共的空格

  127.         MatchCollection matches = Regex.Matches(html, @"^ *(?=\S)", RegexOptions.Multiline);

  128.         int len = matches.OfType<Match>().Select(m => m.Value.Length).Min();

  129.         html = Regex.Replace(html, @"^ {" + len + "}", "", RegexOptions.Multiline);

  130.    

  131.         //把每一行开头的空格变成&nbsp;

  132.         html = Regex.Replace(html, @"^ +(?=\S)",

  133.                              new MatchEvaluator(

  134.                                  m => string.Join("", new string[m.Length].Select(s => "&nbsp;"))),

  135.                              RegexOptions.Multiline);

  136.     }

  137.     return html;

  138. }

    有兴趣的同学可以下载源码看一下。

    作者:明年我18 
    出处:http://www.cnblogs.com/default 
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。