OfficeToXps: Convert Word, Excel, and PowerPoint to XPS

May 11th, 2010 by Mel Leave a reply »

I recently had the need to convert Word, Excel, and PowerPoint files to Microsoft’s XPS format for easy displaying in WPF. There’s a plethora of articles, threads, and questions out there that illustrate how to do this, but I haven’t seen anyone compile a single class/library that will convert from all three applications with good error handling and no price tag.

So I figured since I had to write it anyway I’d post it here for the aid of anyone else looking to do the same thing. As always comments/questions/praise are appreciated.

Download Code File

using System;
using System.Collections.Generic;
using System.IO;
using Excel = Microsoft.Office.Interop.Excel;
using PowerPoint = Microsoft.Office.Interop.PowerPoint;
using Word = Microsoft.Office.Interop.Word;
 
namespace CGS
{
    public class OfficeToXps
    {
        #region Properties & Constants
        private static List<string> wordExtensions = new List<string>
        {
            ".doc",
            ".docx"
        };
 
        private static List<string> excelExtensions = new List<string>
        {
            ".xls",
            ".xlsx"
        };
 
        private static List<string> powerpointExtensions = new List<string>
        {
            ".ppt",
            ".pptx"
        };
 
        #endregion
 
        #region Public Methods
        public static OfficeToXpsConversionResult ConvertToXps(string sourceFilePath, ref string resultFilePath)
        {
            var result = new OfficeToXpsConversionResult(ConversionResult.UnexpectedError);
 
            // Check to see if it's a valid file
            if (!IsValidFilePath(sourceFilePath))
            {
                result.Result = ConversionResult.InvalidFilePath;
                result.ResultText = sourceFilePath;
                return result;
            }
 
 
 
            var ext = Path.GetExtension(sourceFilePath).ToLower();
 
            // Check to see if it's in our list of convertable extensions
            if (!IsConvertableFilePath(sourceFilePath))
            {
                result.Result = ConversionResult.InvalidFileExtension;
                result.ResultText = ext;
                return result;
            }
 
            // Convert if Word
            if (wordExtensions.Contains(ext))
            {
                return ConvertFromWord(sourceFilePath, ref resultFilePath);
            }
 
            // Convert if Excel
            if (excelExtensions.Contains(ext))
            {
                return ConvertFromExcel(sourceFilePath, ref resultFilePath);
            }
 
            // Convert if PowerPoint
            if (powerpointExtensions.Contains(ext))
            {
                return ConvertFromPowerPoint(sourceFilePath, ref resultFilePath);
            }
 
            return result;
        }
        #endregion
 
        #region Private Methods
        public static bool IsValidFilePath(string sourceFilePath)
        {
            if (string.IsNullOrEmpty(sourceFilePath))
                return false;
 
            try
            {
                return File.Exists(sourceFilePath);
            }
            catch (Exception)
            {
            }
 
            return false;
        }
 
        public static bool IsConvertableFilePath(string sourceFilePath)
        {
            var ext = Path.GetExtension(sourceFilePath).ToLower();
 
            return IsConvertableExtension(ext);
        }
        public static bool IsConvertableExtension(string extension)
        {
            return wordExtensions.Contains(extension) ||
                   excelExtensions.Contains(extension) ||
                   powerpointExtensions.Contains(extension);
        }
 
        private static string GetTempXpsFilePath()
        {
            return Path.ChangeExtension(Path.GetTempFileName(), ".xps");
        }
 
 
        private static OfficeToXpsConversionResult ConvertFromWord(string sourceFilePath, ref string resultFilePath)
        {
            object pSourceDocPath = sourceFilePath;
 
            string pExportFilePath = string.IsNullOrWhiteSpace(resultFilePath) ? GetTempXpsFilePath() : resultFilePath;
 
            try
            {
                var pExportFormat = Word.WdExportFormat.wdExportFormatXPS;
                bool pOpenAfterExport = false;
                var pExportOptimizeFor = Word.WdExportOptimizeFor.wdExportOptimizeForOnScreen;
                var pExportRange = Word.WdExportRange.wdExportAllDocument;
                int pStartPage = 0;
                int pEndPage = 0;
                var pExportItem = Word.WdExportItem.wdExportDocumentContent;
                var pIncludeDocProps = true;
                var pKeepIRM = true;
                var pCreateBookmarks = Word.WdExportCreateBookmarks.wdExportCreateWordBookmarks;
                var pDocStructureTags = true;
                var pBitmapMissingFonts = true;
                var pUseISO19005_1 = false;
 
 
                Word.Application wordApplication = null;
                Word.Document wordDocument = null;
 
                try
                {
                    wordApplication = new Word.Application();
                }
                catch (Exception exc)
                {
                    return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToInitializeOfficeApp, "Word", exc);
                }
 
                try
                {
                    try
                    {
                        wordDocument = wordApplication.Documents.Open(ref pSourceDocPath);
                    }
                    catch (Exception exc)
                    {
                        return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToOpenOfficeFile, exc.Message, exc);
                    }
 
                    if (wordDocument != null)
                    {
                        try
                        {
                            wordDocument.ExportAsFixedFormat(
                                                pExportFilePath,
                                                pExportFormat,
                                                pOpenAfterExport,
                                                pExportOptimizeFor,
                                                pExportRange,
                                                pStartPage,
                                                pEndPage,
                                                pExportItem,
                                                pIncludeDocProps,
                                                pKeepIRM,
                                                pCreateBookmarks,
                                                pDocStructureTags,
                                                pBitmapMissingFonts,
                                                pUseISO19005_1
                                            );
                        }
                        catch (Exception exc)
                        {
                            return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToExportToXps, "Word", exc);
                        }
                    }
                    else
                    {
                        return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToOpenOfficeFile);
                    }
                }
                finally
                {
                    // Close and release the Document object.
                    if (wordDocument != null)
                    {
                        wordDocument.Close();
                        wordDocument = null;
                    }
 
                    // Quit Word and release the ApplicationClass object.
                    if (wordApplication != null)
                    {
                        wordApplication.Quit();
                        wordApplication = null;
                    }
 
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                }
            }
            catch (Exception exc)
            {
                return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToAccessOfficeInterop, "Word", exc);
            }
 
            resultFilePath = pExportFilePath;
 
            return new OfficeToXpsConversionResult(ConversionResult.OK, pExportFilePath);
        }
 
        private static OfficeToXpsConversionResult ConvertFromPowerPoint(string sourceFilePath, ref string resultFilePath)
        {
            string pSourceDocPath = sourceFilePath;
 
            string pExportFilePath = string.IsNullOrWhiteSpace(resultFilePath) ? GetTempXpsFilePath() : resultFilePath;
 
            try
            {
                PowerPoint.Application pptApplication = null;
                PowerPoint.Presentation pptPresentation = null;
 
                try
                {
                    pptApplication = new PowerPoint.Application();
                }
                catch (Exception exc)
                {
                    return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToInitializeOfficeApp, "PowerPoint", exc);
                }
 
                try
                {
                    try
                    {
                        pptPresentation = pptApplication.Presentations.Open(pSourceDocPath,
                                                                            Microsoft.Office.Core.MsoTriState.msoTrue,
                                                                            Microsoft.Office.Core.MsoTriState.msoTrue,
                                                                            Microsoft.Office.Core.MsoTriState.msoFalse);
                    }
                    catch (Exception exc)
                    {
                        return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToOpenOfficeFile, exc.Message, exc);
                    }
 
                    if (pptPresentation != null)
                    {
                        try
                        {
                            pptPresentation.ExportAsFixedFormat(
                                                pExportFilePath,
                                                PowerPoint.PpFixedFormatType.ppFixedFormatTypeXPS,
                                                PowerPoint.PpFixedFormatIntent.ppFixedFormatIntentScreen,
                                                Microsoft.Office.Core.MsoTriState.msoFalse,
                                                PowerPoint.PpPrintHandoutOrder.ppPrintHandoutVerticalFirst,
                                                PowerPoint.PpPrintOutputType.ppPrintOutputSlides,
                                                Microsoft.Office.Core.MsoTriState.msoFalse,
                                                null,
                                                PowerPoint.PpPrintRangeType.ppPrintAll,
                                                string.Empty,
                                                true,
                                                true,
                                                true,
                                                true,
                                                false
                                            );
                        }
                        catch (Exception exc)
                        {
                            return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToExportToXps, "PowerPoint", exc);
                        }
                    }
                    else
                    {
                        return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToOpenOfficeFile);
                    }
                }
                finally
                {
                    // Close and release the Document object.
                    if (pptPresentation != null)
                    {
                        pptPresentation.Close();
                        pptPresentation = null;
                    }
 
                    // Quit Word and release the ApplicationClass object.
                    if (pptApplication != null)
                    {
                        pptApplication.Quit();
                        pptApplication = null;
                    }
 
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                }
            }
            catch (Exception exc)
            {
                return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToAccessOfficeInterop, "PowerPoint", exc);
            }
 
            resultFilePath = pExportFilePath;
 
            return new OfficeToXpsConversionResult(ConversionResult.OK, pExportFilePath);
        }
 
        private static OfficeToXpsConversionResult ConvertFromExcel(string sourceFilePath, ref string resultFilePath)
        {
            string pSourceDocPath = sourceFilePath;
 
            string pExportFilePath = string.IsNullOrWhiteSpace(resultFilePath) ? GetTempXpsFilePath() : resultFilePath;
 
            try
            {
                var pExportFormat = Excel.XlFixedFormatType.xlTypeXPS;
                var pExportQuality = Excel.XlFixedFormatQuality.xlQualityStandard;
                var pOpenAfterPublish = false;
                var pIncludeDocProps = true;
                var pIgnorePrintAreas = true;
 
 
                Excel.Application excelApplication = null;
                Excel.Workbook excelWorkbook = null;
 
                try
                {
                    excelApplication = new Excel.Application();
                }
                catch (Exception exc)
                {
                    return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToInitializeOfficeApp, "Excel", exc);
                }
 
                try
                {
                    try
                    {
                        excelWorkbook = excelApplication.Workbooks.Open(pSourceDocPath);
                    }
                    catch (Exception exc)
                    {
                        return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToOpenOfficeFile, exc.Message, exc);
                    }
 
                    if (excelWorkbook != null)
                    {
                        try
                        {
                            excelWorkbook.ExportAsFixedFormat(
                                                pExportFormat,
                                                pExportFilePath,
                                                pExportQuality,
                                                pIncludeDocProps,
                                                pIgnorePrintAreas,
 
                                                OpenAfterPublish : pOpenAfterPublish
                                            );
                        }
                        catch (Exception exc)
                        {
                            return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToExportToXps, "Excel", exc);
                        }
                    }
                    else
                    {
                        return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToOpenOfficeFile);
                    }
                }
                finally
                {
                    // Close and release the Document object.
                    if (excelWorkbook != null)
                    {
                        excelWorkbook.Close();
                        excelWorkbook = null;
                    }
 
                    // Quit Word and release the ApplicationClass object.
                    if (excelApplication != null)
                    {
                        excelApplication.Quit();
                        excelApplication = null;
                    }
 
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                }
            }
            catch (Exception exc)
            {
                return new OfficeToXpsConversionResult(ConversionResult.ErrorUnableToAccessOfficeInterop, "Excel", exc);
            }
 
            resultFilePath = pExportFilePath;
 
            return new OfficeToXpsConversionResult(ConversionResult.OK, pExportFilePath);
        }
        #endregion
    }
 
    public class OfficeToXpsConversionResult
    {
        #region Properties
        public ConversionResult Result { get; set; }
        public string ResultText { get; set; }
        public Exception ResultError { get; set; } 
        #endregion
 
        #region Constructors
        public OfficeToXpsConversionResult()
        {
            Result = ConversionResult.UnexpectedError;
            ResultText = string.Empty;
        }
        public OfficeToXpsConversionResult(ConversionResult result)
            : this()
        {
            Result = result;
        }
        public OfficeToXpsConversionResult(ConversionResult result, string resultText)
            : this(result)
        {
            ResultText = resultText;
        }
        public OfficeToXpsConversionResult(ConversionResult result, string resultText, Exception exc)
            : this(result, resultText)
        {
            ResultError = exc;
        } 
        #endregion
    }
 
    public enum ConversionResult
    {
        OK = 0,
        InvalidFilePath = 1,
        InvalidFileExtension = 2,
        UnexpectedError = 3,
        ErrorUnableToInitializeOfficeApp = 4,
        ErrorUnableToOpenOfficeFile = 5,
        ErrorUnableToAccessOfficeInterop = 6,
        ErrorUnableToExportToXps = 7
    }
}

This solution uses the 2007 Office Interop libraries for Word, Excel, and PowerPoint. To compile it in Visual Studio you’ll need to reference these assemblies in your project. For example here’s what the Word assembly looks like:

Also note that I’ve made use of some shortcuts provided by the new optional parameters in C# 4.0. If you’re using an earlier version of .Net you’ll have to make some changes to the interop calls, but it’s nothing serious.

Here’s a quick example of using the given code in an application:

string filePath = @"C:\Test\Test.doc";
string xpsFilePath = @"C:\Test\Test.xps";
 
var convertResults = OfficeToXps.ConvertToXps(filePath, ref xpsFilePath);
 
switch (convertResults.Result)
{
    case ConversionResult.OK:
        XpsDocument xpsDoc = new XpsDocument(xpsFilePath, FileAccess.ReadWrite);
        break;
 
    case ConversionResult.InvalidFilePath:
        // Handle bad file path or file missing
        break;
    case ConversionResult.UnexpectedError:
        // This should only happen if the code is modified poorly
        break;
    case ConversionResult.ErrorUnableToInitializeOfficeApp:
        // Handle Office 2007 (Word | Excel | PowerPoint) not installed
        break;
    case ConversionResult.ErrorUnableToOpenOfficeFile:
        // Handle source file being locked or invalid permissions
        break;
    case ConversionResult.ErrorUnableToAccessOfficeInterop:
        // Handle Office 2007 (Word | Excel | PowerPoint) not installed
        break;
    case ConversionResult.ErrorUnableToExportToXps:
        // Handle Microsoft Save As PDF or XPS Add-In missing for 2007
        break;
}
Advertisement

13 comments

  1. Ankit says:

    I have a Refresh functionality – when I click Refresh button, the document must be converted to XPS format again. For this I invoke ConvertFromPowerPoint().
    Issue:
    I have a PPT file open, then run the application. Upon clicking Refresh button twice or more, the other PPT file closes.
    Any idea how I can stop this?

  2. Zarfishan Zahid says:

    Using Saaspose Document Converter (http://saaspose.com) you can convert any MS office document to XPS online for free.

  3. Reem says:

    Thank you so much, you saved my life

  4. Manuj says:

    If I use this code through service(for word) I get this error: The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))

    Also, the instance of word that is created has to be killed manually. 

    • Mel says:

      Hey Manuj,

      I’m not sure why you’d be seeing that error. A quick Google search indicates that it might be due to Word attempting to show some dialog or alert but it’s set to not be visible by the code I posted. Try some of the results from this search.

  5. Vijay says:

    Hi Mel,

    I was looking for similar solution to view word document into silverlight 4 application.

    Can we extend your solution in providing deep zoom or like page next /previous in XPS files to make complete word document viewer control and make it free for Silverlight/wfp community to use?

    Thank you,
    Vijay

  6. sarala says:

    Mel,
    Word 2007 did the trick. I was able to run it.
    Will continue to read the rest of your articles.
    (I am java programmer just moved to WPF).
    Thanks again!!!

    Sarala
     

  7. sarala says:

    Mel,
    Thanks for the quick response.
    I am using Microsoft Word 2003. Interop Version 12.0.

    Sarala

    • Mel says:

      Sarala,

      Word 2003 is most likely your problem. This solution should only work with Office 2007 or later since that’s when Microsoft introduced support for exporting to XPS.

      I’m sorry I didn’t make that clearer in my original post. =\

      Try it with Word 2007 or 2010 and see if you have better luck!

  8. sarala says:

    Thank you. I just downloaded the code. Have no compilation errors. But when I run it I get
    “Attempted to read or write protected memory. This is often an indication that other memory is corrupt.” at wordDocument.ExportAsFixedFormat.
    Not sure how to resolve this. Any help will be
    appreciated
     

     

     

    • Mel says:

      Hey Sarala,

      This is likely due to an error with the particular Office Interop you’re using. What version of word are you testing this with? Have you installed the correct interop libraries for that version?

  9. Bill says:

    yes, thank you for this.

Leave a Reply