由于加班要转换Office文档及CAD为PDF,为了省事因此临时写个批量转换PDF工具。CAD已经有现成的一个叫Convert的工具,那就剩下Office这边的Word,Excel,PowerPoint的转换了。微软在Office 2007已经提供了一个叫save as pdf or xps的插件,但插件只能单个转换。因此网上搜了一下这方面的转换代码,搜来搜去很杂,itext,icreator等等,文档也不是很详细,于是想想微软应该提供了这方面的接口,查阅了一下MSDN,微软确实提供了.NET 调用Office com接口转换PDF的代码,以下简直封装的代码。
准备条件:
Office 12 dll Microsoft.Office.Interop.Word,Microsoft.Office.Interop.Excel.....
save as pdf插件
代码部分:
Word代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Word;
using Microsoft.Office.Core;
using System.Threading;
namespace ConvertToPDF.BaseClass
{
public class WordToPDF:OfficeToPDF
{
#region 初始化参数
ApplicationClass wordApplication = null ;
Document wordDocument = null ;
object paramMissing;
WdExportFormat paramExportFormat;
bool paramOpenAfterExport;
WdExportOptimizeFor paramExportOptimizeFor;
WdExportRange paramExportRange;
int paramStartPage = 0 ;
int paramEndPage = 0 ;
WdExportItem paramExportItem;
bool paramIncludeDocProps;
bool paramKeepIRM;
WdExportCreateBookmarks paramCreateBookmarks;
bool paramDocStructureTags;
bool paramBitmapMissingFonts;
bool paramUseISO19005_1;
object paramReadOnly;
#endregion
public WordToPDF()
{
paramMissing = Type.Missing;
paramExportFormat = WdExportFormat.wdExportFormatPDF;
paramOpenAfterExport = false ;
paramExportOptimizeFor = WdExportOptimizeFor.wdExportOptimizeForPrint;
paramExportRange = WdExportRange.wdExportAllDocument;
paramStartPage = 0 ;
paramEndPage = 0 ;
paramExportItem = WdExportItem.wdExportDocumentContent;
paramIncludeDocProps = true ;
paramKeepIRM = true ;
paramCreateBookmarks = WdExportCreateBookmarks.wdExportCreateWordBookmarks;
paramDocStructureTags = true ;
paramBitmapMissingFonts = true ;
paramUseISO19005_1 = false ;
paramReadOnly = true ;
}
public override void SaveAsPDF( string paramSourceFilePath, string paramExportFilePath)
{
try
{
object paramSourceDocPath = ( object )paramSourceFilePath;
// Open the source document.
wordDocument = wordApplication.Documents.Open(
ref paramSourceDocPath, ref paramMissing, ref paramReadOnly,
ref paramMissing, ref paramMissing, ref paramMissing,
ref paramMissing, ref paramMissing, ref paramMissing,
ref paramMissing, ref paramMissing, ref paramMissing,
ref paramMissing, ref paramMissing, ref paramMissing,
ref paramMissing);
// Export it in the specified format.
if (wordDocument != null )
wordDocument.ExportAsFixedFormat(paramExportFilePath,
paramExportFormat, paramOpenAfterExport,
paramExportOptimizeFor, paramExportRange, paramStartPage,
paramEndPage, paramExportItem, paramIncludeDocProps,
paramKeepIRM, paramCreateBookmarks, paramDocStructureTags,
paramBitmapMissingFonts, paramUseISO19005_1,
ref paramMissing);
// 通知成功
OnFinish(paramSourceFilePath, paramExportFilePath);
Thread.Sleep( 1000 );
}
catch (Exception ex)
{
OnError(ex, paramSourceFilePath, paramExportFilePath);
try
{
// Close and release the Document object.
if (wordDocument != null )
{
wordDocument.Close( ref paramMissing, ref paramMissing,
ref paramMissing);
wordDocument = null ;
}
}
catch (Exception e)
{
if (wordDocument != null )
wordDocument = null ;
}
}
}
public override void Open()
{
wordApplication = new ApplicationClass();
}
public override void Close()
{
try
{
// Close and release the Document object.
if (wordDocument != null )
{
wordDocument.Close( ref paramMissing, ref paramMissing,
ref paramMissing);
wordDocument = null ;
}
}
catch (Exception ex)
{
wordDocument = null ;
}
try
{
if (wordApplication != null )
{
wordApplication.Quit( ref paramMissing, ref paramMissing,
ref paramMissing);
wordApplication = null ;
}
}
catch (Exception ex)
{
wordApplication = null ;
ProcessManager.KillWordProcess();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
Excel代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Excel;
using Microsoft.Office.Core;
using System.Threading;
namespace ConvertToPDF.BaseClass
{
public class ExcelToPDF:OfficeToPDF
{
#region 参数定义
Microsoft.Office.Interop.Excel.ApplicationClass excelApplication = null ;
Workbook excelWorkBook = null ;
object paramMissing = Type.Missing;
XlFixedFormatType paramExportFormat = XlFixedFormatType.xlTypePDF;
XlFixedFormatQuality paramExportQuality = XlFixedFormatQuality.xlQualityStandard;
bool paramOpenAfterPublish;
bool paramIncludeDocProps;
bool paramIgnorePrintAreas;
object paramFromPage;
object paramToPage;
#endregion
public ExcelToPDF()
{
paramMissing = Type.Missing;
paramExportFormat = XlFixedFormatType.xlTypePDF;
paramExportQuality = XlFixedFormatQuality.xlQualityStandard;
paramOpenAfterPublish = false ;
paramIncludeDocProps = true ;
paramIgnorePrintAreas = true ;
paramFromPage = Type.Missing;
paramToPage = Type.Missing;
}
public override void Open()
{
excelApplication = new Microsoft.Office.Interop.Excel.ApplicationClass();
}
public override void Close()
{
try
{
// Close the workbook object.
if (excelWorkBook != null )
{
excelWorkBook.Close( false , paramMissing, paramMissing);
excelWorkBook = null ;
}
}
catch (Exception ex)
{
excelWorkBook = null ;
}
try
{
// Quit Excel and release the ApplicationClass object.
if (excelApplication != null )
{
excelApplication.Quit();
excelApplication = null ;
}
}
catch (Exception ex)
{
excelApplication = null ;
ProcessManager.KillExcelProcess();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
public override void SaveAsPDF( string paramSourceFilePath, string paramExportFilePath)
{
try
{
// Open the source workbook.
excelWorkBook = excelApplication.Workbooks.Open(paramSourceFilePath,
paramMissing, paramMissing, paramMissing, paramMissing,
paramMissing, paramMissing, paramMissing, paramMissing,
paramMissing, paramMissing, paramMissing, paramMissing,
paramMissing, paramMissing);
// Save it in the target format.
if (excelWorkBook != null )
excelWorkBook.ExportAsFixedFormat(paramExportFormat,
paramExportFilePath, paramExportQuality,
paramIncludeDocProps, paramIgnorePrintAreas, paramFromPage,
paramToPage, paramOpenAfterPublish,
paramMissing);
// 完成通知
OnFinish(paramSourceFilePath,paramExportFilePath);
Thread.Sleep( 1000 );
}
catch (Exception ex)
{
// Respond to the error.
OnError(ex,paramSourceFilePath,paramExportFilePath);
try
{
// Close the workbook object.
if (excelWorkBook != null )
{
excelWorkBook.Close( false , paramMissing, paramMissing);
excelWorkBook = null ;
}
}
catch (Exception e)
{
// Close the workbook object.
if (excelWorkBook != null )
excelWorkBook = null ;
}
}
}
}
}
open打开一个Office进程(Word为Word.exe,Excel为Excel.exe进程,Close关闭此进程)。在转换Word中总会碰到一些意外(有时候是RPC不响应),当进程未正常关闭时则杀死此进程。
另外注意一点,在转换Word过程使用的是只读模式,否进出现意外后会弹出此Word文档副本操作,很麻烦。基类OfficeToPDF提供了事件通知机制,接口IOfficeToPDF提供了事件注册及公用的接口方法SaveAsPDF。事件主要用来控制异常和查看进度。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConvertToPDF.BaseClass
{
public class PDFConvertEventArgs : EventArgs
{
public PDFConvertEventArgs()
{ }
public Exception Exception { set ; get ; }
public string SourceFilePath { set ; get ; }
public string ExportFilePath { set ; get ; }
}
public interface IOfficeToPDF
{
void SaveAsPDF( string paramSourceFilePath, string paramExportFilePath);
event EventHandler < PDFConvertEventArgs > Error;
event EventHandler < PDFConvertEventArgs > Finish;
void Open();
void Close();
}
public abstract class OfficeToPDF : IOfficeToPDF
{
#region IOfficeToPDF 成员
public virtual void SaveAsPDF( string paramSourceFilePath, string paramExportFilePath)
{
throw new NotImplementedException();
}
public event EventHandler < PDFConvertEventArgs > Error;
public event EventHandler < PDFConvertEventArgs > Finish;
protected void OnError(Exception ex)
{
if (Error != null )
{
PDFConvertEventArgs args = new PDFConvertEventArgs();
args.Exception = ex;
Error( this , args);
}
}
protected void OnError(Exception ex, string paramSourceFilePath, string paramExportFilePath)
{
if (Error != null )
{
PDFConvertEventArgs args = new PDFConvertEventArgs();
args.Exception = ex;
args.SourceFilePath = paramSourceFilePath;
args.ExportFilePath = paramExportFilePath;
Error( this , args);
}
}
protected void OnFinish()
{
if (Finish != null )
{
PDFConvertEventArgs args = new PDFConvertEventArgs();
Finish( this , args);
}
}
protected void OnFinish( string paramSourceFilePath, string paramExportFilePath)
{
if (Finish != null )
{
PDFConvertEventArgs args = new PDFConvertEventArgs();
args.SourceFilePath = paramSourceFilePath;
args.ExportFilePath = paramExportFilePath;
Finish( this , args);
}
}
public virtual void Open()
{
throw new NotImplementedException();
}
public virtual void Close()
{
throw new NotImplementedException();
}
#endregion
}
}
转Word总会出现一些莫名其妙的问题,没办法只增加了一个杀死进程的类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
namespace ConvertToPDF.BaseClass
{
class ProcessManager
{
// 获取程序集
// private static Assembly _reflect = Assembly.Load("ExcelConvert");
[DllImport( " kernel32.dll " )]
private static extern IntPtr _lopen( string lpPathName, int iReadWrite);
[DllImport( " kernel32.dll " )]
private static extern bool CloseHandle(IntPtr hObject);
private static int OF_READWRITE = 2 ;
private static int OF_SHARE_DENY_NONE = 0x40 ;
private static readonly IntPtr HFILE_ERROR = new IntPtr( - 1 );
/// <summary>
/// 判断文是否被占用
/// </summary>
///
///
///
/// <param name="filePath"></param>
/// <returns></returns>
public static bool FileIsUsing( string filePath)
{
bool result = false ;
IntPtr vHandle = _lopen(filePath, OF_READWRITE | OF_SHARE_DENY_NONE);
if (vHandle == HFILE_ERROR)
{
result = true ;
}
CloseHandle(vHandle);
return result;
}
/// <summary>
/// 杀死EXCEL进程
/// </summary>
public static void KillExcelProcess()
{
KillProcess( " Excel " );
}
/// <summary>
/// 杀死EXCEL进程
/// </summary>
public static void KillWordProcess()
{
KillProcess( " Word " );
}
/// <summary>
/// 杀死进程
/// </summary>
public static void KillProcess( string processName)
{
System.Diagnostics.Process[] excelProcess = System.Diagnostics.Process.GetProcessesByName(processName);
foreach (System.Diagnostics.Process process in excelProcess)
{
if (process != null )
{
process.Kill();
}
}
}
/// <summary>
/// 杀死进程
/// </summary>
public static bool ProcessIsRun( string processName)
{
bool isRun = false ;
System.Diagnostics.Process[] excelProcess = System.Diagnostics.Process.GetProcessesByName(processName);
foreach (System.Diagnostics.Process process in excelProcess)
{
if (process != null )
isRun = true ;
}
return isRun;
}
}
}
看一下简单调用的方式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
word.Error += new EventHandler < PDFConvertEventArgs > (office_Error);
word.Finish += new EventHandler < PDFConvertEventArgs > (office_Finish);
word.Open();
IOfficeToPDF excel = new ExcelToPDF();
excel.Error += new EventHandler < PDFConvertEventArgs > (office_Error);
excel.Finish += new EventHandler < PDFConvertEventArgs > (office_Finish);
excel.Open();
word.SaveAsPDF(sourceFilePath, exportFilePath);
excel.SaveAsPDF(sourceFilePath, exportFilePath);
excel.Close();
word.Close();
代码很简单,忽忙写的,所以就不注释了。另外程序在运行的尽量不要直接关闭(所以我屏掉了关闭等按钮),否则像wordDocumnet这个没正常关闭,下次再转换的时候会引起一些不必要的麻烦。(基本是RPC不响应,估计频率调COM接口的问题,还有就是WORD不停弹只读副本的原因等等)
看下程序的运行效果:
时间关系简单封装后,做了100份批传测试没啥大问题。
现将源码发布出来,WordDocument关闭异常问题还没解决,有知道原因的可以指点或修正回发我一份。