phpword文檔 table轉(zhuǎn)word表格

phpword 文檔生成
中文文檔
github

通過html的table生成world表格代碼
在thinkphp index 控制器中做的例子
不兼容樣式 只能簡單的生成表格
可能還有其他形式的表格不兼容(慎重使用)

namespace app\index\controller;

use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\PhpWord;
use think\Db;

class Index
{
    public function index()
    {
        $phpWord = new PhpWord();
        $section = $phpWord->addSection();
        header("Content-type:text/html;charset=utf-8");
        $phpWord->addTableStyle(
            'myTable',
            [
                'borderSize' => '1',
                'borderColor' => '000000',
            ]
        );
        $txt = array (
            "表格1\n",
            '<table><tr><td rowspan="4">1-1</td><td>1-2</td><td>1-3</td><td>1-4</td><td>1-5</td><td rowspan="4">1-6</td></tr><tr><td>2-2</td><td colspan="2" rowspan="2">2-3</td><td>2-4</td></tr><tr><td>3-2</td><td>3-5</td></tr><tr><td>4-2</td><td>4-3</td><td>4-4</td><td>4-5</td></tr></table>',
            "表格2\n",
            '<table><tr><td>1-1</td><td>1-2</td><td>1-3</td><td>1-4</td><td>1-5</td></tr><tr><td>2-1</td><td>2-2</td><td>2-3</td><td>2-4</td><td>2-5</td></tr><tr><td>3-1</td><td>3-2</td><td>3-3</td><td>3-4</td><td>3-5</td></tr><tr><td>4-1</td><td>4-2</td><td>4-3</td><td>4-4</td><td>4-5</td></tr></table>',
            "表格3\n",
            '<table><tr><td colspan="2" rowspan="2">1-1</td><td>1-3</td><td>1-4</td></tr><tr><td rowspan="2">2-3</td><td>2-4</td></tr><tr><td>3-1</td><td>3-2</td><td rowspan="2">3-4</td></tr><tr><td colspan="2">4-1</td><td>4-2</td></tr></table>',
            "表格4\n",
            '<table><tr><td rowspan="3" colspan="2">1-1</td><td colspan="3">1-3</td><td>1-6</td><td rowspan="3">1-7</td><td colspan="2" rowspan="5">1-8</td><td>1-9</td></tr><tr><td>2-3</td><td>2-4</td><td>2-5</td><td>2-6</td><td>2-9</td></tr><tr><td colspan="2">3-3</td><td colspan="2" rowspan="2">3-5</td><td rowspan="2">3-9</td></tr><tr><td>4-1</td><td>4-2</td><td>4-3</td><td>4-4</td><td>4-7</td></tr><tr><td colspan="2">5-1</td><td colspan="2">5-3</td><td colspan="2">5-5</td><td>5-7</td><td>5-9</td></tr></table>',
            "表格5\n",
            '<table><tr><td colspan="2">1-1</td><td>1-3</td><td colspan="3">1-4</td><td>1-7</td><td>1-8</td><td>1-9</td><td>1-10</td></tr><tr><td rowspan="3">2-1</td><td rowspan="2">2-2</td><td colspan="8">2-3</td></tr><tr><td rowspan="2">3-3</td><td rowspan="3">3-4</td><td>3-5</td><td>3-6</td><td rowspan="4">3-7</td><td>3-8</td><td colspan="2" rowspan="3">3-9</td></tr><tr><td rowspan="3">4-2</td><td rowspan="2" colspan="2">4-5</td><td>4-8</td></tr><tr><td>5-1</td><td>5-3</td><td>5-8</td></tr><tr><td>6-1</td><td>6-3</td><td>6-4</td><td>6-5</td><td>6-6</td><td>6-8</td><td>6-9</td><td>6-10</td></tr></table>'
        );


        for ($i=0;$i<count($txt);$i++)
        {

            if (preg_match('/<table[\s\S]*>/',$txt[$i]))
            {
                $this->createTable($section,$txt[$i]);
            }else{
                $section->addText($txt[$i]);
            }

        }

        $objWriter = IOFactory::createWriter($phpWord,'Word2007');

        $file = '測(cè)試文檔.docx';
        header("Content-Description: File Transfer");
        header('Content-Disposition: attachment; filename="' . $file . '"');
        header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
        header('Content-Transfer-Encoding: binary');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Expires: 0');

        $objWriter->save('PHP://output');
    }


    /**
     *
     * 具體思路:
     * 通過 rowspan 與 colspan 還原基本表格
     * 記錄 rowspan 的每行坐標(biāo) 組合colspan 進(jìn)行 每次一行生成表格
     *
     * @param \PhpOffice\PhpWord\Element\Section $section
     * @param string $strTable
     */
    private function createTable($section,$strTable)
    {
        //查找所有的table標(biāo)簽
        preg_match_all("/<table[\s\S]*>[\s\S]*<\/table>/U",$strTable,$tables);

        for ($tableI=0;$tableI<count($tables[0]);$tableI++)
        {
            //設(shè)置table樣式
            $table = $section->addTable('myTable');
            //尋找行
            preg_match_all("/<tr>[\s\S]*<\/tr>/U",$tables[0][$tableI],$tr);

            //合并列的數(shù)據(jù)
            $tableRowSpan = [];
            for ($r = 0;$r < count($tr[0]);$r ++)
            {
                $table->addRow(); //增加一行
                //尋找列
                preg_match_all("/<td[\s\S]*>([\s\S]*)<\/td>/U",$tr[0][$r],$td);
                //找出所有的colspan的數(shù)量  通過此數(shù)量可計(jì)算出一共有多少列
                preg_match_all('/colspan="(\d{1,})"/U',$tr[0][$r],$colspanNumber);
                //只取一次有多少列
                if (!isset($tdTotal))
                {
                    //td總數(shù)量 = 匹配到的數(shù)量 + colspan的總和 - colspan的總數(shù)
                    $tdTotal = count($td[0]) + array_sum($colspanNumber[1]) - count($colspanNumber[1]);
                }
                //將每一個(gè)rowspan記錄到數(shù)組中  如果同時(shí)含有 colspan 進(jìn)行特俗處理
                $tdAddUp= 0;
                for ($j=0;$j<$tdTotal;$j++){
                    //驗(yàn)證此處是否已經(jīng)記錄過  分為兩種情況 第一次出現(xiàn)rowspan時(shí)可以正確獲取到
                    //第二次 以后 由于上面有rowspan 則第一位的td并不是應(yīng)當(dāng)記錄的 坐標(biāo)
                    //如果曾經(jīng)已記錄過忽略就可以了
                    if (!isset($tableRowSpan[$j]))
                    {
                        //查看是否含有colspan屬性  并獲得 colspan 的 數(shù)量
                        $isColspan = preg_match('/colspan="(\d{1,})"/',$td[0][$tdAddUp],$colspanCount);
                        //驗(yàn)證是否含有 rowspan 屬性并獲得數(shù)量
                        if (preg_match('/rowspan="(\d{1,})"/',$td[0][$tdAddUp],$number))
                        {
                            //取出 rowspan 屬性的內(nèi)容
                            preg_match('/<td[\s\S]*>([\s\S]*)<\/td>/',$td[0][$tdAddUp],$value);
                            $tableRowSpan[$j] = [
                                'rowCount' => $number[1], //記錄rowspan的數(shù)量
                                'total' => $number[1], //記錄rowspan的總數(shù)  通過它可以驗(yàn)證是否為第一次添加
                                'colsCount' => isset($colspanCount[1])?$colspanCount[1]:0, //記錄colspan的數(shù)量 作為是否添加 列的條件
                                'value' => $value[1]
                            ];
                            // 如果同時(shí)含有 rowspan 與 colspan 兩個(gè)屬性 則向后補(bǔ)位空數(shù)組,數(shù)量為colspan的值
                            if ($isColspan)
                            {
                                for ($colcI = 0; $colcI < $colspanCount[1] - 1;$colcI++){
                                    $tableRowSpan[++$j] = [];
                                }
                            }
                        }else{
                            //只有colspan屬性 $j 的增量為 colspan 的值減1
                            if ($isColspan){
                                $j+=$colspanCount[1] - 1;
                            }
                        }
                        //每次檢查后 需要增加1
                        $tdAddUp++;
                    }
                }

                //所有有rowspan屬性的td已被記錄在  $tableRowSpan 變量中 所以在要在匹配到的 td中 刪除 鲜棠,否則會(huì)被重復(fù)添加
                for ($delI = count($td[0]) - 1;$delI >= 0; $delI --)
                {
                    $isRowSpan = preg_match('/rowspan="(\d{1,})"/U',$td[0][$delI]);
                    if ($isRowSpan){
                        array_splice($td[0],$delI,1);
                        array_splice($td[1],$delI,1);
                    }
                }
                //普通td的下標(biāo)記錄
                $tdCount = 0;
                //以變量$c為橫向坐標(biāo)系 也就是html中table的tr為一行 開始生成表格
                for ($c=0;$c<$tdTotal;)
                {
                    // $c的增量 由于存在colspan屬性的td $c 的增量不是 1 需要根據(jù)colspan的數(shù)量增加 默認(rèn)為 1
                    $addUp = 1;
                    //首選驗(yàn)證是否在 $tableRowSpan 記錄了此行td的 rowspan 的屬性
                    if (isset($tableRowSpan[$c]))
                    {
                        //由于 td 同時(shí) 含有 rowspan 與 colspan 屬性時(shí) 會(huì)在 $tableRowSpan 使用空數(shù)組進(jìn)行補(bǔ)位
                        //所以需要在驗(yàn)證是否為補(bǔ)位的數(shù)據(jù)
                        if (isset($tableRowSpan[$c]['rowCount']) && $tableRowSpan[$c]['rowCount'] > 0)
                        {
                            //記錄行數(shù)與總行數(shù)  不匹配則使用 continue 屬性  反之 則使用 restart
                            $vMerge = $tableRowSpan[$c]['rowCount'] == $tableRowSpan[$c]['total']?'restart':'continue';
                            //增加一個(gè)td并且設(shè)置屬性 如果 $vMerge 為 restart 說明是第一次添加  加入 td的值
                            //并將 colspan的屬性 加入其中
                            $table->addCell(2000,['vMerge' => $vMerge,'gridSpan' => $tableRowSpan[$c]['colsCount']])->addText($vMerge == 'restart'?$tableRowSpan[$c]['value']:'');
                            //每增加一個(gè)進(jìn)行減少操作
                            $tableRowSpan[$c]['rowCount']--;
                            //如果此列所有的 rowspan屬性增加完畢 則 將此記錄移除
                            if ($tableRowSpan[$c]['rowCount'] == 0) unset($tableRowSpan[$c]);
                        }else{
                            //如果為補(bǔ)位的數(shù)據(jù) 還需要驗(yàn)證前 一個(gè) rowspan屬性是否增加完畢 增加完畢則移除
                            if (empty($tableRowSpan[$c]) && !isset($tableRowSpan[$c - 1])) unset($tableRowSpan[$c]);
                        }
                    }else{//html中table中正常的 td 或只含有 colspan 的 td

                        //獲取td中包含的值
                        preg_match('/<td[\s\S]*>([\s\S]*)<\/td>/',$td[0][$tdCount],$tdValue);
                        $gridSpan = 0;  //colspan的默認(rèn)值
                        //獲得td 中colspan的值
                        if (preg_match('/colspan="(\d{1,})"/',$td[0][$tdCount],$number))
                        {
                            //$addUp是$c 的增量并且他的默認(rèn)增量是 1
                            //$gridSpan 是 td 的行合并數(shù)量
                            //因此兩個(gè) 參數(shù)的值都以 $number[1] 的數(shù)量變化
                            $addUp = $gridSpan = $number[1];
                        }
                        //增加一個(gè)td 并且填入值
                        $table->addCell(2000,['gridSpan' => $gridSpan])->addText($tdValue[1]);
                        //由于已將含有 rowspan 屬性的td去除,此處每增加一個(gè)td 就需要增加 1
                        $tdCount++;
                    }
                    //累計(jì)行的增量
                    $c+=$addUp;

                }
            }
            //表格結(jié)束后增加換行
            $section->addText("\n");
        }
    }
}

原創(chuàng)文章,禁止任何形式的轉(zhuǎn)載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載别渔,如需轉(zhuǎn)載請(qǐng)通過簡信或評(píng)論聯(lián)系作者著摔。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市损同,隨后出現(xiàn)的幾起案子遏考,更是在濱河造成了極大的恐慌慈鸠,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灌具,死亡現(xiàn)場(chǎng)離奇詭異青团,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)咖楣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門督笆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人截歉,你說我怎么就攤上這事胖腾。” “怎么了瘪松?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锨阿。 經(jīng)常有香客問我宵睦,道長,這世上最難降的妖魔是什么墅诡? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任壳嚎,我火速辦了婚禮,結(jié)果婚禮上末早,老公的妹妹穿的比我還像新娘烟馅。我一直安慰自己,他們只是感情好然磷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布郑趁。 她就那樣靜靜地躺著,像睡著了一般姿搜。 火紅的嫁衣襯著肌膚如雪寡润。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天舅柜,我揣著相機(jī)與錄音梭纹,去河邊找鬼。 笑死致份,一個(gè)胖子當(dāng)著我的面吹牛变抽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼绍载,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼诡宗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起逛钻,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤僚焦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后曙痘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芳悲,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年边坤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了名扛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茧痒,死狀恐怖肮韧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旺订,我是刑警寧澤弄企,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站区拳,受9級(jí)特大地震影響拘领,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜樱调,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一约素、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笆凌,春花似錦圣猎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晦闰,卻和暖如春放祟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背呻右。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國打工跪妥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人声滥。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓眉撵,卻偏偏與公主長得像侦香,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子纽疟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容