using System; using System.Collections.Generic; using Microsoft.Office.Core; using System.IO; using PowerPoint = Microsoft.Office.Interop.PowerPoint; namespace RobvanderWoude { class PowerPoint2Any { static string progver = "1.00"; // Generate a list of accepted file types static Dictionary acceptedtypes = ListWorkingFormats( ); static int Main( string[] args ) { #region Initialize Variables bool overwrite = false; string inputfilespec = null; string outputfilespec = null; string inputfolder; string outputfolder; string inputfile; string outputfile; string inputfilename; string outputfilename; string inputfileext; string outputfileext = null; int inputformat = -1; int outputformat = -1; #endregion Initialize Variables #region Command Line Parsing if ( args.Length == 0 || ( args.Length == 1 && args[0].ToUpper( ) != "/T" ) ) { return ShowHelp( ); } foreach ( string arg in args ) { if ( arg[0] == '/' ) { if ( arg.ToString( ).ToUpper( ) == "/O" ) { if ( overwrite ) { return ShowHelp( "Duplicate command line switch /O" ); } overwrite = true; break; } else if ( arg.ToString( ).ToUpper( ) == "/T" ) { ListFormats( ); return 0; } else if ( arg.Length > 3 && arg.Substring( 0, 3 ).ToUpper( ) == "/T:" ) { if ( outputformat != -1 ) { return ShowHelp( "Duplicate command line switch /T" ); } outputformat = GetFormat( arg.Substring( 3 ) ); if ( outputformat == -1 ) { return ShowHelp( "Output file type not recognized, use /T to list all available types" ); } } else { return ShowHelp( "Invalid command line switch {0}", arg ); } } else { if ( String.IsNullOrEmpty( inputfilespec ) ) { inputfilespec = arg; } else if ( String.IsNullOrEmpty( outputfilespec ) ) { outputfilespec = arg; } else { return ShowHelp( "Invalid command line argument \"{0}\"", arg ); } } } #endregion Command Line Parsing #region Command Line Validation // Validate input filespec if ( String.IsNullOrEmpty( inputfilespec ) ) { return ShowHelp( "Please specify an input file" ); } switch ( ValidateFilespec( inputfilespec ) ) { case -1: if ( inputfilespec.IndexOf( '*' ) == -1 ) { return ShowHelp( "Parent folder of input file not found" ); } else { return ShowHelp( "Parent folder of input files not found" ); } case 0: if ( inputfilespec.IndexOf( '*' ) == -1 ) { return ShowHelp( "Input file not found" ); } else { return ShowHelp( "No matching input files found" ); } case 1: break; default: if ( !String.IsNullOrEmpty( outputfilespec ) && Path.GetFileNameWithoutExtension( outputfilespec ) != "*" ) { return ShowHelp( "When using wildcards in the input file names,\n\tyou must use wildcard \"*\" for the output file names, if specified" ); } break; } inputfolder = Directory.GetParent( inputfilespec ).FullName; inputfile = Path.GetFileName( inputfilespec ); inputfilename = Path.GetFileNameWithoutExtension( inputfilespec ); inputfileext = Path.GetExtension( inputfilespec ); inputformat = GetFormatByExtension( inputfilespec ); if ( inputformat == -1 ) { return ShowHelp( "Unrecognized input file type" ); } // Validate or build output filespec if ( String.IsNullOrEmpty( outputfilespec ) ) { if ( outputformat == -1 ) { return ShowHelp( "Please specify output file(s) and/or valid output file type" ); } outputfolder = inputfolder; outputfile = "*"; outputfilename = "*"; outputfilespec = Path.Combine( outputfolder, outputfile ); // Extension will be default extension based on file type } else { outputfile = Path.GetFileName( outputfilespec ); outputfilename = Path.GetFileNameWithoutExtension( outputfilespec ); outputfileext = Path.GetExtension( outputfilespec ); if ( outputfilespec.IndexOf( '\\' ) == -1 ) // e.g. "*.xps" or "filename.pdf" { outputfolder = inputfolder; outputfilespec = Path.Combine( outputfolder, outputfile ); } outputfolder = Directory.GetParent( outputfilespec ).FullName; if ( ValidateFilespec( outputfilespec ) == -1 ) { if ( outputfilespec.IndexOf( '*' ) == -1 ) { return ShowHelp( "Parent folder for output file not found" ); } else { return ShowHelp( "Parent folder for output files not found" ); } } } if ( outputformat == -1 ) { outputformat = GetFormatByExtension( outputfilespec ); } if ( outputformat == -1 ) { return ShowHelp( "Unrecognized output file type" ); } // Input and output file types should be different if ( inputformat == outputformat ) { return ShowHelp( "Input and output file types should be different" ); } // Input and output extensions should be different if ( inputfileext == outputfileext ) { return ShowHelp( "Input and output file extensions should be different" ); } #endregion Command Line Validation #region Iterate File List and Convert Each File int rc = 0; foreach ( string file in Directory.GetFiles( inputfolder, inputfile ) ) { if ( Path.GetExtension( file ) == inputfileext ) // prevent including *.pptx when *.ppt is specified { string output; if ( inputfilename.IndexOf( '*' ) > -1 ) { output = Path.Combine( outputfolder, Path.GetFileNameWithoutExtension( file ) + outputfileext ); } else { output = outputfilespec; } if ( File.Exists( output ) && !overwrite ) { if ( inputfilename.IndexOf( '*' ) > -1 ) { Console.WriteLine( "Skipped \"{0}\" because \"{1}\" already exists", Path.GetFileName( file ), Path.GetFileName( output ) ); } else { return ShowHelp( "Output file \"{0}\" already exists, use /O to silently overwrite existing files", Path.GetFileName( output ) ); } } else { Console.Write( "Converting \"{0}\" . . . ", Path.GetFileName( file ) ); string result = ConvertPowerPoint( file, output, outputformat ); Console.WriteLine( result ); if ( result != "Success" ) { rc += 1; } } } } #endregion Iterate File List and Convert Each File return rc; } // Opens the specified presentation and saves it with the specified file name and file type static string ConvertPowerPoint( string inputfile, string outputfile, int outputtype ) { string result = "Failed"; string outputfilename = Path.GetFileNameWithoutExtension( outputfile ); string outputextension = Path.GetExtension( outputfile ); string outputfolder; if ( outputfile.IndexOf( '\\' ) == -1 ) { outputfolder = Directory.GetParent( inputfile ).FullName; } else { outputfolder = Directory.GetParent( outputfile ).FullName; } if ( outputfilename == "*" ) { outputfilename = Path.GetFileNameWithoutExtension( inputfile ); } outputfile = Path.Combine( outputfolder, outputfilename + outputextension ); PowerPoint.Application pptapp = new PowerPoint.Application( ); PowerPoint.Presentation pptpres = pptapp.Presentations.Open( inputfile, MsoTriState.msoTrue, MsoTriState.msoTrue, MsoTriState.msoFalse ); try { PowerPoint.PpSaveAsFileType filetype = (PowerPoint.PpSaveAsFileType) outputtype; pptpres.SaveAs( outputfile, filetype ); result = "Success"; } catch { result = "Failed"; } pptpres.Close( ); pptapp.Quit( ); return result; } // Returns the numeric representation of the PowerPoint file format for the specified extension static int GetFormatByExtension( string file ) { string ext = Path.GetExtension( file ).ToLower( ).Substring( 1 ); Dictionary knownpptexts = new Dictionary( ); knownpptexts["htm"] = (int) PowerPoint.PpSaveAsFileType.ppSaveAsHTML; knownpptexts["html"] = (int) PowerPoint.PpSaveAsFileType.ppSaveAsHTML; knownpptexts["odp"] = (int) PowerPoint.PpSaveAsFileType.ppSaveAsOpenDocumentPresentation; knownpptexts["pdf"] = (int) PowerPoint.PpSaveAsFileType.ppSaveAsPDF; knownpptexts["pps"] = (int) PowerPoint.PpSaveAsFileType.ppSaveAsShow; knownpptexts["ppsx"] = (int) PowerPoint.PpSaveAsFileType.ppSaveAsOpenXMLShow; knownpptexts["ppt"] = (int) PowerPoint.PpSaveAsFileType.ppSaveAsPresentation; knownpptexts["pptx"] = (int) PowerPoint.PpSaveAsFileType.ppSaveAsOpenXMLPresentation; knownpptexts["xps"] = (int) PowerPoint.PpSaveAsFileType.ppSaveAsXPS; if ( knownpptexts.ContainsKey( ext ) && acceptedtypes.ContainsValue( knownpptexts[ext] ) ) { return knownpptexts[ext]; } return -1; } // Returns the numeric representation for the specified PowerPoint file format static int GetFormat( string format ) { // test for numeric fomat (type number) try { int testformat = (int) (PowerPoint.PpSaveAsFileType) Convert.ToInt32( format ); if ( acceptedtypes.ContainsValue( testformat ) ) { return testformat; } return -1; } catch { } // test for string format (type name) try { foreach ( string test in acceptedtypes.Keys ) { if ( test.ToUpper( ) == format.ToUpper( ) ) { return acceptedtypes[test]; } } } catch { } // return -1 if format not valid return -1; } // Lists all available file formats as string (name) and number static void ListFormats( ) { int maxlen = 0; foreach ( int i in acceptedtypes.Values ) { if ( ( (PowerPoint.PpSaveAsFileType) i ).ToString( ).Length > maxlen ) { maxlen = ( (PowerPoint.PpSaveAsFileType) i ).ToString( ).Length; } } ConsoleColor bgblue = ConsoleColor.DarkBlue; ConsoleColor bgdefault = Console.BackgroundColor; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine( String.Format( "{0,-" + maxlen + "} {1}", "File Type", "Number" ) ); if ( maxlen > 12 ) { Console.WriteLine( new String( '=', 12 ) + new String( ' ', maxlen - 12 + 2 ) + new String( '=', 6 ) ); } else { Console.WriteLine( new String( '=', maxlen ) + " " + new String( '=', 6 ) ); } List oddeven = new List { bgdefault, bgblue }; int linenum = 0; foreach ( int i in acceptedtypes.Values ) { Console.BackgroundColor = oddeven[linenum % 2]; foreach ( string type in acceptedtypes.Keys ) { if ( acceptedtypes[type] == i ) { Console.Write( String.Format( "{0,-" + maxlen + "} {1,4} ", type, i ) ); } } Console.BackgroundColor = bgdefault; Console.WriteLine( ); linenum += 1; } Console.ResetColor( ); } // Create a list of all available formats, removing known problem makers like bitmaps and RTF static Dictionary ListWorkingFormats( ) { List knownproblemtypes = new List( ); // Available file types that just don't work as expected knownproblemtypes.Add( (int) PowerPoint.PpSaveAsFileType.ppSaveAsBMP ); knownproblemtypes.Add( (int) PowerPoint.PpSaveAsFileType.ppSaveAsEMF ); knownproblemtypes.Add( (int) PowerPoint.PpSaveAsFileType.ppSaveAsGIF ); knownproblemtypes.Add( (int) PowerPoint.PpSaveAsFileType.ppSaveAsJPG ); knownproblemtypes.Add( (int) PowerPoint.PpSaveAsFileType.ppSaveAsMetaFile ); knownproblemtypes.Add( (int) PowerPoint.PpSaveAsFileType.ppSaveAsPNG ); knownproblemtypes.Add( (int) PowerPoint.PpSaveAsFileType.ppSaveAsRTF ); knownproblemtypes.Add( (int) PowerPoint.PpSaveAsFileType.ppSaveAsTIF ); Dictionary acceptedtypes = new Dictionary( ); acceptedtypes.Clear( ); for ( int i = 0; i < 64; i++ ) { if ( ( (PowerPoint.PpSaveAsFileType) i ).ToString( ) != i.ToString( ) ) { if ( !knownproblemtypes.Contains( i ) ) { acceptedtypes.Add( ( (PowerPoint.PpSaveAsFileType) i ).ToString( ), i ); } } } return acceptedtypes; } // Displays help text static int ShowHelp( params string[] errmsg ) { #region Help Text /* PowerPoint2Any, Version 1.00 Open a presentation in Microsoft PowerPoint and save it in "any" (known) format Usage: POWERPOINT2ANY "presentation" [ "outfile" ] [ options ] Where: "presentation" PowerPoint presentation(s) to be converted (wildcards allowed in file name, e.g. "name*.pptx") "outfile" output file(s) to be created (wildcard "*" allowed for file name, e.g. "*.odp" or "*.pdf") Options: /O silently overwrite existing output file(s) (default: abort or skip if output file exists) /T list accepted output file types /T:type set output file type (required if "outfile" is not specified; type may be number or string) Notes: [1] This program requires a "regular" (MSI based) Microsoft PowerPoint (2007 or later) installation, it will fail on an MS Office "click-to-run" installation. [2] For PowerPoint 2007, to save as PDF or XPS, this program requires the "Microsoft Save as PDF or XPS Add-in for 2007 Microsoft Office programs", available at: http://www.microsoft.com/en-us/download/details.aspx?id=7 [3] If wildcards are used in the PowerPoint file names, and the output file path is not specified, /T:type must be used, and the input file names should not contain dots. [4] If wildcards are used in the PowerPoint file names, and the output file path is specified, the output file name must be "*". [5] If wildcards are used in the PowerPoint file names, and the /O switch is not used, the program will display an error message in case an output file already exists, but it will then continue to convert the next file instead of aborting. [6] If PowerPoint was already active when this program is started, any other opened presentation(s) will be left alone, and only the presenation(s) opened by this program will be closed. Examples: EXCEL2ANY "D:\folder\myfile.ppt" *.pdf will save to "D:\folder\myfile.pdf" EXCEL2ANY "D:\folder\myfile.pptx" "D:\otherfolder\*.odp" will save to "D:\otherfolder\myfile.odp" EXCEL2ANY "D:\folder\myfile.pptx" "D:\elsewhere\newfile.xps" will save to "D:\elsewhere\newfile.xps" EXCEL2ANY "D:\folder\name*.pptx" *.html will save all matching files as HTML to "D:\folder\" recognized extensions: htm(l), odp, pdf, pps(x), ppt(x), xps EXCEL2ANY "D:\folder\*.pptx" /T:12 like previous example, but more file types available EXCEL2ANY /T will list all available file types Written by Rob van der Woude http://www.robvanderwoude.com */ if ( errmsg.Length > 0 ) { List errargs = new List( errmsg ); errargs.RemoveAt( 0 ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.Red; Console.Error.Write( "ERROR:\t" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) ); Console.ResetColor( ); } Console.Error.WriteLine( ); Console.Error.WriteLine( "PowerPoint2Any, Version {0}", progver ); Console.Error.WriteLine( "Open a presentation in Microsoft PowerPoint and save it in \"any\" (known) format" ); Console.Error.WriteLine( ); Console.Error.Write( "Usage: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "POWERPOINT2ANY \"presentation\" [ \"outfile\" ] [ options ]" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.Write( "Where: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "\"presentation\"" ); Console.ResetColor( ); Console.Error.WriteLine( " PowerPoint presentation(s) to be converted" ); Console.Error.WriteLine( " (wildcards allowed in file name, e.g. \"name*.pptx\")" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " \"outfile\"" ); Console.ResetColor( ); Console.Error.WriteLine( " output file(s) to be created (wildcard \"*\" allowed" ); Console.Error.WriteLine( " for file name, e.g. \"*.odp\" or \"*.pdf\")" ); Console.Error.Write( "Options: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "/O" ); Console.ResetColor( ); Console.Error.Write( " silently " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "O" ); Console.ResetColor( ); Console.Error.WriteLine( "verwrite existing output file(s)" ); Console.Error.WriteLine( " (default: abort or skip if output file exists)" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " /T" ); Console.ResetColor( ); Console.Error.Write( " list accepted output file " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "T" ); Console.ResetColor( ); Console.Error.WriteLine( "ypes" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " /T:type" ); Console.ResetColor( ); Console.Error.Write( " set output file " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "T" ); Console.ResetColor( ); Console.Error.Write( "ype (required if " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "\"outfile\"" ); Console.ResetColor( ); Console.Error.WriteLine( " is not" ); Console.Error.Write( " specified; " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "type" ); Console.ResetColor( ); Console.Error.WriteLine( " may be number or string)" ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Notes: [1] This program requires a \"regular\" (MSI based) Microsoft PowerPoint" ); Console.Error.WriteLine( " (2007 or later) installation, it will fail on an MS Office" ); Console.Error.WriteLine( " \"click-to-run\" installation" ); Console.Error.WriteLine( " [2] For PowerPoint 2007, to save as PDF or XPS, this program requires" ); Console.Error.WriteLine( " the \"Microsoft Save as PDF or XPS Add-in for 2007 Microsoft Office" ); Console.Error.WriteLine( " programs\", available at:" ); Console.Error.WriteLine( " http://www.microsoft.com/en-us/download/details.aspx?id=7" ); Console.Error.WriteLine( " [3] If wildcards are used in the PowerPoint file names, and the output" ); Console.Error.Write( " file path is not specified, " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "/T:type" ); Console.ResetColor( ); Console.Error.WriteLine( " must be used, and the input" ); Console.Error.WriteLine( " file names should not contain dots." ); Console.Error.WriteLine( " [4] If wildcards are used in the PowerPoint file names, and the output" ); Console.Error.Write( " file path is specified, the output file " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "name" ); Console.ResetColor( ); Console.Error.WriteLine( " must be \"*\"." ); Console.Error.Write( " [5] If wildcards are used in the PowerPoint file names, and the " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "/O" ); Console.ResetColor( ); Console.Error.WriteLine( " switch is not used, the program will display an error message in" ); Console.Error.WriteLine( " case an output file already exists, but it will then continue to" ); Console.Error.WriteLine( " convert the next file instead of aborting." ); Console.Error.WriteLine( " [6] If PowerPoint was already active when this program is started," ); Console.Error.WriteLine( " any other opened presentation(s) will be left alone, and only" ); Console.Error.WriteLine( " the presentation(s) opened by this program will be closed." ); Console.Error.WriteLine( ); Console.Error.Write( "Examples: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "POWERPOINT2ANY \"D:\\folder\\myfile.ppt\" *.pdf" ); Console.ResetColor( ); Console.Error.WriteLine( " will save to \"D:\\folder\\myfile.pdf\"" ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( " POWERPOINT2ANY \"D:\\folder\\myfile.pptx\" \"D:\\otherfolder\\*.odp\"" ); Console.ResetColor( ); Console.Error.WriteLine( " will save to \"D:\\otherfolder\\myfile.odp\"" ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( " POWERPOINT2ANY \"D:\\folder\\myfile.pptx\" \"D:\\elsewhere\\newfile.xps\"" ); Console.ResetColor( ); Console.Error.WriteLine( " will save to \"D:\\elsewhere\\newfile.xps\"" ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( " POWERPOINT2ANY \"D:\\folder\\name*.pptx\" *.html" ); Console.ResetColor( ); Console.Error.WriteLine( " will save all matching files as HTML to \"D:\\folder\\\"" ); Console.Error.WriteLine( " recognized extensions: htm(l), odp, pdf, pps(x), ppt(x), xps" ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( " POWERPOINT2ANY \"D:\\folder\\*.pptx\" /T:12" ); Console.ResetColor( ); Console.Error.WriteLine( " like previous example, but more file types available" ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( " POWERPOINT2ANY /T" ); Console.ResetColor( ); Console.Error.WriteLine( " will list all accepted file types" ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Written by Rob van der Woude" ); Console.Error.WriteLine( "http://www.robvanderwoude.com" ); #endregion Help Text return 1; } // Returns -1 if folder not found, 0 if no matching files found, otherwise the matching file count static int ValidateFilespec( string filespec ) { int matchingfiles = -1; try { string parentfolder = Directory.GetParent( filespec ).FullName; if ( Directory.Exists( parentfolder ) ) { matchingfiles = 0; foreach ( string matchingfile in Directory.GetFiles( parentfolder, Path.GetFileName( filespec ) ) ) { matchingfiles += 1; } } } catch { }; return matchingfiles; } } }