2013/09/29

C#.Net PowerPoint簡報輸出成圖片

同學最近在趕10/4評鑑,需要將PPT輸出成圖片XDDD
他丟了篇文章『[C#]Export PowerPoint file to photos』給我,學習學習XD

首先,先將MS PowerPoint 12.0 Object Library加入參考



將以下程式碼貼到程式內




using System;
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Office.Core;

namespace PowerPointToPhotos
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private static string type;
        private static string filePath;
        private static string fileName;
        private static string outPath;

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "PowerPoint 97|*.ppt|PowerPoint 2007|*.pptx";

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                type = dialog.FileName.Substring(dialog.FileName.LastIndexOf('.') + 1);
                filePath = dialog.FileName;
                fileName = Path.GetFileNameWithoutExtension(filePath);
                outPath = dialog.FileName.Substring(0, dialog.FileName.LastIndexOf('\\') + 1);

                BackgroundWorker worker = new BackgroundWorker();
                worker.WorkerReportsProgress = true;
                worker.WorkerSupportsCancellation = true;
                worker.DoWork += backgroundWorker_DoWork;
                worker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
                worker.RunWorkerAsync();
            }
        }

        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true)
            {
                MessageBox.Show("以取消");
            }
            else if (e.Error != null)
            {
                MessageBox.Show("error");
            }
            else
            {
                MessageBox.Show("輸出完成");
            }
        }

        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                var pp = new Microsoft.Office.Interop.PowerPoint.Application();
                int index = 0;

                if (type.Equals("ppt"))
                {
                    var ppt = pp.Presentations.Open(filePath, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);

                    foreach (Microsoft.Office.Interop.PowerPoint.Slide s in ppt.Slides)
                    {
                        s.Export(Path.Combine(outPath, string.Format("{0}{1}.jpg", fileName, index)), "jpg", Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                        index++;
                    }

                    ppt.Close();
                }
                else if (type.Equals("pptx"))
                {
                    var ppt = pp.Presentations.Open2007(filePath, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);

                    foreach (Microsoft.Office.Interop.PowerPoint.Slide s in ppt.Slides)
                    {
                        s.Export(Path.Combine(outPath, string.Format("{0}{1}.jpg", fileName, index)), "jpg", Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                        index++;
                    }

                    ppt.Close();
                }
            }
            catch (NullReferenceException ex)
            {
            }
            finally
            {
                type = string.Empty;
                filePath = string.Empty;
                fileName = string.Empty;
                outPath = string.Empty;
            }
        }
    }
}

這隻程式出發點是從點擊按鈕觸發的

private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "PowerPoint 97|*.ppt|PowerPoint 2007|*.pptx";

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                type = dialog.FileName.Substring(dialog.FileName.LastIndexOf('.') + 1);
                filePath = dialog.FileName;
                fileName = Path.GetFileNameWithoutExtension(filePath);
                outPath = dialog.FileName.Substring(0, dialog.FileName.LastIndexOf('\\') + 1);

                BackgroundWorker worker = new BackgroundWorker();
                worker.WorkerReportsProgress = true;
                worker.WorkerSupportsCancellation = true;
                worker.DoWork += backgroundWorker_DoWork;
                worker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
                worker.RunWorkerAsync();
            }
        }

可以看到點擊按鈕時,會開啟檔案選取視窗,並且只能選取2003和2007的PowerPoint檔案
OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "PowerPoint 97|*.ppt|PowerPoint 2007|*.pptx";

如果開啟開始分解參數,type是檔案的副檔名、filePath是取得來源位址、fileName則是來源檔案名稱,最後outPath則是要輸出的路徑檔;在這邊我不用Thread,反而用BackgroundWorker

原因是BackgroundWorker能夠取得目前的進度,完成也會有提示


且是跑在背後的一個執行緒,對這個應用比較適合


if (dialog.ShowDialog() == DialogResult.OK)
            {
                type = dialog.FileName.Substring(dialog.FileName.LastIndexOf('.') + 1);
                filePath = dialog.FileName;
                fileName = Path.GetFileNameWithoutExtension(filePath);
                outPath = dialog.FileName.Substring(0, dialog.FileName.LastIndexOf('\\') + 1);

                BackgroundWorker worker = new BackgroundWorker();
                worker.WorkerReportsProgress = true;
                worker.WorkerSupportsCancellation = true;
                worker.DoWork += backgroundWorker_DoWork;
                worker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
                worker.RunWorkerAsync();
            }

如果是使用WPF的朋友應該會發覺沒辦法取得到目前是否有開啟的狀態,可以參考『OpenFileDialog in WPF』與『WPF Dialogs and DialogResult

BackgroundWorker工作的方法是backgroundWorker_DoWork,所以來解析一下backgroundWorker_DoWork吧

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                var pp = new Microsoft.Office.Interop.PowerPoint.Application();
                int index = 0;

                if (type.Equals("ppt"))
                {
                    var ppt = pp.Presentations.Open(filePath, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);

                    foreach (Microsoft.Office.Interop.PowerPoint.Slide s in ppt.Slides)
                    {
                        s.Export(Path.Combine(outPath, string.Format("{0}{1}.jpg", fileName, index)), "jpg", Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                        index++;
                    }

                    ppt.Close();
                }
                else if (type.Equals("pptx"))
                {
                    var ppt = pp.Presentations.Open2007(filePath, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);

                    foreach (Microsoft.Office.Interop.PowerPoint.Slide s in ppt.Slides)
                    {
                        s.Export(Path.Combine(outPath, string.Format("{0}{1}.jpg", fileName, index)), "jpg", Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                        index++;
                    }

                    ppt.Close();
                }
            }
            catch (NullReferenceException ex)
            {
            }
            finally
            {
                type = string.Empty;
                filePath = string.Empty;
                fileName = string.Empty;
                outPath = string.Empty;
            }
        }

可以看到pp是一個PowerPoint,而index是用來紀錄圖片第幾張,接著判斷2003與2007
if (type.Equals("ppt"))
                {
                    ....
                }
                else if (type.Equals("pptx"))
                {
                  ....
                }

為什麼要判斷2003還是2007呢?原因是開啟的方式有分2003以前以及2007的開啟方式

ppt是指到目前開啟的PowerPoint,並透過Slide去走訪每一張投影片,在透過Export輸出圖片

要更改大小可以將Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height這段改成你想要得大小

var ppt = pp.Presentations.Open(filePath, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);

                    foreach (Microsoft.Office.Interop.PowerPoint.Slide s in ppt.Slides)
                    {
                        s.Export(Path.Combine(outPath, string.Format("{0}{1}.jpg", fileName, index)), "jpg", Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                        index++;
                    }


拿學校講義來測試XDDD


輸出不少檔案XDDD


結果就是這樣啦XD


資料參考:
http://www.dotblogs.com.tw/larrynung/archive/2012/08/29/74356.aspx
http://stackoverflow.com/questions/4316789/how-to-convert-powerpoint-ppt-pptx-to-several-images-of-each-slide
http://msdn.microsoft.com/zh-tw/library/system.componentmodel.backgroundworker.aspx
http://www.c-sharpcorner.com/uploadfile/mahesh/openfiledialog-in-wpf/
http://marlongrech.wordpress.com/2008/05/28/wpf-dialogs-and-dialogresult/