C#操作word:将rtf中的ole对象通过MathType转换成MathML

最近有一个需求,有一个老的数据库,里面存了2000多道高数题目,同时还有题目的答案、解题过程、用到的知识点,他们都是以trf文本的方式保存。例如:

{\rtf1\adeflang1025\ansi\ansicpg936\uc2\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe2052\themelang1033\themelangfe2052\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
{\f13\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'cb\'ce\'cc\'e5{\*\falt SimSun};}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f38\fbidi \fswiss\fcharset0\fprq0{\*\panose 00000000000000000000}MS Sans Serif{\*\falt Arial};}
{\f39\fbidi \fnil\fcharset134\fprq2{\*\panose 0201060003010101010...

然后保存成rtf后,用word打开就是一个个和数学相关的内容:

C#操作word:将rtf中的ole对象通过MathType转换成MathML_第1张图片这一整个内容都是一个ole对象,嵌入到一个rtf中
处理过数学题目的朋友们都知道,数学公式的显示、保存、输入等是一个比较麻烦的问题,在这个数据库中保存的所有的内容都是一长串的rtf文本,文本保存的是数学公式和题目描述,需要将他们转成MathML,以方便在网页上显示。
在MathML提供的SDK中,有ConvertEquation这个类,这个类的作用就是格式的转换,如下是MathType所提供的输入的格式和输出的格式:
C#操作word:将rtf中的ole对象通过MathType转换成MathML_第2张图片
通过描述能够看出,除了在Word嵌入的对象(Embedded Object),不能将word作为文件直接传入,其他的格式都能直接输入文件,然后输出.text文本。因为数据库中的数据量太大,所以想到通过程序,将word中ole对象复制到剪贴板,然后再调用MathType提供的接口,实现。
具体操作如下:
首先初始化一些用到的对象

        static word.ApplicationClass wordapp = null;
        static word.Document doc = null;
        static word.Selection selection = null;
        static object omissing = System.Reflection.Missing.Value;

打开文档:

 //打开文档
        public static void OpenDocFile(string docName)
        {
            wordapp = new word.ApplicationClass();
            wordapp.Visible = false;

            object docObject = docName;

            doc = wordapp.Documents.Add(ref docObject, ref omissing, ref omissing, ref omissing);
            doc.Activate();
            int ParagraphCount = doc.Content.Paragraphs.Count;
            Console.WriteLine(ParagraphCount);
        }

(建议讲wordapp.Visible设为false,表示打开文档但是不显示出来,这么做会提高些速度,不会造成卡顿)
然后分析word文件,结构非常简单,只有ole对象,对象前面有一连串的空格,所以思路就是首先将光标定义到文档最开始,然后一个字符一个字符的朝下走,当走到不是字符的时候停止,那么下一个字符就是所需要的ole对象,然后执行复制就好。

执行复制的操作在 selection.MoveRight(ref unit, ref count, ref extend);处,需要注意最后一个传入的参数是word.WdMovementType.wdExtend。关于这个参数可以使用Word里面非常强大的录制宏,查看宏作为向导(此处录制宏非常简单,就是移动到ole对象然后执行复制),VBA 宏如下:

Sub 宏()
'
' 宏 宏
'
'
    Selection.MoveRight Unit:=wdCharacter, Count:=6
    Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend
    Selection.Copy
End Sub

可以看见执行复制操作是先设置wdExtend,然后执行Selection.Copy(),复制到剪贴板。
所以代码如下:
向下一个字符复制并且移动:

 //向右移动count个单位并进行复制
        public static void CopyAndMove(object count) 
        {
            object dummy = System.Reflection.Missing.Value;
            object value = 1;
            object unit = word.WdUnits.wdCharacter;
            object extend = word.WdMovementType.wdExtend;
            selection.MoveRight(ref unit, ref count, ref extend);
            selection.Copy();
            selection.MoveRight(ref unit, ref value, ref dummy);
        }

其中selection.MoveRight(ref unit, ref value, ref dummy);是为了将光标移动向下一个单位。
当下一个字符不是空格时,停止:

 public static void CopyOleObject() 
        {
            do
            {
                CopyAndMove(1);
            } while (Paste().Equals(" "));
        }

然后进行复制就可以将OLE对象添加到剪贴板,但是在使用剪贴板时出现一个问题,无法使用Clipboard对象,查阅发现,将main方法设置为单线程模式就可以。
[STAThread]
static void Main(string[] args)
{
OpenDocFile("F:\\doc\\l.rtf");
Console.WriteLine(getCurrentPos());
CopyOleObject();
Console.WriteLine(getCurrentPos());
Console.WriteLine("数据是:"+Paste() + "结束");
Console.ReadLine();
}

至此完成操作,然后将MathType的接口嵌入就可以。
示例:
这里写图片描述


<m:math>
 <m:semantics>
  <m:mrow>
   <m:mi>ym:mi><m:mo>=m:mo><m:mfrac>
    <m:mrow>
     <m:msup>
      <m:mi>am:mi>
      <m:mi>xm:mi>
     m:msup>
     <m:mo>+m:mo><m:msup>
      <m:mi>am:mi>
      <m:mrow>
       <m:mo>m:mo><m:mi>xm:mi>m:mrow>
     m:msup>
     m:mrow>
    <m:mn>2m:mn>
   m:mfrac>
   m:mrow>
  <m:annotation encoding='MathType-MTEF'>MathType@MTEF@5@5@+=
  feaagKart1ev2aqatCvAUfeBSjuyZL2yd9gzLbvyNv2CaerbuLwBLn
  .....

你可能感兴趣的:(C#)