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. Python2.2-原理之类型和运算

    此节来自于<Python学习手册第四版>第二部分 一.Python对象类型(第4章) 1. Python可以分解成模块.语句.表达式以及对象:1.程序由模块构成:2.模块包含语句:3.语句 ...

  2. 模拟MVC-WebForm实现ModelBinding

    (一) 前言                                                                           用ASP.NET MVC的时候,我们都 ...

  3. JavaScript高级程序设计笔记 事件冒泡和事件捕获

    1.事件冒泡 要理解事件冒泡,就得先知道事件流.事件流描述的是从页面接收事件的顺序,比如如下的代码: <body> <div> click me! </div> & ...

  4. 熟悉css/css3颜色属性

    颜色属性无处不在.字体要用颜色,背景可以有颜色,粒子特效更是离不开颜色.本文参考了一些资料简单总结下以备日后查阅. css中颜色的定义方式: 十六进制色 RGB & RGBA HSL & ...

  5. 自定义圆形控件RoundImageView并认识一下attr.xml

    今天我们来讲一下有关自定义控件的问题,今天讲的这篇是从布局自定义开始的,难度不大,一看就明白,估计有的同学或者开发者看了说,这种方式多此一举,但是小编我不这么认为,多一种解决方式,就多一种举一反三的学 ...

  6. TextBoxFor控件的扩展---Bootstrap在mvc上的应用

    TextBoxFor控件的问题: 1:自带了样式,再用bootstrap样式会有冲突. 2:要加水印,js事件,限制输入长度比较麻烦. 因此需要对textboxfor控件进行扩展. 目标: 1:能使用 ...

  7. 初用protobuf-csharp-port

    下面这个用法是参照protobuf-csharp-port的官方wiki,参见: https://code.google.com/p/protobuf-csharp-port/wiki/Getting ...

  8. [HDU5904]LCIS(DP)

    题意: 给定两个序列,求它们的最长公共递增子序列的长度, 并且这个子序列的值是连续的 n,m<=1e5,a[i],b[i]<=1e6分析:dp[i]表示以数字i结尾的序列最长长度 dp[a ...

  9. 总有一天会NB的! SB一样的坚持会有NB一样的结果的!

    第一天: 1.背景图不显示,因为背景图片无法撑开div,所以必须自己设置div的高度哦! 2.div水平居中! A:margin-left:auto;margin-right:auto;  B: 父元 ...

  10. AngularJS 日期转换字符串

    日期转换成字符串的办法有很多种,其中最简单的方法是 使用AngularJS的filter来实现. $filter('date')(date, 'yyyyMM'): $filter('date')(da ...