[置顶] PHP生成word的三种方式

摘要:

最近工作遇到关于生成word的问题

现在总结一下生成word的三种方法。

btw:好像在博客园发表博客只要是标题带PHP的貌似点击量都不是很高(哥哥我标题还是带上PHP了),不知道为什么,估计博客园以net技术为主吧,这让我等PHP草民情何以堪情何以堪。。牢骚发完了,正式写博客吧

正文

PHP生成word原理

  1. 利用windows下面的 com组件
  2. 利用PHP将内容写入doc文件之中

具体实现:

  • 利用windows下面的 com组件

原理:com作为PHP的一个扩展类,安装过office的服务器会自动调用word.application的com,可以自动生成文档,PHP官方文档手册:http://www.php.net/manual/en/class.com.php

使用官方实例:

点击查看代码:
<pre><?php
// starting word
$word = new COM( "word.application" ) or die ( "Unable to instantiate Word" );
echo "Loaded Word, version {$word->Version}\n" ;
 
//bring it to front
$word ->Visible = 1;
 
//open an empty document
$word ->Documents->Add();
 
//do some weird stuff
$word ->Selection->TypeText( "This is a test..." );
$word ->Documents[1]->SaveAs( "Useless test.doc" );
 
//closing word
$word ->Quit();
 
//free the object
$word = null;
?>

个人建议:com实例后的方法都需要查找官方文档才知道什么意思,编辑器没有代码提示,非常不方便,另外这个效率也不是很高,不推荐使用

利用PHP将内容写入doc文件之中

这个方法又可以分为两种方法

  • 生成mht格式(和HTML很相似)写入word
  • 纯HTML格式写入word
  1. 生成mht格式(和HTML很相似)写入word

这个方法主要参看:http://www.cnitblog.com/CoffeeCat/archive/2008/08/07/47753.html

点击查看代码:
/**
  * 根据HTML代码获取word文档内容
  * 创建一个本质为mht的文档,该函数会分析文件内容并从远程下载页面中的图片资源
  * 该函数依赖于类MhtFileMaker
  * 该函数会分析img标签,提取src的属性值。但是,src的属性值必须被引号包围,否则不能提取
  *
  * @param string $content HTML内容
  * @param string $absolutePath 网页的绝对路径。如果HTML内容里的图片路径为相对路径,那么就需要填写这个参数,来让该函数自动填补成绝对路径。这个参数最后需要以/结束
  * @param bool $isEraseLink 是否去掉HTML内容中的链接
  */
function getWordDocument( $content , $absolutePath = "" , $isEraseLink = true )
{
     $mht = new MhtFileMaker();
     if ( $isEraseLink )
         $content = preg_replace( '/<a\s*.*?\s*>(\s*.*?\s*)<\/a>/i' , '$1' , $content );   //去掉链接
 
     $images = array ();
     $files = array ();
     $matches = array ();
     //这个算法要求src后的属性值必须使用引号括起来
     if ( preg_match_all( '/<img[.\n]*?src\s*?=\s*?[\"\'](.*?)[\"\'](.*?)\/>/i' , $content , $matches ) )
     {
         $arrPath = $matches [1];
         for ( $i =0; $i < count ( $arrPath ); $i ++)
         {
             $path = $arrPath [ $i ];
             $imgPath = trim( $path );
             if ( $imgPath != "" )
             {
                 $files [] = $imgPath ;
                 if ( substr ( $imgPath ,0,7) == 'http://' )
                 {
                     //绝对链接,不加前缀
                 }
                 else
                 {
                     $imgPath = $absolutePath . $imgPath ;
                 }
                 $images [] = $imgPath ;
             }
         }
     }
     $mht ->AddContents( "tmp.html" , $mht ->GetMimeType( "tmp.html" ), $content );
 
     for ( $i =0; $i < count ( $images ); $i ++)
     {
         $image = $images [ $i ];
         if ( @ fopen ( $image , 'r' ) )
         {
             $imgcontent = @ file_get_contents ( $image );
             if ( $content )
                 $mht ->AddContents( $files [ $i ], $mht ->GetMimeType( $image ), $imgcontent );
         }
         else
         {
             echo "file:" . $image . " not exist!<br />" ;
         }
     }
 
     return $mht ->GetFile();
}

这个函数的主要功能其实就是分析HTML代码中的所有图片地址,并且依次下载下来。获取到了图片的内容以后,调用MhtFileMaker类,将图片添加到mht文件中。具体的添加细节,封装在MhtFileMaker类中了。

  • 使用方法:远程调用

url= http://www.***.com;$content = file_get_contents($url);$fileContent = getWordDocument($content,"http://www.yoursite.com/Music/etc/");$fp = fopen("test.doc", 'w');fwrite($fp, $fileContent);fclose($fp);

其中,$content变量应该是HTML源代码,后面的链接应该是能填补HTML代码中图片相对路径的URL地址

  • 本地生成调用:

header(“Cache-Control: no-cache, must-revalidate”);

header(“Pragma: no-cache”);

$wordStr = ‘PHP淮北的个人网站–PHP10086.com’;

$fileContent = getWordDocument($wordStr);

$fileName = iconv(“utf-8″, “GBK”, ‘PHP淮北’ . ‘_’. $intro . ‘_’ . rand(100, 999));
header(“Content-Type: application/doc”);

header(“Content-Disposition: attachment; filename=” . $fileName . “.doc”);

echo $fileContent;
注意,在使用这个函数之前,您需要先包含类MhtFileMaker,这个类可以帮助我们生成Mht文档。

点击查看代码:
<?php
/***********************************************************************
Class:        Mht File Maker
Version:      1.2 beta
Date:         02/11/2007
Author:       Wudi <wudicgi@yahoo.de>
Description:  The class can make .mht file.
***********************************************************************/
 
class MhtFileMaker{
     var $config = array ();
     var $headers = array ();
     var $headers_exists = array ();
     var $files = array ();
     var $boundary ;
     var $dir_base ;
     var $page_first ;
 
     function MhtFile( $config = array ()){
 
     }
 
     function SetHeader( $header ){
         $this ->headers[] = $header ;
         $key = strtolower ( substr ( $header , 0, strpos ( $header , ':' )));
         $this ->headers_exists[ $key ] = TRUE;
     }
 
     function SetFrom( $from ){
         $this ->SetHeader( "From: $from" );
     }
 
     function SetSubject( $subject ){
         $this ->SetHeader( "Subject: $subject" );
     }
 
     function SetDate( $date = NULL, $istimestamp = FALSE){
         if ( $date == NULL) {
             $date = time();
         }
         if ( $istimestamp == TRUE) {
             $date = date ( 'D, d M Y H:i:s O' , $date );
         }
         $this ->SetHeader( "Date: $date" );
     }
 
     function SetBoundary( $boundary = NULL){
         if ( $boundary == NULL) {
             $this ->boundary = '--' . strtoupper (md5(mt_rand())) . '_MULTIPART_MIXED' ;
         } else {
             $this ->boundary = $boundary ;
         }
     }
 
     function SetBaseDir( $dir ){
         $this ->dir_base = str_replace ( "\\" , "/" , realpath ( $dir ));
     }
 
     function SetFirstPage( $filename ){
         $this ->page_first = str_replace ( "\\" , "/" , realpath ( "{$this->dir_base}/$filename" ));
     }
 
     function AutoAddFiles(){
         if (!isset( $this ->page_first)) {
             exit ( 'Not set the first page.' );
         }
         $filepath = str_replace ( $this ->dir_base, '' , $this ->page_first);
         $filepath = 'http://mhtfile' . $filepath ;
         $this ->AddFile( $this ->page_first, $filepath , NULL);
         $this ->AddDir( $this ->dir_base);
     }
 
     function AddDir( $dir ){
         $handle_dir = opendir( $dir );
         while ( $filename = readdir( $handle_dir )) {
             if (( $filename != '.' ) && ( $filename != '..' ) && ( "$dir/$filename" != $this ->page_first)) {
                 if ( is_dir ( "$dir/$filename" )) {
                     $this ->AddDir( "$dir/$filename" );
                 } elseif ( is_file ( "$dir/$filename" )) {
                     $filepath = str_replace ( $this ->dir_base, '' , "$dir/$filename" );
                     $filepath = 'http://mhtfile' . $filepath ;
                     $this ->AddFile( "$dir/$filename" , $filepath , NULL);
                 }
             }
         }
         closedir ( $handle_dir );
     }
 
     function AddFile( $filename , $filepath = NULL, $encoding = NULL){
         if ( $filepath == NULL) {
             $filepath = $filename ;
         }
         $mimetype = $this ->GetMimeType( $filename );
         $filecont = file_get_contents ( $filename );
         $this ->AddContents( $filepath , $mimetype , $filecont , $encoding );
     }
 
     function AddContents( $filepath , $mimetype , $filecont , $encoding = NULL){
         if ( $encoding == NULL) {
             $filecont = chunk_split ( base64_encode ( $filecont ), 76);
             $encoding = 'base64' ;
         }
         $this ->files[] = array ( 'filepath' => $filepath ,
                                'mimetype' => $mimetype ,
                                'filecont' => $filecont ,
                                'encoding' => $encoding );
     }
 
     function CheckHeaders(){
         if (! array_key_exists ( 'date' , $this ->headers_exists)) {
             $this ->SetDate(NULL, TRUE);
         }
         if ( $this ->boundary == NULL) {
             $this ->SetBoundary();
         }
     }
 
     function CheckFiles(){
         if ( count ( $this ->files) == 0) {
             return FALSE;
         } else {
             return TRUE;
         }
     }
 
     function GetFile(){
         $this ->CheckHeaders();
         if (! $this ->CheckFiles()) {
             exit ( 'No file was added.' );
         }
         $contents = implode( "\r\n" , $this ->headers);
         $contents .= "\r\n" ;
         $contents .= "MIME-Version: 1.0\r\n" ;
         $contents .= "Content-Type: multipart/related;\r\n" ;
         $contents .= "\tboundary=\"{$this->boundary}\";\r\n" ;
         $contents .= "\ttype=\"" . $this ->files[0][ 'mimetype' ] . "\"\r\n" ;
         $contents .= "X-MimeOLE: Produced By Mht File Maker v1.0 beta\r\n" ;
         $contents .= "\r\n" ;
         $contents .= "This is a multi-part message in MIME format.\r\n" ;
         $contents .= "\r\n" ;
         foreach ( $this ->files as $file ) {
             $contents .= "--{$this->boundary}\r\n" ;
             $contents .= "Content-Type: $file[mimetype]\r\n" ;
             $contents .= "Content-Transfer-Encoding: $file[encoding]\r\n" ;
             $contents .= "Content-Location: $file[filepath]\r\n" ;
             $contents .= "\r\n" ;
             $contents .= $file [ 'filecont' ];
             $contents .= "\r\n" ;
         }
         $contents .= "--{$this->boundary}--\r\n" ;
         return $contents ;
     }
 
     function MakeFile( $filename ){
         $contents = $this ->GetFile();
         $fp = fopen ( $filename , 'w' );
         fwrite( $fp , $contents );
         fclose( $fp );
     }
 
     function GetMimeType( $filename ){
         $pathinfo = pathinfo ( $filename );
         switch ( $pathinfo [ 'extension' ]) {
             case 'htm' : $mimetype = 'text/html' ; break ;
             case 'html' : $mimetype = 'text/html' ; break ;
             case 'txt' : $mimetype = 'text/plain' ; break ;
             case 'cgi' : $mimetype = 'text/plain' ; break ;
             case 'php' : $mimetype = 'text/plain' ; break ;
             case 'css' : $mimetype = 'text/css' ; break ;
             case 'jpg' : $mimetype = 'image/jpeg' ; break ;
             case 'jpeg' : $mimetype = 'image/jpeg' ; break ;
             case 'jpe' : $mimetype = 'image/jpeg' ; break ;
             case 'gif' : $mimetype = 'image/gif' ; break ;
             case 'png' : $mimetype = 'image/png' ; break ;
             default : $mimetype = 'application/octet-stream' ; break ;
         }
         return $mimetype ;
     }
}
?>

点评:这种方法的缺点是不支持批量生成,因为一个页面只能有一个header,(无论远程使用还是本地生成声明header页面只能输出一个header),即使你循环生成,结果还是只有一个word生成(当然你可以修改上面的方式来实现)

2.纯HTML格式写入word

原理:

利用ob_start把html页面先存储起来(解决一下页面多个header问题,可以批量生成),然后在写入doc文档内容利用

代码:

点击查看代码:
<?php
class word
{
function start()
{
ob_start();
echo '<html xmlns:o= "urn:schemas-microsoft-com:office:office"
xmlns:w= "urn:schemas-microsoft-com:office:word"
}
function save( $path )
{
 
echo "</html>" ;
$data = ob_get_contents();
ob_end_clean();
 
$this ->wirtefile ( $path , $data );
}
 
function wirtefile ( $fn , $data )
{
$fp = fopen ( $fn , "wb" );
fwrite( $fp , $data );
fclose( $fp );
}
}
$html = '
<table width=600 cellpadding= "6" cellspacing= "1" bgcolor= "#336699" >
<tr bgcolor= "White" >
   <td>PHP10086</td>
   <td><a href= "http://www.php10086.com" target= "_blank" >http://www.php10086.com</a></td>
</tr>
<tr bgcolor= "red" >
   <td>PHP10086</td>
   <td><a href= "http://www.php10086.com" target= "_blank" >http://www.php10086.com</a></td>
</tr>
<tr bgcolor= "White" >
   <td colspan=2 >
   PHP10086<br>
   最靠谱的PHP技术博客分享网站
   </td>
</tr>
</table>
';
 
//批量生成
for ( $i =1; $i <=3; $i ++){
     $word = new word();
     $word ->start();
     //$html = "aaa".$i;
     $wordname = 'PHP淮北的个人网站--PHP10086.com' . $i . ".doc" ;
     echo $html ;
     $word ->save( $wordname );
     ob_flush(); //每次执行前刷新缓存
     flush ();
}

个人点评:这种方法效果最好,原因有两个:

第一代码比较简洁,很容易理解,第二种支持批量生成word且下载(这个很重要)

第三支持完整的html代码

看一下效果:

QQ截图20111129100019

生成了三个word文档:并且内容支持完整的html代码显示,第三种方法强烈推荐


知识共享许可协议本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名:PHP10086博客网(PHP淮北):http://www.php10086.com,也可以邮件与我联系。据说每个程序员都应该挖一口自己的井,希望各位支持我的"井":PHP10086博客网(PHP淮北):http://www.php10086.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值