暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

VSTO操作PPT

94geek的大嘴 2020-06-16
1218

这次玩一点不一样的.

最近因为做ppt,总发现有2件事情让我很烦恼:

  1. 我有一些PPT模版,但是需要找到一个合适的风格来表达当前的需求比较难,在目前的情况下,我只能一个一个先从文件名过滤,然后再一个一个的打开精确过滤;

  2. 确定了ppt的总体风格后,面对某些特殊的页面,模版中的一些单页PPT没法很好的符合我当前页的需求,我只能再一个一个的去打开PPT模版,去找相对合适的PPT;

所以,我就想是不是有一个插件,能让我导入我自己的ppt模版,然后能给我一个搜索框,能精确的搜索我想要ppt页的这种功能.看上去需求挺简单,但是开始找到的插件没有一个是能满足这个需求.不过还真有几款比较有意思的插件,使用起来怎么说呢,只能说感觉一般.质量也是参差不齐,各有侧重.但是对于资源基本都是内置选用型,没有自己导入型再给与搜索的.

那就自己写一个试试看!

在自己动手的过程中,我发现了VSTO这个不错的小玩意.Microsoft出品,.Net可控.作为一个很久很久没有动手写c#的我,现在的状态真的又一次坐实了"基本不会.Net了".-By the way:这可能是我这辈子的标签了.

我在网上找了好久VSTO的资料,发现网上关于PPT插件的操作大部分都是基于一个叫Spxxx什么的软件,这个软件试用版有限制,收费版好贵啊....算了,对于一个追求自力更生的我来说,原生的操作才是最爱.

到目前,我完成的功能不多,并且都是demo性质的.我现在的想法就是先把demo完成,所有的技术点试验完成后,整合起来即可.

这期先给记录一下,PPT整理阶段的一些远程VSTO操作:

PS:

  1. 所有的代码都是需要引用VSTO相关的dll进行的,对于另外特殊的dll引用,会另行告知

  2. 所有的代码都是demo,未考虑出错,资源释放等问题


  • ppt中的每一页导出成图片.纯VSTO操作就是香!

/*
* 将会根据ppt文件的全名,在ppt所在的文件夹下新建一个img文件夹,将导出的图片全部保存到这个img文件夹.
* 注意:不支持一个文件夹多个ppt,因为操作一个ppt会检查一次img文件夹,存在即删除
* pptPath -> ppt文件的全名
*/
using Microsoft.Office.Interop.PowerPoint;
using Microsoft.Office.Core;

      public static void Export2Img(string pptPath)
      {
          var app = new Application();

var ppt = app.Presentations.Open(pptPath,
                              MsoTriState.msoFalse,
                              MsoTriState.msoFalse,
                              MsoTriState.msoFalse);

          var index = 0;
          Console.WriteLine("ppt -> %s ", pptPath);

          var fullpath = Path.GetDirectoryName(pptPath);
          var imgpath = fullpath + @"\img\";
          if(Directory.Exists(imgpath))
          {
              Directory.Delete(imgpath,true);
          }
          Directory.CreateDirectory(imgpath);
           
          foreach (Slide slid in ppt.Slides)
          {
              ++index;
              //设置图片大小
              // 不需要设置大小即为默认比率的大小,不设置不会失真
              slid.Export(imgpath + string.Format("{0}.png",
                          index.ToString()),
                          "png");
          }

          //释放资源
          ppt.Close();
          app.Quit();
          GC.Collect();
      }
 public static void CleanupText(string pptPath)
      {
          var app = new Application();
          var ppt = app.Presentations.Open(pptPath,
          MsoTriState.msoFalse,
              MsoTriState.msoTrue,
                MsoTriState.msoFalse);


          StringBuilder st = new StringBuilder();
          foreach (Slide slide in ppt.Slides)
          {
              int count = slide.Shapes.Count;
              for (int i = 1; i <= count; i++)
              {
                  if (slide.Shapes[i].HasTextFrame ==
                      MsoTriState.msoTrue)
                  {
                    st.Append(slide.Shapes[i].TextFrame.TextRange.Text);
                    string orgtxt = slide.Shapes[i].TextFrame.TextRange.Text;
                      string txt = orgtxt.Trim().Replace(" ", "");
                      if (0 <= txt.IndexOf("需要被替换的字"))
                      {
                          txt = txt.Replace("需要被替换的字", "替换的字");
                      }
                      slide.Shapes[i].TextFrame.TextRange.Text = txt;

                  }
              }
              Console.WriteLine(st);
          }
          // 这句一定要有,否则所有的更改都不会被保存
          ppt.AcceptAll();

          //释放资源
          ppt.Close();
          app.Quit();
          GC.Collect();
      }
public static void Do(string pptPath)
      {

      var app = new Application();

var ppt = app.Presentations.Open(pptPath,
MsoTriState.msoFalse,
MsoTriState.msoFalse,
MsoTriState.msoFalse);
          var index = 0;
          Console.WriteLine("ppt -> %s ", pptPath);

          var fullpath = Path.GetDirectoryName(pptPath);
          var imgpath = fullpath + @"\paging\";
          if (Directory.Exists(imgpath))
          {
                  Directory.Delete(imgpath, true);
          }
          Directory.CreateDirectory(imgpath);

          foreach (Slide slid in ppt.Slides)
          {
              ++index;
              var newapp = new Application();
              var newppt = newapp.Presentations.Add(MsoTriState.msoFalse);
              PpSaveAsFileType format = PpSaveAsFileType.ppSaveAsDefault;
              newppt.Slides.InsertFromFile(pptPath, 0,index ,index);
              newppt.SaveAs(imgpath + string.Format("{0}.pptx",
              index.ToString()), format,
                  MsoTriState.msoFalse);
              newppt.Close();
              newapp.Quit();

          }
          //释放资源
          ppt.Close();
          app.Quit();
          GC.Collect();
      }
        public static void ModifyAttribut(string filename)
      {

          DSOFile.OleDocumentProperties dso = new DSOFile.OleDocumentProperties();
          dso.Open(filename, false, DSOFile.dsoFileOpenOptions.dsoOptionOpenReadOnlyIfNoWriteAccess);
          dso.SummaryProperties.Title = "标题";
          dso.SummaryProperties.Subject = "Subject";
          dso.SummaryProperties.Company = "Company";
          dso.SummaryProperties.Author = "作者";
          dso.SummaryProperties.Comments = "备注";
          dso.SummaryProperties.Keywords = "关键字";
          dso.Save();
          dso.Close(false);

      }

但是到目前为止,对于ppt的页面检测,我还是有一个没有想明白的.我们都知道ppt的页面有很多的图形组成,这些图形的组成中,我们都是会填写信息的.这些信息有的是一项,有的是两项,或者三项,四项...n项.我想通过程序如何能区分出来这个ppt页面到底是几项表示,这是其一.其二,我如何能分析出这个图形到底是一个什么图形,比如是鱼骨图,齿轮图等等...

写了这些的VSTO的代码,个人感觉VS作为IDE还是全宇宙第一的.另外VSTO确实蛮好玩的,和PPT这种office联合起来确实能做很多的事情,就像我的预想一样,虽然问题很多,但是至少解决方案还是不错.

PS:在运行的过程中,编译的时候一定要选择CPU为x86,而不是AnyCpu,否则运行出错.

  • 最后一个,也是最折腾的一个,"干坏事"专用.更改文件的属性页中指定的属性.这个功能需要DSOFile支持,也是Microsoft出品.官网下载即可.

  • 分割每个PPT页为一个单独的PPT,保存在ppt同目录的split目录下.

  • 替换ppt中所有的文本框中指定的字


文章转载自94geek的大嘴,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论