Title: Create a PowerPoint presentation from a Word document in C#
This example shows how you can create a PowerPoint presentation containing slides that correspond to selected styles in a Microsoft Word document.
How to Use It
Enter or select a Word document and a destination PowerPoint presentation. Enter the styles in the Word document that contain the text you want to use for the PowerPoint slides. Fill in a "Title Style" and a "Heading Style" and click Go.
The program makes a PowerPoint presentation. It use the first piece of text in the Word document's "Title Style" style for the PowerPoint presentation's title slide. It uses text in the "Heading Style" to make other slides. It finishes by creating an Agenda slide that contains links to the "Heading Style" slides.
For example, the project includes the Word document Test.docx shown on the right. The first line is in the Heading 1 style. The Section lines are in the Heading 2 style. When you run the program with Title Style = Heading 1 and Heading Style = Heading 2, you get the result shown at the top of this post. The presentation includes a title slide labeled "Title." Next comes the agenda slide that provides links to the other slides, which are labeled "Section 1," "Section 2," and "Section 3."
If there are other elements in the Word document that you want to include in the presentation, you could modify the program to include them. For example, you could add a second level of heading. After using the program to build the basic presentation, you can fill in the details such as adding text, pictures, and other slides.
How it Works
So how does the program work?
First, I used Project > Add Reference command to open the Add Reference dialog. On the .NET tab, I added references to the following:
- Microsoft.Office.Interop.PowerPoint
- Microsoft.Office.Interop.Word
- Office
To make using the libraries easier, the program includes the following using directives.
using Word = Microsoft.Office.Interop.Word;
using Ppt = Microsoft.Office.Interop.PowerPoint;
using Microsoft.Office.Interop.PowerPoint;
using Microsoft.Office.Core;
When you click the Go button, the following code executes to start the conversion process.
// Create the PowerPoint presentation.
private void btnGo_Click(object sender, EventArgs e)
{
try
{
Cursor = Cursors.WaitCursor;
// Get the information we need from the Word file.
string title;
List<string> headings;
GetWordData(txtWordFile.Text, txtTitleStyle.Text,
txtHeadingStyle.Text,
out title, out headings);
if (title == "")
{
MessageBox.Show("Could not find title style '" +
txtTitleStyle.Text + "'");
return;
}
if (headings.Count == 0)
{
MessageBox.Show("Could not find heading style '" +
txtHeadingStyle.Text + "'");
return;
}
// Create the PowerPoint presentation.
CreatePpt(txtPowerPointFile.Text, title, headings);
MessageBox.Show("Done");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
Cursor = Cursors.Default;
}
}
This code mostly calls the GetWordData and CreatePpt methods.
The GetWordData method (described shortly) opens the Word file and finds the appropriate text. It saves the first piece of text with the "Title Style" in its title parameter. It saves all of the text with the "Heading Style" in the headings array.
The CreatePpt method (also described shortly) creates the PowerPoint presentation.
GetWordData
The following code shows the GetWordData method. The code actually isn't too complicated but error handling makes it a bit longish.
// Get the necessary information from the Word document.
private void GetWordData(string file_name,
string title_style, string heading_style,
out string title, out List<string> headings)
{
// Load the Word document.
// Get the Word application object.
Word._Application word_app = new Word.ApplicationClass();
object save_changes = false;
object missing = System.Reflection.Missing.Value;
try
{
// Make Word visible (optional).
word_app.Visible = false;
// Open the file.
object filename = file_name;
object confirm_conversions = false;
object read_only = true;
object add_to_recent_files = false;
object format = 0;
Word._Document word_doc =
word_app.Documents.Open(ref filename,
ref confirm_conversions, ref read_only,
ref add_to_recent_files, ref missing, ref missing,
ref missing, ref missing, ref missing, ref format,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing);
try
{
// Get the title.
object style_name_obj = txtTitleStyle.Text;
WordFindWordWithStyle(word_doc, word_app,
style_name_obj, out title);
Console.WriteLine("Title: " + title);
// Get the headings.
style_name_obj = txtHeadingStyle.Text;
headings = new List<string>();
// Repeat until we find a match before the previous one.
int last_pos = -1;
for (; ; )
{
string heading;
int pos = WordFindWordWithStyle(word_doc, word_app,
style_name_obj, out heading);
if ((pos == 0) || (pos < last_pos)) break;
last_pos = pos;
headings.Add(heading);
Console.WriteLine("Section: " + pos + ": " +
heading);
}
}
catch
{
// Rethrow the exception.
throw;
}
finally
{
// Close the document without prompting.
word_doc.Close(ref save_changes, ref missing,
ref missing);
}
}
catch
{
// Rethrow the exception.
throw;
}
finally
{
word_app.Quit(ref save_changes, ref missing, ref missing);
}
}
The GetWordData method creates a Word application object to act as a Word automation server and uses it to open the Word document. The method then calls WordFindWordWithStyle (described next) to try to find a piece of text with the "Title Style."
The code then enters a loop where it uses WordFindWordWithStyle to try to find text with the "Heading Style." The WordFindWordWithStyle method returns the index of the next occurrence of the text it finds. If it returns 0, it did not find the text so the program breaks out of the loop.
If WordFindWordWithStyle returns an index less than the previous one, that means it has wrapped around to the beginning of the file so it has already returned all of the occurrences of the "Heading Style." In that case, the code also breaks out of the loop.
The GetWordData method then returns, having stored the text it found in its title and headings parameters. The rest of the method's code is error handling.
Notice how the method uses finally blocks to close the Word document if it is open and to close the Word application server if it is open. If you don't do this, you may get odd system effects such as a zombie Word server running in the background and taking up resources but not doing anything useful.
WordFindWordWithStyle
The following code shows the WordFindWordWithStyle method.
// Find an occurrence of a style in a Word document.
// If the style isn't found, set text = "" and return 0.
private int WordFindWordWithStyle(Word._Document word_doc,
Word._Application word_app, object style_name, out string text)
{
word_app.Selection.Find.ClearFormatting();
object style;
try
{
style = word_doc.Styles.get_Item(ref style_name);
}
catch
{
text = "";
return 0;
}
word_app.Selection.Find.set_Style(ref style);
object blank_text = "";
object false_obj = false;
object true_obj = true;
object wrap_obj = Word.WdFindWrap.wdFindContinue;
object missing = System.Reflection.Missing.Value;
word_app.Selection.Find.Execute(ref blank_text,
ref false_obj, ref false_obj, ref false_obj,
ref false_obj, ref false_obj, ref true_obj,
ref wrap_obj, ref true_obj, ref missing,
ref missing, ref false_obj, ref false_obj,
ref false_obj, ref false_obj);
text = word_app.Selection.Text.Trim();
return word_app.Selection.Start;
}
This method clears any formatting in the Word Selection object so it can begin a fresh search. It then uses the Word document object's Styles collection to get the object representing the desired style. If there is an error, that means the desired style doesn't exist in the Word document. In that case, the method returns 0 to indicate it did not find any text.
If the method did find the desired style, it sets the Selection.Find object's style to the style of the object that it found. The code creates some variables to represent search parameters and then calls the Selection.Find object's Execute method to find the next occurrence of the desired style.
The most interesting parameter at this point is Word.WdFindWrap.wdFindContinue. This value makes Selection.Find move from one match to the next, wrapping around to the beginning of the file when it reaches the end. Other choices for this parameter are wdFindAsk (but you don't want to ask the user whether to continue) and wdFindStop (which only finds one occurrence and doesn't move to the next).
After it has found some text, the method trims it and saves it in the text output parameter. Finally the method returns the index of the text that it found.
CreatePpt
The example's last interesting piece of code is the CreatePpt method shown in the following code. Like the GetWordData method, it is complicated slightly by error handling code.
// Create the PowerPoint presentation.
private void CreatePpt(string file_name,
string title, List<string> headings)
{
// Get the PowerPoint application object.
Ppt._Application ppt_app = new Ppt.ApplicationClass();
try
{
// Create the presentation.
Ppt.Presentation ppt_pres =
ppt_app.Presentations.Add(MsoTriState.msoFalse);
try
{
// Create the title slide.
Ppt.Slide title_slide =
ppt_pres.Slides.Add(1,
PpSlideLayout.ppLayoutTitleOnly);
title_slide.Shapes[1].TextFrame.TextRange.Text = title;
// Keep track of the other slides so
// we can make an agenda.
string agenda = "";
// Create other slides.
int slide_num = 1;
foreach (string heading in headings)
{
slide_num++;
Ppt.Slide heading_slide = ppt_pres.Slides.Add(
slide_num, PpSlideLayout.ppLayoutText);
heading_slide.Shapes[1].TextFrame.TextRange.Text =
heading;
agenda += '\n' + heading;
}
// Create the agenda.
if (agenda.Length > 0)
{
// Remove the initial \n.
agenda = agenda.Substring(1);
// Create the agenda slide.
Ppt.Slide agenda_slide = ppt_pres.Slides.Add(
2, PpSlideLayout.ppLayoutText);
agenda_slide.Shapes[1].TextFrame.TextRange.Text =
"Agenda";
agenda_slide.Shapes[2].TextFrame.TextRange.Text =
agenda;
// Make each line in the agenda text be a hyperlink
// to the corresponding section page.
for (int i = 1; i < slide_num; i++)
{
// Page number (the current slide number) is
// the section number plus 2 (for the title
// slide and the agenda).
int page_number = i + 2;
// Set the SubAddress.
// (Address gives the file or URL. We don't
// use Address so the destination is within
// this document. SubAddress gives the
// location within the file.
// In this case, that's the slide number.)
agenda_slide.Shapes[2].TextFrame.TextRange.
Lines(i, i).ActionSettings[
PpMouseActivation.ppMouseClick].
Hyperlink.SubAddress =
page_number.ToString();
}
}
// Save the presentation.
ppt_pres.SaveAs(file_name,
PpSaveAsFileType.ppSaveAsPresentation,
MsoTriState.msoFalse);
}
catch
{
// Rethrow the exception.
throw;
}
finally
{
// Close.
ppt_pres.Close();
}
}
catch
{
// Rethrow the exception.
throw;
}
finally
{
ppt_app.Quit();
}
}
This method starts by creating a PowerPoint application server object. It then uses the Presentations.Add method to create a new presentation. The parameter to that method indicates whether the new presentation should be displayed in a visible window.
Next, the method calls the presentation object's Slides.Add method to create the title slide. As its name implies, the ppLayoutTitleOnly type of slide contains only a title text area. The code sets the text for the first TextFrame object on the slide to the title text taken from the Word file.
The method then loops through the heading values the program got from the Word file. For each value, the code creates a new slide. This slide has type ppLayoutText, which gives it a title text box and a larger detail text area beneath. The method sets the slide's first shape's text (in the title text area) to the heading taken from the Word file.
The code also adds the new slide's heading to the growing string agenda. After the loop finishes, the string agenda contains a list of the slides' titles.
After the method has built all of the detail slides, it inserts an agenda slide after the main title slide. It sets the slide's title to "Agenda" and sets the text beneath to the agenda string.
Next, the code loops from 1 to the number of detail slides that it created earlier. For each of those slides, the method gets the corresponding line in the agenda slide's detail text and gets that line's ActionSettings value. It sets the ppMouseClick action setting's Hyperlink.SubAddress property to the corresponding page number. The result is that the line in the agenda slide is now a hyperlink to the corresponding page number within this document. (If you wanted a hyperlink to a location in another document, you could set the Hyperlink object's Address property.)
The CreatePpt method finishes by saving the new PowerPoint presentation. If the file already exists, the method overwrites it without warning.
The rest of the method uses finally blocks to close the presentation and PowerPoint server.
I used this program to make presentations to go with my book Essential Algorithms: A Practical Approach to Computer Algorithms.
The presentations are intended for instructors. After using the program to build the basic presentation, I filled in the details by adding text, pictures, other slides, and some notes.
Download the example to experiment with it and to see additional details.
|