PHPExcel使用体会

因为毕设导师智能分配系统的需要,系负责人在管理学生和导师时,希望可以使用Excel批量导入学生和导师的信息,学长的报课系统使用的是PHPExcel的类库,于是我也抽空花了2天的时间学习了PHPExcel的最基础的导入导出功能的实现,总结了自己的使用心得和一些常用的使用方法

一、类库的引入

  • PHP我使用的是ThinkPHP5的框架,所以以TP5框架为例,这是项目的PHPExcel的目录结构:

      require_once 'extend/reader.php'; //Excel读取
    require_once 'extend/PHPExcel_1.8.0_doc/Classes/PHPExcel.php'; //Excel导入导出

二、Excel导入

  • 调用Reader

      require_once 'extend/reader.php';
  • 创建Reader

      $data = new \Spreadsheet_Excel_Reader();
  • 设置在页面中输出的编码方式

      $data->setOutputEncoding('utf-8');
  • 读取上传到当前目录下实际路径为$realPath的文件

      $data->read($realPath);
  • 设置PHP的报错级别并返回当前的级别

      error_reporting(E_ALL ^ E_NOTICE);
    或error_reporting(E_ALL & ~E_NOTICE);

    起初并不是很懂这句代码的含义,经过查找资料后发现,在不同的PHP版本中,原本可能在低版本的PHP中运行正常的代码,在较高版本的PHP中运行可能就会出现报错,为了使程序能够正常运行,需要在程序开头加上这句代码;error_reporting()设置PHP的报错级别并返回当前的级别,以下是网络上查找的一些资料,在做Excel导出的时候出现了一个bug很久都没有解决,在TP5的交流群询问之后被某位大佬问到:“你知道PHP的报错等级吗?你知道什么是未定义变量吗?”查看错误报告之后发现确实出现了下面的第7条错误:

    1. 错误报告是按位的。或者将数字加起来得到想要的错误报告等级
    2. E_ALL - 所有的错误和警告
    3. E_ERROR - 致命性运行时错
    4. E_WARNING - 运行时警告(非致命性错)
    5. E_PARSE - 编译时解析错误
    6. E_NOTICE - 运行时提醒
    7. 可能是有意的行为造成的(如:基于未初始化的变量自动初始化为一个空字符串的事实而使用一个未初始化的变量)
    8. E_CORE_ERROR - 发生于PHP启动时初始化过程中的致命错误
    9. E_CORE_WARNING - 发生于PHP启动时初始化过程中的警告(非致命性错)
    10. E_COMPILE_ERROR - 编译时致命性错
    11. E_COMPILE_WARNING - 编译时警告(非致命性错)
    12. E_USER_ERROR - 用户产生的出错消息
    13. E_USER_WARNING - 用户产生的警告消息
    14. E_USER_NOTICE - 用户产生的提醒消息
  • 循环处理Excel表格里的每一行数据并插入数据库

      for ($i=3; $i <=$data->sheets[0]['numRows'] ; $i++) {
    $insert = [];
    $insert['grade'] = $data->sheets[0]['cells'][$i][1];
    $insert['serialNum'] = $data->sheets[0]['cells'][$i][2];
    $insert['password'] = $data->sheets[0]['cells'][$i][2];
    $insert['name'] = $data->sheets[0]['cells'][$i][3];
    $insert['gender'] = $data->sheets[0]['cells'][$i][4];
    $insert['college'] = $data->sheets[0]['cells'][$i][5];
    $insert['department'] = $data->sheets[0]['cells'][$i][6];
    $insert['gpa'] = $data->sheets[0]['cells'][$i][7];
    $insert['rank'] = $data->sheets[0]['cells'][$i][8];
    $insert['telephone'] = $data->sheets[0]['cells'][$i][9];
    $insert['chosen'] = 0;
    //插入数据库中
    Db('user_student_'.$insert['grade'])->insert($insert);
    }

三、Excel导出

  • 引入PHPExcel.php

      require_once 'extend/PHPExcel_1.8.0_doc/Classes/PHPExcel.php';
  • 创建一个新的Excel文件

      $excel = new \PHPExcel();
  • 先进行一般的Excel格式的处理

      $excel->getActiveSheet()->getColumnDimension('A')->setWidth(9);  //手动设置单元格宽度
    $excel->getActiveSheet()->getColumnDimension('B')->setWidth(30);
    $excel->getActiveSheet()->getColumnDimension('C')->setWidth(9); $excel->getActiveSheet()->getRowDimension(2)->setRowHeight(35); //设置某一行高度 $excel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); //设置水平居中
    $excel->getActiveSheet()->getStyle('A1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); //设置水平居中 $excel->getActiveSheet()->getStyle('G')->getNumberFormat()->setFormatCode('000000000'); //设置文本格式 //设置边框和水平垂直居中,PHPExcel貌似没有对所有的单元格进行统一处理的功能,所以我定义里一个$styleArray,方便在往Excel中写入数据时,同时对单元格进行格式的设置
    $styleArray = [
    'alignment' => [
    'horizontal' => \PHPExcel_Style_Alignment::HORIZONTAL_CENTER,
    'vertical' => \PHPExcel_Style_Alignment::VERTICAL_CENTER
    ],
    'borders' => [
    'allborders' => [
    'style' => \PHPExcel_Style_Border::BORDER_THIN
    ]
    ]
    ];
    $excel->getActiveSheet()->getStyle('A1')->applyFromArray($styleArray); $excel->getActiveSheet()->getStyle('A1')->getFont()->setBold(true); //设置字体加粗 $excel->getActiveSheet()->mergeCells('A1:H1'); //合并A1:F1单元格
  • 对表格第一行标题的特殊处理

      $excel->getActiveSheet()->mergeCells('A1:H1');  //合并A1:H1单元格
    $excel->getActiveSheet()->setCellValue('A1',$insert[0]['grade'].'级'.$insert[0]['dep'].'导师分配结果');
    $excel->getActiveSheet()->getStyle('A1')->getFont()->setBold(true); //加粗
    $excel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); //设置水平居中
    $excel->getActiveSheet()->getStyle('A1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); //设置垂直居中
  • 对表的标题行的特殊处理

      $letter = ['A','B','C','D','E','F','G','H'];
    $tableHeader = ['序号','系别','专业导师','职称','课题','学生姓名','学号','联系方式']; //设置表头数组,单独处理
    for ($i=0; $i <8 ; $i++) {
    $excel->getActiveSheet()->setCellValue($letter[$i].'2',$tableHeader[$i]); //设置单元格的值
    $excel->getActiveSheet()->getStyle($letter[$i].'2')->applyFromArray($styleArray); //设置单元格格式:水平、垂直居中、加边框
    $excel->getActiveSheet()->getStyle($letter[$i].'2')->getFont()->setBold(true); //设置单元格字体加粗
    }
  • 在这次项目中碰到的比较奇葩的问题和处理办法 - 某些单元格的动态合并:

    第一种情况如上图,对于上图这种格式的Excel写入是比较简单的,只需从数据库中取出数据,逐条的插入进表格中,并作格式处理就好了

      $totalInsert = count($insert);   //计算总插入数
    for ($i=0; $i <$totalInsert ; $i++) {
    $excel->getActiveSheet()->setCellValue('A'.($i+3),($i+1));
    $excel->getActiveSheet()->setCellValue('B'.($i+3),$insert[$i]['tdep']);
    $excel->getActiveSheet()->setCellValue('C'.($i+3),$insert[$i]['sname']);
    $excel->getActiveSheet()->setCellValue('D'.($i+3),$insert[$i]['snum']);
    $excel->getActiveSheet()->setCellValue('E'.($i+3),$insert[$i]['stele']);
    $excel->getActiveSheet()->setCellValue('F'.($i+3),$insert[$i]['tname']);
    $excel->getActiveSheet()->setCellValue('G'.($i+3),$insert[$i]['tposi']);
    $excel->getActiveSheet()->setCellValue('H'.($i+3),$insert[$i]['title']);
    $excel->getActiveSheet()->setCellValue('I'.($i+3),$insert[$i]['ttele']);
    } for ($j=0; $j <9 ; $j++) {
    $excel->getActiveSheet()->getStyle($letter[$j].'3'.':'.$letter[$j].($totalInsert+2))->applyFromArray($styleArray); //设置单元格格式:水平、垂直居中、加边框
    }

    第二种情况如上图,对于初学PHPExcel的我来说,上图的操作简直是麻烦,我的做法是

    1. 先设置两个临时变量 $oldTemp$newTemp 用来处理合并的单元格的范围,例如合并A1:A6,$oldTemp 用来记录合并的左范围,$newTemp用来记录合并的右范围,并且 $newTemp = $oldTemp + 每个导师的学生数,若学生数为0,则加1

    2. 先插入列F、G、H的数据,加样式,然后对前面的列A、B、C、D、E先插值,再进行单元格合并,因为比如A1:A3合并,合并后的单元格名称仍然为A1,合并的范围为 $oldTemp : $newTemp-1,然后交换 $oldTemp$newTemp

    3. 不知道有没有更好的处理办法,对自己的处理办法表示有点愚蠢。。

       $oldTemp = 3;           //临时变量,用于处理合并单元格的范围
      $newTemp = 0; //临时变量,用于处理合并单元格的范围 for ($i=0; $i <$totalInsert ; $i++) { //循环插入数据,并作格式处理
      if ($insert[$i]['stuNum'] == 0) { //判断导师是否有学生,如果没有学生,只需插入一行
      $tempCount = $insert[$i]['stuNum'] + 1;
      } else {
      $tempCount = $insert[$i]['stuNum'];
      }
      for ($j=0; $j <$tempCount ; $j++) { //开始插入
      if ($insert[$i]['stuNum'] != 0) { //逐一插入导师的学生信息
      $excel->getActiveSheet()->setCellValue('F'.($j+$oldTemp),$insert[$i]['tstudentL'][$j]['sname']);
      $excel->getActiveSheet()->setCellValue('G'.($j+$oldTemp),$insert[$i]['tstudentL'][$j]['snum']);
      $excel->getActiveSheet()->setCellValue('H'.($j+$oldTemp),$insert[$i]['tstudentL'][$j]['stele']);
      } $excel->getActiveSheet()->getStyle('F'.($j+$oldTemp))->applyFromArray($styleArray); //设置单元格格式:水平、垂直居中、加边框
      $excel->getActiveSheet()->getStyle('G'.($j+$oldTemp))->applyFromArray($styleArray); //设置单元格格式:水平、垂直居中、加边框
      $excel->getActiveSheet()->getStyle('H'.($j+$oldTemp))->applyFromArray($styleArray); //设置单元格格式:水平、垂直居中、加边框
      } $excel->getActiveSheet()->setCellValue('A'.$oldTemp,($i+1)); //设置单元格的值
      $excel->getActiveSheet()->setCellValue('B'.$oldTemp,$insert[$i]['dep']);
      $excel->getActiveSheet()->setCellValue('C'.$oldTemp,$insert[$i]['tname']);
      $excel->getActiveSheet()->setCellValue('D'.$oldTemp,$insert[$i]['position']);
      $excel->getActiveSheet()->setCellValue('E'.$oldTemp,$insert[$i]['title']); $newTemp = $oldTemp + $tempCount;
      if ($insert[$i]['stuNum'] != 1 && $insert[$i]['stuNum'] != 0) {
      for ($k=0; $k <5 ; $k++) {
      $excel->getActiveSheet()->mergeCells($letter[$k].$oldTemp.':'.$letter[$k].($newTemp-1)); //根据导师的学生数合并A、B、C、D、E列的单元格
      }
      } for ($z=0; $z <5 ; $z++) {
      $excel->getActiveSheet()->getStyle($letter[$z].$oldTemp.':'.$letter[$z].($newTemp-1))->applyFromArray($styleArray); //设置单元格格式:水平、垂直居中、加边框
      } $oldTemp = $newTemp;
      }
  • 直接输出至浏览器,即下载至本地,只需直接加入代码就行

      $write = new \PHPExcel_Writer_Excel5($excel);
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
    header("Content-Type:application/force-download");
    header("Content-Type:application/vnd.ms-execl");
    header("Content-Type:application/octet-stream");
    header("Content-Type:application/download");;
    header('Content-Disposition:attachment;filename='.'"'.$insert[0]['grade'].'级导师互选结果.xls"'); //可以对文件名进行处理
    header("Content-Transfer-Encoding:binary");
    $write->save('php://output');

四、实践效果动图

学生Excel导入:

Excel模版导出:

结果导出:

五、总结

  • 期间遇到了很多的bug,不断的上网找资料、找博客,学到了很多的知识,比如在一个''上刚了非常多的时间,最后找到错误的时候又喜又气的,还有在往Excel中写数据的时候,碰到一个未定义数组下标[0]的错误的时候,花了更多的时间,反反复复的检查代码愣是没发现错误在哪里,躺在床上没解决bug不甘心又下床苦寻,最后发现数据库中的数据有一些是空的,直接插入会出错,要做一些相应的处理

  • 学到了新知识心里是惊喜的,不过我也是得去做下编译实验的。。

PHPExcel使用体会的更多相关文章

  1. phpexcel读取输出操作

    //读取 <?php header("Content-Type:text/html;charset=utf-8"); include 'Classes/PHPExcel.ph ...

  2. [moka同学笔记]PHPexcel之excel导出和导入

    原案例来自http://www.sucaihuo.com/有修改 1.目录结构(文件不用解释,应该都可以看得懂,直接看代码)

  3. phpexcel导出数据表格

    1.下载phpexcel(李昌辉) 2.在页面引入phpexcel的类文件,并且造该类的对象 include("../chajian/phpexcel/Classes/PHPExcel.ph ...

  4. phpexcel 字符串转码

    问题状况:在导入excel的时候会出现 PHPExcel_RichText Object ( [_richTextElements:PHPExcel_RichText:] => PHPExcel ...

  5. thinkphp3.2和phpexcel导入

    先整个最基础的代码,理解了这个,后面的就非常简单了 $file_name= './Upload/excel/123456.xls'; import("Org.Util.PHPExcel&qu ...

  6. PHPExcel 大数据的导出

    PHPExcel 是一个php语言读取导出数据.导入生成Excel的类库,使用起来非常方便,但有时会遇到以些问题,比如导出的数据超时,内存溢出等. 下面我们来说说这些问题和解决办法. PHPExcel ...

  7. PHPExcel按单元格读取数据

    import('ORG.Util.PHPExcel.PHPExcel'); $objReader = new PHPExcel_Reader_Excel2007(); //use excel2007 ...

  8. phpexcel读取excel的xls xlsx csv格式

    我之前写过一篇PHP读取csv文件的内容 上代码index.php <?php /** * * @author XC * */ class Excel { public $currentShee ...

  9. 解决 PHPExcel 长数字串显示为科学计数

    解决 PHPExcel 长数字串显示为科学计数 在excel中如果在一个默认的格中输入或复制超长数字字符串,它会显示为科学计算法,例如身份证号码,解决方法是把表格设置文本格式或在输入前加一个单引号. ...

随机推荐

  1. C#微信公众号开发系列教程五(接收事件推送与消息排重)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  2. HoloLens开发手记 - Unity之Recommended settings 推荐设置

    Unity提供了大量的设置选项来满足全平台的配置,对于HoloLens,Unity可以通过切换一些特定的设置来启用HoloLens特定的行为. Holographic splash screen 闪屏 ...

  3. des解密不完整,前面几位是乱码的解决办法

    在工作中遇到的Des解密问题,第三方发来的数据需要我们进行des解密,但是解密的结果前几位始终是乱码.废了半天劲,终于找到了问题所在. 下面先介绍一下des,了解des的同学可以直接看下面的解决办法. ...

  4. [转]linux 系统监控、诊断工具之 IO wait

    1.问题: 最近在做日志的实时同步,上线之前是做过单份线上日志压力测试的,消息队列和客户端.本机都没问题,但是没想到上了第二份日志之后,问题来了: 集群中的某台机器 top 看到负载巨高,集群中的机器 ...

  5. iptables规则组成

    一.四张表五条链 组成部分:四张表 + 5条链(Hook point) + 规则 四张表:filter nat mangle raw 五条链:PREROUTING INPUT FORWARD OUTP ...

  6. 完整的社交app源码android+laravel

    等想到写点什么的时候再写吧,其他看代码. https://github.com/huijimuhe/monolog-android https://github.com/huijimuhe/monol ...

  7. 备忘:maven 错误信息: Plugin execution not covered by lifecycle configuration

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  8. Nginx 负载均衡

    Nginx简单实现网站的负载均衡 地址:http://www.cnblogs.com/alvin_xp/p/4161162.html

  9. [转]史上最全最强SpringMVC详细示例实战教程

    原文:http://www.cnblogs.com/sunniest/p/4555801.html?utm_source=tuicool&utm_medium=referral SpringM ...

  10. Qt自定义窗体,边框,圆角窗体

    MainWindow::MainWindow(QWidget*parent): QMainWindow(parent), ui(new Ui::MainWindow) { setAttribute(Q ...