最近在一个项目碰到一个问题,要用WPF打开并显示打印Office文档。包括Word, Excel, 和PowerPoint 文档。找了很多资料,解决方案之一:调用第三方开发的Word, Excel, PowerPoint解析控件,三个不同的人开发的,要使用三个控件才能解决这个问题。而且有些控件对解析表格和图片还存在问题。
所以只好使用第二个解决方案,把Office文档先转换成XPS,然后用DocumentViewer 来显示XPS。
所以解决方案的操作流程是:打开Office文档=》转换并在硬盘生成XPS=》加载显示XPS=》任务完成后删除XPS。
也许你会问,为什么不在内存直接转换而必须在硬盘生成,答案是内存转换容易产生格式的错误。
以下代码适用于目标计算机已安装Office2007或以上版本,对于Office 2003,需要下载 Office升级插件
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3C9A983A-AC14-4125-8BA0-D36D67E0F4AD
那我们开始吧:
在一个工程文件添加如下引用:
Microsoft.Office.Interop.Excel(C:/Program Files/Microsoft Visual Studio 10.0/Visual Studio Tools for Office/PIA/Office12/Microsoft.Office.Interop.Excel.dll)
Microsoft.Office.Interop.PowerPoint (C:/Program Files/Microsoft Visual Studio 10.0/Visual Studio Tools for Office/PIA/Office12/Microsoft.Office.Interop.PowerPoint.dll)
Microsoft.Office.Interop.Word (C:/Program Files/Microsoft Visual Studio 10.0/Visual Studio Tools for Office/PIA/Office12/Microsoft.Office.Interop.Word.dll)
OFFICE (C:/Windows/assembly/GAC/office/12.0.0.0__71e9bce111e9429c/OFFICE.DLL)
ReachFramework
(C:/Program Files/Reference Assemblies/Microsoft/Framework/v3.0/ReachFramework.dll
以上的引用可直接在引用窗口点击“浏览”,直接找到相应的DLL,并添加就可以了。
我们先完成最关键的步骤:Office文档转成XPS
首先创建一个转换类:
OfficeToXps.cs
代码如下:
- 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 Office_To_XPS
{
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);
if (!IsValidFilePath(sourceFilePath))
{
result.Result = ConversionResult.InvalidFilePath;
result.ResultText = sourceFilePath;
return result;
}
var ext = Path.GetExtension(sourceFilePath).ToLower();
if (!IsConvertableFilePath(sourceFilePath))
{
result.Result = ConversionResult.InvalidFileExtension;
result.ResultText = ext;
return result;
}
if (wordExtensions.Contains(ext))
{
return ConvertFromWord(sourceFilePath, ref resultFilePath);
}
if (excelExtensions.Contains(ext))
{
return ConvertFromExcel(sourceFilePath, ref resultFilePath);
}
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.IsNullOrEmpty(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
{
if (wordDocument != null)
{
wordDocument.Close();
wordDocument = null;
}
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.IsNullOrEmpty(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
{
if (pptPresentation != null)
{
pptPresentation.Close();
pptPresentation = null;
}
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.IsNullOrEmpty(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
{
if (excelWorkbook != null)
{
excelWorkbook.Close();
excelWorkbook = null;
}
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
}
}
有了这个类,我们可以轻而易举的把Word, Excel 和 PPT文档转成XPS。
调用方法如下:
- private void button1_Click(object sender, RoutedEventArgs e)
- {
- OpenFileDialog dlg = new OpenFileDialog();
- dlg.CheckFileExists = true;
- dlg.Filter = "PowerPoint Format (*.ppt,*.pptx)|*.ppt;*.pptx|" +
- "All files (*.*)|*.*";
-
- if ((bool)dlg.ShowDialog(this))
- {
- string filePath = dlg.FileName;
- string xpsFilePath = dlg.FileName + ".xps";
- PleaseWait pw = new PleaseWait();
- pw.Owner = this;
- pw.Show();
- var convertResults = OfficeToXps.ConvertToXps(filePath, ref xpsFilePath);
- pw.Close();
- switch (convertResults.Result)
- {
- case ConversionResult.OK:
- Xps_Document xps = new Xps_Document(xpsFilePath);
- xps.Owner = this;
- xps.Show();
- break;
-
- case ConversionResult.InvalidFilePath:
-
- break;
- case ConversionResult.UnexpectedError:
-
- break;
- case ConversionResult.ErrorUnableToInitializeOfficeApp:
-
- break;
- case ConversionResult.ErrorUnableToOpenOfficeFile:
-
- break;
- case ConversionResult.ErrorUnableToAccessOfficeInterop:
-
- break;
- case ConversionResult.ErrorUnableToExportToXps:
-
- break;
- }
- }
- }
由于有些文档可能很大,为了保证在完全转换后才加载XPS,我们可以接收OfficeToXps.cs里 ConversionResult属性,只有在接收到ConversionResult.OK 属性的情况下,才能开始加载XPS文件。
为了让用户稍作等待,我们这里姑且用一个比较简陋的方法提示用户等待。
PleaseWait pw = new PleaseWait();
pw.Owner = this;
pw.Show();
我们打开一个无边框的窗体,上面写着“请等待”。大家也可以使用WPFToolKit里的BusyIndicator;
转换完成后,pw.Close();关闭窗体。
加载XPS的代码非常简单:
在窗体的XAML里定义一个DocumentViewer:
<Window x:Class="Office_To_XPS.Xps_Document"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="XpsDocument" Height="413" Width="605" WindowStartupLocation="CenterScreen">
<DocumentViewer x:Name="xpsDoc"/>
</Window>
在C#里:
private void LoadXPSFile(string _xpsfile)
{
using (XpsDocument xpsDoc = new XpsDocument(_xpsfile, FileAccess.Read))
{
var fs = xpsDoc.GetFixedDocumentSequence();
this.xpsDoc.Document = fs;
}
}
大功告成!效果图如下图所示:
可以打开任何Word, Excel, PowerPoint文件,而且支持显示文件内的图形,表格等各类元素!
本文完整代码下载