资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划
从策略到执行的一站式服务

yii2+PhpSpreadsheet导入execl数据踩坑记

来源:奇兵网络 | 2020-05-29 | 浏览:1155次

几年前采用phpexecl导入过数据,今天又有这个需求,于是开始了踩坑的过程。几年时间变化好大,phpexecl变成了PhpSpreadsheet,再加上yii2框架及各种技术环境的变化,要将各种技术整合起来不易呀。


一、composer安装PhpSpreadsheet

1、composer我是全局安装,直接cmd到当前程序路径,然后:composer require phpoffice/phpspreadsheet

2、我是采用composer阿里云的镜像,才不会被墙:https://developer.aliyun.com/composer

3、PhpSpreadsheet的github地址(composer安装不需要理会这个):https://github.com/PHPOffice/PhpSpreadsheet



三、yii2控制器 : DataController.php

<?php
namespace app\modules\controllers;

use Yii;
use app\modules\models\UploadForm;
use yii\web\UploadedFile;
use app\models\Product;

use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;


/**
*
*/
class DataController extends CommonController
{
 
  public function actionIndexinput()
  {
       $model = new UploadForm;
       $this->layout = "layout1";
       return $this->render("inputdata", ['model'=>$model]);
  }

   public function actionIndexclear()
   {
       $this->layout = "layout1";
       return $this->render("cleardata");
   }

   public function actionInputdata()
   {
       $this->layout = "layout1";
       $model = new UploadForm();
       $prmodel = new Product;

       if (Yii::$app->request->isPost) {

           $model->file = UploadedFile::getInstance($model, 'file');

           if ($model->file && $model->validate()) {
               $filename = date('Y-m-d',time()).'_'.rand(1,9999) . '.' . $model->file->extension;
               $model->file->saveAs('uploads/' . $filename);
               $filepath = 'uploads/' . $filename;
           }
       }
       $Data = $this->importExecl($filepath,0,10, $prmodel);
       $num = count($Data);
       if($num>1000){
           Yii::$app->session->setFlash('info', '一次只能导入1000条以内的数据!');
           return $this->render("inputdata", ['model'=>$model]);
       }

       for ($row = 1; $row <= $num; $row++) {
           Yii::$app->db->createCommand()->batchInsert('xy_product', ['name', 'company', 'sex', 'pcnum', 'ticketnum', 'mannum', 'groupnum', 'contact', 'testtime',  'productname'], [$Data[$row]])->execute();
       }
       Yii::$app->session->setFlash('info', '数据导入成功!');
       return $this->render("inputdata", ['model'=>$model]);
   }

   public function actionCleardata()
   {
       $this->layout = "layout1";
       Product::deleteAll();
       Yii::$app->session->setFlash('info', '数据清空成功!');
       return $this->render("cleardata");
   }


   /**
    * 使用PHPEXECL导入
    *
    * @param string $file      文件地址
    * @param int    $sheet     工作表sheet(传0则获取个sheet)
    * @param int    $columnCnt 列数(传0则自动获取更大列)
    * @param array  $options   操作选项
    *                          array mergeCells 合并单元格数组
    *                          array formula    公式数组
    *                          array format     单元格格式数组
    *
    * @return array
    * @throws Exception
    */
   function importExecl($file = '', $sheet = 0, $columnCnt = 0, $model)
   {
       try {
           /* 转码 */
           $file = iconv("utf-8", "gb2312", $file);

           if (empty($file) OR !file_exists($file)) {
               throw new \Exception('文件不存在!');
           }

           /** @var Xlsx $objRead */
           $objRead = IOFactory::createReader('Xlsx');
           //die("ok");
           if (!$objRead->canRead($file)) {
               /** @var Xls $objRead */
               $objRead = IOFactory::createReader('Xls');

               if (!$objRead->canRead($file)) {
                   throw new \Exception('只支持导入Excel文件!');
               }
           }

           /* 如果不需要获取特殊操作,则只读内容,可以大幅度提升读取Excel效率 */
           $objRead->setReadDataOnly(true);
           /* 建立excel对象 */
           $obj = $objRead->load($file);
           /* 获取指定的sheet表 */
           $currSheet = $obj->getSheet($sheet);

           if (0 == $columnCnt) {
               /* 取得更大的列号 */
               $columnH = $currSheet->getHighestColumn();
               /* 兼容原逻辑,循环时使用的是小于等于 */
               $columnCnt = Coordinate::columnIndexFromString($columnH);
           }

           /* 获取总行数 */
           $rowCnt = $currSheet->getHighestRow();
           $data   = [];

           /* 读取内容 */
           for ($_row = 1; $_row <= $rowCnt; $_row++) {
               $isNull = true;

               for ($_column = 1; $_column <= $columnCnt; $_column++) {
                   $cellName = Coordinate::stringFromColumnIndex($_column);
                   $cellId   = $cellName . $_row;
                   $cell     = $currSheet->getCell($cellId);

                   if (isset($format) && 'm/d/yyyy' == $format) {
                       /* 日期格式翻转处理 */
                       $cell->getStyle()->getNumberFormat()->setFormatCode('yyyy/mm/dd');
                   }

                   $data[$_row][$cellName] = trim($currSheet->getCell($cellId)->getFormattedValue());  //$data[$_row][$cellName]  值

                   if (!empty($data[$_row][$cellName])) {
                       $isNull = false;
                   }

               }
               //return $data; //这里将返回一整行数据

               /* 判断是否整行数据为空,是的话删除该行数据 */
               if ($isNull) {
                   unset($data[$_row]);
               }
           }

           return $data;
       } catch (\Exception $e) {
           throw $e;
       }
   }

}


?>


四、yii2模型model :  UploadForm.php

<?php
namespace app\modules\models;

use yii\base\Model;


class UploadForm extends Model
{

   public $file;


   public function rules()
   {
       return [
           [['file'], 'file'],
       ];
   }

   public function attributeLabels(){
       return [
           'file'=>'文件上传'
       ];
   }


}


五、yii2视图: inputdata.php

: 注意事项:1、execl表的的数据顺序必须为:姓名   企业名称   性别 机位号    准考证号   身份证号   分组号    联系方式   考试时间   考试类型2、一次只能导入1000条以内的数据


六、其它注意事项

1、PHP低版本及高版本都不行,这是啥坑。7.1.9测试成功。2020.5.28日composer安装PhpSpreadsheet,没有选择安装版本,可能是最新的版本。

2、yii2 数据库操作的两种模式{{%product}}:https://blog.csdn.net/nw_ningwang/article/details/77102610

3、修改数据库字段排序:

https://www.cnblogs.com/yangxiaochu/p/8108976.html

4、参考网址:https://blog.csdn.net/DestinyLordC/article/details/84071456


技术交流:309800818

—— 微信公众号 ——

热门标签

上一条———————

阿里云账号RAM鉴权实现单个域名管理

下一条———————

web页面原型设计原则
十六年 建站经验

多一份参考,总有益处

联系奇兵网络,免费获得《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

业务热线:151-1127-5288 / 客户专线   长沙:13975129722 0731-85502318