您的位置:首页 > 其它

IEP项目对Word文件的操作分析

2011-06-22 20:37 309 查看
在NPDS中,需要对word进行操作,由于在网上查的资料都不怎么有用,所以,我决定今天好好分析下孙伟以前在IEP项目中的操作办法,希望能得到一些启示,以下是我对孙伟的代码的分析:
 
项目结构如下:
 
如到导出功能的就主要是划红线的四个部分,下面我们来分别看下里面的内容,首先从IEP.Exportword的内容
 
展开项目后发现里面只有一个文件,找开该文件,首先看到的是USING处,多了几个不常见的东西
 
 
通过在网上查询发现,aspose是一个收费的第三方插件,我估计现在我们用的可能是破解版,因为在网上有破解版提供下载。aspose是一个专业插件开发公司提供的用于制图,写电子邮件,拼写检查,创建条形码,生成各种文档等的组件。Aspose.Words是一款先进的类库,使您可以直接在各个应用程序中执行各种文档处理任务。Aspose.Words支持DOC,OOXML,RTF,HTML,OpenDocument, PDF, XPS, EPUB和其他格式。使用Aspose.Words,您可以生成,更改,转换,渲染和打印文档而不使用Microsoft Word。
 
接下来是定义了三个私有字段
//用于取得模板文件的存放路径
   private static string tmpPath = HttpContext.Current.Server.MapPath("~/" + System.Configuration.ConfigurationManager.AppSettings["WordTmp"]);
 
//用于取得XML文件的存放路径
        private static string xmlPath = HttpContext.Current.Server.MapPath("~/" + System.Configuration.ConfigurationManager.AppSettings["WordData"]);
 
//取得导出文件的文件名称
        private static string outName =HttpContext.Current.Server.UrlDecode(System.Configuration.ConfigurationManager.AppSettings["WordName"]);
tmpPath对应的文件版段如下:
 
 
其中黄色部分就是需要替换的地方,还有个XMLPATH是用来做什么 的呢?让我们来看看片断或许就明白了。
 
我们看到,这个xml的格式如上图,每个words节点下都有,k、t、v、m四个子节点,其中k代表我们需要替换的内容,比较红框中的#*1-9月*#,就代表,凡是在word中出在#*1-9月*#的地方,我们都需要用
  <m>GetValue</m>中的方法来替换,那这个方法又从哪里来呢?  <v>IMonthly</v> 没错,从IMonthly对应的接口来。这个接口的定义就在项目IEP.Iexport中,如下图:
 
看到红色框的部分了吧,在这个文件中只有一个接口的定义
  public interface IMonthly {
        string GetValue();
    }
 
这个接口又在什么地方被实现呢?没错就是IEP.ExportData项目中如下
 
 
文件中的类实现了对于接口的定义
 public class Monthly : IMonthly {
        public string GetValue() {
            string ret = string.Empty;
            //实现
            //ret = "1-9月";
            ret = OutCondition.GetReportCondition("GenerateMonth", "StartMonth") + "-" + OutCondition.GetReportCondition("GenerateMonth", "EndMonth") + "月";
            return ret;
        }
    }
 
好,搞清了数据的具体来源,我们再回过头来看IEP.ExportWord中的代码。第一个方法是导出word报表函数的OutWords()方法,具体代码如下
 /// <summary>
        /// 导出Word报表函数
        /// </summary>        
        public static void OutWords() {
            
            //bool ret = false;
            Document doc = new Document(tmpPath);//说明:这里的Document对象就是aspose插件提供的
 
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlPath);//说明:这里是把xml中的内容加载到XmlDocument 对象中去
 
            XmlNodeList nodeList = xmlDoc.SelectSingleNode("IEP").ChildNodes;//说明:取得xml文件中的所有Words节点集合然后通过遍历就能知道每个需要替换的文字片断,以及这个地方需要从那个接口提供的什么方法来取得值,同时,这个值是什么类型。
            foreach (XmlNode xn in nodeList)//遍历所有Words子节点
            {
                XmlNodeList nod = xn.ChildNodes;
                string k = nod[0].InnerText;//说明:需要替换的关键字
                string t = nod[1].InnerText;//说明:替换类型,1是word文字,2是table,3是图片
                string v = nod[2].InnerText;//说明:从那个接口获取数据
                string m = nod[3].InnerText;//说明:需要调用接口中的那个方法
 
                v = IEP.ExportFactory.FactoryBuild.GetValues(v, m);
                
/*---------------------------------以下为说明-----------------------------
 上面一句代码的作用是获取具体的值,可以看到这个地方使用了IEP.ExportFactory.FactoryBuild.GetValues(v, m)其实,IEP.ExportFactory.FactoryBuild是一个工厂类,根据传入的接口和方法生成来调用IEP.ExportData中的具体方法,以得到返回值。代码如下
 
//下面这句代码是创建一个IMonthly 接口的实例,创建具体内容在IEP.ExportFactory.ExpFactory中创建的具体方法如下
 
 
 
 
 
 private static readonly IEP.IExport.IMonthly monthly = IEP.ExportFactory.ExpFactory.CreateMonthLy();
 /// <summary>
        /// 反射调用方法,取得返回值string
        /// </summary>
        /// <param name="title">实例Type</param>
        /// <param name="methodName">方法名称</param>
        /// <returns></returns>
        private static string GetMethodRetValue(Type title, string methodName)
        {
            string ret = string.Empty;
            try
            {
                if (!String.IsNullOrEmpty(methodName))
                {
                    MethodInfo method = title.GetMethod(methodName);//说明:methodinfo是发现方法并提供对方法的访问,这里的title实现上是一个具体的类,通过GetMthod方法,可以找到指定的方法
                    if (method != null)
                    {
//说明:下面这句的意思是能过Activator.CreateInstance(title) 创建当前titel的具体对象,然后用method.Invoke的方法来调用这个对象的methodname方法。返回的结果是一个object对象
                        object retK = method.Invoke(Activator.CreateInstance(title), null);
 
                        if (retK != null)
                            ret = (string)retK;
                    }
                }
 
            }
            catch (Exception)
            {
                //IEP
            }
            return ret;
        }
 
 
 /// <summary>
        /// 获取对应的工厂实体
        /// </summary>
        /// <param name="key">接口名称</param>
        /// <returns>具体实体</returns>
        public static string GetValues(string key, string methodName)
        {
            string ret = string.Empty;
            switch (key)
            {
               case "IMonthly"://说明:通过传入的key找到接口,并调用GetMethodRetValue方法返回具体内容
                    ret = GetMethodRetValue(monthly.GetType(), methodName);
                    break;
                case "IPicOne":
                    ret = GetMethodRetValue(picone.GetType(), methodName);
                    break;
             default:
                ret = "";
                    break;
            }
 
            return ret;
        }
 
 
---------------------------------------------------------------------------*/
      
          try {
                    switch (t) {
                        case "1"://说明:以下是调用对文字的替换,传入三个参数,此时的V为最终的返回结果。具体代码如后所示
                            RepWords(doc, k, v);
                            break;
                        case "2"://说明:以下是调用对table的替换,传入三个参数,此时的V为最终的返回结果。具体代码如后所示

                            RepTable(doc, k, v);
                            break;
                        case "3"://说明:以下是调用对图片的替换,传入三个参数,此时的V为最终的返回结果。具体代码如后所示

                            k = k.Replace("#*", "");
                            k = k.Replace("*#", "");
                            RepIamges(doc, k, v);
                            break;
                    }
                }
                catch (System.Exception ex) {
                    throw ex;
                }
 
            }
            //return ret;
            doc.Save(outName, SaveFormat.Doc, SaveType.OpenInWord, HttpContext.Current.Response); 
            //说明:doc.save(保存的文件名,保存格式,保存类型,当前请求)
 //保存为doc,并打开
        }
 
 
 
 /// <summary>
        /// 替换Word文档文字
        /// </summary>
        /// <param name="doc">当前上下文doc文档</param>
        /// <param name="key">文档中定义的标记(如:#*2010*#)</param>
        /// <param name="val">替换值</param>
        private static void RepWords(Document doc, string key, string val) {
            //bool ret = false;
            try {               
                doc.Range.Replace(key, val, false, false);//说明:aspose提供的方法具体解释如下图
 

            }
            catch (System.Exception ex) {
                throw ex;
            }
 
            //return ret;
        }
 
 
 
 
 
 
 /// <summary>
        /// 替换word文档表格内容
        /// </summary>
        /// <param name="doc">当前上下文word对象</param>
        /// <param name="key">当前定义表的前缀(如:#*TB1_L1_1*#只在xml原始数据中定义TB1)</param>
        /// <param name="val">表格数据值(キ隔离每行,ぐ隔离每行中的每列数据)</param>
        private static void RepTable(Document doc, string key, string val) {
            //bool ret = false;
            try {
                //doc.Range.Replace(key, val, false, false);
                string curKey = string.Empty;
                string[] lineData = val.Split('キ');
                int lines = lineData.Length;
                //string colData = string.Empty;
                for (int l = 0; l < lines; l++) {
                    string[] colData = lineData[l].Split('ぐ');
                    for (int c = 0; c < colData.Length; c++) {
                        curKey = key + "_L" + (l + 1) + "_" + (c + 1);
                        doc.Range.Replace(curKey, colData[c], false, false);
                    }
                }
 
            }
            catch (System.Exception ex) {
                throw ex;
            }
 
            //return ret;
        }
 
        /// <summary>
        /// 替换Word文档内图片
        /// </summary>
        /// <param name="doc">当前上下文文档</param>
        /// <param name="key">文档中定义的书签(Word书签名)位置</param>
        /// <param name="val">图片相对站点根路径|在word中显示的长度|在word中显示的宽度</param>
        private static void RepIamges(Document doc, string key, string val) {
            //bool ret = false;
            DocumentBuilder builder = new DocumentBuilder(doc);
            try {
                string[] p = val.Split('キ');
 
                string imgPath = HttpContext.Current.Server.MapPath("~/" + p[0]);
                if (!System.IO.File.Exists(imgPath))
                {
                    return;
                }
 
                System.Drawing.Image image = System.Drawing.Image.FromFile(imgPath);
                if (builder.MoveToBookmark(key)) {
                   
                    if (imgPath.ToLower().IndexOf("rpttempimg") > -1)
                    {
                        builder.InsertImage(image, double.Parse(p[1]), double.Parse(p[2]));
                    }
                    else
                    {
                        int width = 460;
                        int height = Convert.ToInt32((Convert.ToDouble(image.Height) / image.Width) * width);
                        builder.InsertImage(image, width, height);
                    }
 
 
                    builder.Writeln();
                }
 
              
 
            }
            catch (System.Exception ex) {
                throw ex;
            }
 
            //return ret;
        }
 
通过以上代码,我们了解到,所有操作都是以aspose为核心,那么这个东西是否也能满足我合并多个word文件的需求呢? 于是我再通过互联网进行查询发现,document这个对象有个apppnedDocument方法。于是我准备建一个测试项目。
 
引入了aspose.words然后增加一个OpreateWord.aspx页面。前台不写任何代码,后台代码如下
 
相信都看的明白,只是需要说明下
 doc2.AppendDocument(DOC,ImportFormatMode.KeepSourceFormatting);
P它的详细定义如下:
 
 
可以看到这个方法要求输入两个参数,一个是需要追加的文档,另一个是IMportFormatMode接口的实现,我们可以使用枚举ImportFormatMode来选择
 
第一个选择是指保持原格式,第二个是指使用目标样式。也就是说我们把文档doc加入到doc2的时候是保留原格式还是使用目标格式。
 
看看运行结果如何?
 
哇,结果出来了,还不错,基本是把两个文件完整合并到一起了。
 
关于aspose的使用,以后再继续讲,尽请关注。
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: