PHP生成word的三种方式

摘要:

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

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

btw:好像在博客园发表博客只要是标题带PHP的貌似点击量都不是很高(哥哥我标题还是带上PHP了),不知道为什么,估计博客园上net技术大牛比较多吧,如果把java,.net,php比作程序员的女友,那么java是Oracle门下的大家闺秀,.net微软旗下的名门望族,PHP则是草根门下的山村野姑,这让我等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

使用官方实例:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<?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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

/**

 * 根据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类中了。

  • 使用方法:远程调用


1

2

3

4

5

6

7

8

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文档。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

<?php

/***********************************************************************

Class:        Mht File Maker

Version:      1.2 beta

Date:         02/11/2007

Author:       Wudi <[email protected]>

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文档内容利用

代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

<?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"

xmlns="http://www.w3.org/TR/REC-html40">‘;

}

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);

}

}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

$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技术博客分享网站

  <img src="http://www.php10086.com/wp-content/themes/WPortal-Blue/images/logo.gif">

  </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代码

看一下效果:

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

打个小广告:据说每个程序员都应该挖一口自己的井,希望各位支持我的"井":PHP10086博客网(PHP淮北):http://www.php10086.com

Technorati 标签: PHP,生成word文档,批量生成word,PHP10086博客分享,PHP淮北

时间: 2024-10-10 23:07:05

PHP生成word的三种方式的相关文章

EF Codefirst生成数据库的三种方式

1.写在前头 不是什么高大上的东西,也不是完全原创的,大多是自己学习时去网上查的各种资料.只是发现学东西还是要写点东西,不然前边写着后边忘了,花的时间都浪费了,写写增加记忆吧.如果是有人刚开始学看到这个相信会有帮助的. 2.开搞 前几天写了篇小文章搞了下EF生成数据库时获取连接字符串的方式,发布时不小心勾选了发布到首页,秒秒钟就被管理员给撤销了( ⊙ o ⊙ ),确实太低端了,博客园锅锅撤销也是可以理解的,废话不多说,今天继续搞一搞获取完连接字符串后EF怎么生成数据库呢,有哪些方式呢? 第一种:

spring生成EntityManagerFactory的三种方式

1.LocalEntityManagerFactoryBean只是简单环境中使用.它使用JPA PersistenceProvider自动检测机制( according to JPA's Java SE bootstrapping ),并且大多数情况下,你只能定义一下persistence unit name 例如: <beans><bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityM

小蚂蚁学习页面静态化(2)——更新生成纯静态化页面的三种方式

更新生成纯静态化页面的三种方式:1.按照时间间隔更新.2.手动更新.3.定时更新(需要系统配合). 1. 按照时间间隔更新. 当用户第一次访问这个页面的时候,程序自动判断,该静态文件是否存在,并且该文件是否还在有效时间内,如果该文件未超出了有效时间,用户访问的是已经生成的静态文件.如果超出了有效时间,用户得到的是动态输出的内容,同时重新生成静态文件.稍微修改一下昨天的代码为例: <?php //首先判断是否有静态文件,并且文件的最新修改时间到现在是否大于20秒 if(is_file('./tex

三种方式都能生成同样的列表

d = {'x': 'A', 'y': 'B', 'z': 'C'} # 下方的三种方式都能生成同样的列表 a = [] for k, v in d.items(): # 直接生成键和值,再添加到空列表中 a.append(str(k + '=' + v)) print(a) b = [] for k1 in d: # 先生成键,再找键对应的值,再添加到空列表中 b.append(str(k1 + '=' + d[k1])) print(b) c = ([k + '=' + v for k, v

JVM 在遇到OOM(OutOfMemoryError)时生成Dump文件的三种方式

JVM 在遇到OOM(OutOfMemoryError)时生成Dump文件的三种方式,以及如何使用Eclips Memory Analyzer(MAT)插件进行堆内存分析. 方法一: jmap -dump:format=b,file=文件名 [pid] 例如: jmap -dump:format=b,file=/usr/local/base/02.hprof 12942 方法二: 让JVM在遇到OOM(OutOfMemoryError)时生成Dump文件,需要配置一些信息 -XX:+HeapDu

0166 DOM 之 节点操作: 删除节点,删除留言案例,复制(克隆)节点,动态生成表格案例,创建元素的三种方式,innerHTML和createElement效率对比

1.1.1 删除节点 node.removeChild(child) // 此处的node指 父节点 node.removeChild() 方法: 从 node节点中删除一个子节点,返回删除的节点. <button>删除</button> <ul> <li>熊大</li> <li>熊二</li> <li>光头强</li> </ul> <script> // 1.获取元素 va

【整理】Linux下中文检索引擎coreseek4安装,以及PHP使用sphinx的三种方式(sphinxapi,sphinx的php扩展,SphinxSe作为mysql存储引擎)

一,软件准备 coreseek4.1 (包含coreseek测试版和mmseg最新版本,以及测试数据包[内置中文分词与搜索.单字切分.mysql数据源.python数据源.RT实时索引等测试配置]) Mysql源码包 (必须选择与你已安装mysql的版本一致) 为了避免安装中出现依赖包缺失,你需要打一句鸡血: yum install make gcc g++ gcc-c++ libtool autoconf automake imake mysql-devel libxml2-devel exp

【Eclipse使用方法】Eclipse中安装插件的三种方式

Eclipse也用了很久,但是都没有怎么去研究过怎么安装插件,今天正好在自己新买的本上试了一下.现在将心得写下,以供参考.目前安装Eclipse插件主要有以下三种方式: 在线安装: 以TestNG的安装为例来阐述其安装过程. 第一步:点击菜单栏中“Help”菜单,在下拉列中选择“Install New Software...”.此时会弹出“install”的安装框. 第二步:在弹出的“install”框,选择之前已经建立好的site,如果没有建立好,则可以点击“Add”按钮,弹出一个添加site

tomcat发布web项目的三种方式

tomcat发布web项目的三种方式 方式一: 配置tomcat 安装目录下的conf/server.xml <Host name="loaclhost">标签里面添加 <Context path="/aa" docBase="C:\AA\BB" /> 即/aa这个虚拟路径映射到了C:\AA\BB目录下,修改完servler.xml需要重启tomcat服务器 方式二: 在conf目录下创建Catalina目录,在此目录下新