Create a PowerPoint presentation that makes slides corresponding to selected styles in a Microsoft Word document in C#


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 '" +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 parameter title. It saves all text with the "Heading Style" in the headings array. The CreatePpt method (also described shortly) creates the PowerPoint presentation. The following code shows the GetWordData method. The code actually isn't too complicated but error handling makes it a bit longer.
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; } }
// 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,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 Word server running in the background and taking up resources but not doing anything useful. The following code shows the WordFindWordWithStyle method.
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); } }
// 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 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 it found. The example's last interesting piece of code is the CreatePpt method shown below. 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 titel 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 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 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 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's Address property.) The CreatePpt method finishes by saving the new PowerPoint presentation. If the file already exists, the method overwrites it silently. The rest of the method uses finally blocks to close the presentation and PowerPoint server. I've been using this program to make presentations to go with my latest book:

Essential Algorithms: A Practical Approach to Computer Algorithms
ISBN: 978-1-118-61210-1
Paperback
624 pages
August 2013


Comments