它山之石可以攻玉

键盘上的生活
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

php+phpspreadsheet读取Excel数据存入mysql

Posted on 2018-09-29 16:34  陈达辉  阅读(4495)  评论(1编辑  收藏  举报

先生成Excel模板,然后导入Excel数据到mysql,每条数据对应图片上传到阿里云

  1 <?php
  2 /**
  3  * Created by PhpStorm.
  4  * User: Administrator
  5  * Date: 2018/9/27
  6  * Time: 13:57
  7  */
  8 
  9 namespace site\admin\model;
 10 
 11 use PhpOffice\PhpSpreadsheet\Spreadsheet;
 12 use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
 13 use system\library\AliYunOSS;
 14 use system\library\Unzip;
 15 
 16 class ProductBatchModel extends \site\admin\component\Model
 17 {
 18     
 19     public function add($data){
 20         
 21         if (!$this->_validate($data, 'add')) {
 22             return false;
 23         }
 24         
 25         $languageModel = new LanguageModel();
 26         $categoryModel = new CategoryModel();
 27         $productModel = new ProductModel();
 28         $urlAliasModel = new UrlAliasModel();
 29         
 30         if(substr(strrchr($data['excel_file'], '.'), 1)<>'xlsx'){
 31             $this->addError('excel_file', '请上传xlsx格式的Excel文件');
 32             return false;
 33         }
 34         
 35         $arr_file = explode('com/', $data['excel_file']);
 36         
 37         $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
 38         $reader->setReadDataOnly(TRUE);
 39         $spreadsheet = $reader->load(DIR_UPLOAD.$arr_file[1]); //载入excel表格
 40         
 41         $worksheet = $spreadsheet->getActiveSheet();
 42         $highestRow = $worksheet->getHighestRow(); // 总行数
 43         $highestColumn = $worksheet->getHighestColumn(); // 总列数
 44         $highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn); // e.g. 5
 45         
 46         $lines = $highestRow - 1;
 47         if ($lines <= 0) {
 48             $this->addError('Excel', 'Excel表格中没有数据');
 49             return false;
 50         }
 51         
 52         $enableRow = array();
 53         $arr_url = array();
 54         
 55         for ($row = 2; $row <= $highestRow; ++$row) {
 56             
 57             /******************************验证产品型号***********************************/
 58             
 59             $model_no = $worksheet->getCellByColumnAndRow(1, $row)->getValue();
 60             if(empty($model_no)){
 61                 $this->addError('model_no'.$row, '第'.$row.'行产品型号为空');
 62             }else{
 63                 $if_exist = $productModel->getProductByModel($model_no);
 64                 if(empty($if_exist)){
 65                     $enableRow[] = $row; //新增该行
 66                 }
 67             }
 68             
 69                 
 70             /******************************验证产品分类***********************************/
 71             
 72             $category_name = $worksheet->getCellByColumnAndRow(2, $row)->getValue();
 73             if(empty($category_name)){
 74                 $this->addError('category_name'.$row, '第'.$row.'行分类名为空');
 75             }else{
 76                 $category = $categoryModel->getCategoryIdByName($category_name);
 77                 if(empty($category)){
 78                     $this->addError('category_name'.$row, '第'.$row.'行分类名不存在');
 79                 }
 80             }
 81             
 82                 
 83             $sort_order = $worksheet->getCellByColumnAndRow(3, $row)->getValue();
 84             if(empty($sort_order) || !is_numeric($sort_order)){
 85                 $this->addError('sort_order'.$row, '第'.$row.'行排序错误');
 86             }
 87             
 88             $status = $worksheet->getCellByColumnAndRow(4, $row)->getValue();
 89             if(empty($status) || !is_numeric($status)){
 90                 $this->addError('status'.$row, '第'.$row.'行状态错误');
 91             }
 92                 
 93             /******************************验证语言***********************************/
 94             
 95             $language_name = $worksheet->getCellByColumnAndRow(5, $row)->getValue();
 96             if(empty($language_name)){
 97                 $this->addError('language_name'.$row, '第'.$row.'行语言为空');
 98             }else{
 99                 $languages = $languageModel->getSysLanguageByName($language_name);
100                 if(empty($languages)){
101                     $this->addError('languages'.$row, '第'.$row.'行语言不存在');
102                 }
103             }
104             
105                 
106             $name = $worksheet->getCellByColumnAndRow(6, $row)->getValue();
107             if(empty($name)){
108                 $this->addError('name'.$row, '第'.$row.'行名称为空');
109             }
110             
111             $keywords = $worksheet->getCellByColumnAndRow(7, $row)->getValue();
112             if(empty($keywords)){
113                 $this->addError('keywords'.$row, '第'.$row.'行关键词为空');
114             }
115             
116             $url = $worksheet->getCellByColumnAndRow(10, $row)->getValue();
117             if(!empty($url)){
118                 if(in_array($url, $arr_url)){
119                     $this->addError('url'.$row, '第'.$row.'行网址重复出现');
120                 }else{
121                     $arr_url[] = $url;
122                 }
123             }
124 
125         }
126         
127         if($this->hasErrors()){
128             return false;
129         }
130 
131         //组装数组
132         $enableData = array();
133         foreach ($enableRow as $key => $row) {
134 
135             $model_no = $worksheet->getCellByColumnAndRow(1, $row)->getValue();
136             
137             //获取分类ID
138             $category_name = $worksheet->getCellByColumnAndRow(2, $row)->getValue();
139             $category = $categoryModel->getCategoryIdByName($category_name);
140             $category_id = $category['category_id'];
141             
142             $sort_order = $worksheet->getCellByColumnAndRow(3, $row)->getValue();
143             $status = $worksheet->getCellByColumnAndRow(4, $row)->getValue();
144             
145             //获取语言ID
146             $language_name = $worksheet->getCellByColumnAndRow(5, $row)->getValue();
147             $languages = $languageModel->getSysLanguageByName($language_name);
148             $language_id = $languages['language_id'];
149             
150             $name = $worksheet->getCellByColumnAndRow(6, $row)->getValue();
151             $keywords = $worksheet->getCellByColumnAndRow(7, $row)->getValue();
152             $abstract = $worksheet->getCellByColumnAndRow(8, $row)->getValue();
153             $description = $worksheet->getCellByColumnAndRow(9, $row)->getValue();
154             $url = $worksheet->getCellByColumnAndRow(10, $row)->getValue();
155             $meta_title = $worksheet->getCellByColumnAndRow(11, $row)->getValue();
156             $meta_keyword = $worksheet->getCellByColumnAndRow(12, $row)->getValue();
157             $meta_description = $worksheet->getCellByColumnAndRow(13, $row)->getValue();
158             
159             if(!isset($enableData[$model_no])){
160                 $enableData[$model_no] = array(
161                         'product_type_id'=>'',
162                         'model_no'=>$model_no,
163                         'sort_order'=>$sort_order,
164                         'status'=>$status,
165                         'category'=>array($category_id),
166                         'trade'=>'',
167                         'producttradeinfo'=>array()
168                 );
169             }
170             
171             $enableData[$model_no]['desc'][$language_id] = array(
172                     'description'=>$description,
173                     'name'=>$name,
174                     'abstract'=>$abstract,
175                     'keywords'=>$keywords,
176                     'language_name'=>$language_name,
177                     'meta_title'=>$meta_title,
178                     'meta_keyword'=>$meta_keyword,
179                     'meta_description'=>$meta_description,
180                     'url_alias'=>$url
181             );
182             
183         }
184         
185         //遍历检测网址
186         foreach ($enableData as $key => $value){
187             if(isset($value['desc']) && !empty($value['desc'])){
188                 foreach ($value['desc'] as $k => $v){
189                     $cc = $urlAliasModel->validate(['keyword' => $v['url_alias'], 'language_id' => $k, 'query' => ''],'add');
190                     if($cc==false){
191                         return false;
192                     }
193                 }
194             }
195         }
196 
197         //解压缩图片压缩包
198         $dirPath = DIR_UPLOAD.$this->session->data['site_id'];
199         $file = $dirPath.'/'.$data['images_file'];
200         if(!file_exists($file) || (substr(strrchr($file, '.'), 1)<>'zip')){
201             $this->addError('imageZip', '请上传产品图片压缩包(zip格式)');
202             return false;
203         }
204         $z    = new Unzip;
205         $info = $z->unzip($file, $dirPath.'/', true, false);
206         if($info){
207             unlink($file); //删除压缩包
208         }
209 
210         //获取产品图片
211         foreach ($enableData as $key => $value){            
212             $enableData[$key]['image'] = $this->_getImage($key,$dirPath.'/'.basename($data['images_file'],'.zip'));
213         }
214 
215         foreach ($enableData as $key => $value){
216             try {
217                 $productModel->add($value);
218             } catch (Exception $e) {
219                 $this->addError('add', $e->getMessage());
220                 return false;
221             }
222         }
223         return true;
224 
225     }
226     
227     /**
228      * 生成模板
229      *
230      * @access public
231      * @return void
232      */
233     public function createTemplate()
234     {
235         
236         $languageModel = new LanguageModel();
237         $languages = $languageModel->getEnabledLanguages();
238         
239         $categoryModel = new CategoryModel();
240         $category = $categoryModel->getRecursionCategory();
241         $categoryNme = $this->_getCategoryName($category);
242         
243         $columnNum = 3000;
244         
245         $spreadsheet = new Spreadsheet();
246         
247         /*****************************************设置当前活动页内容***********************************/
248         
249         $sheet = $spreadsheet->getActiveSheet();
250         $sheet->setCellValue('A1', '型号(必填)');
251         $sheet->setCellValue('B1', '分类名(必填)');
252         $sheet->setCellValue('C1', '排序(必填,请输入数字)');
253         $sheet->setCellValue('D1', '状态(必填,1=上架|0=下架)');        
254         $sheet->setCellValue('E1', '语言(必填)');
255         $sheet->setCellValue('F1', '名称(必填)');
256         $sheet->setCellValue('G1', '关键词(必填)');
257         $sheet->setCellValue('H1', '简要描述');
258         $sheet->setCellValue('I1', '详细描述');
259         $sheet->setCellValue('J1', '网址');
260         $sheet->setCellValue('K1', 'seo标题');
261         $sheet->setCellValue('L1', 'seo关键词');
262         $sheet->setCellValue('M1', 'seo描述');
263         
264         //设置相关属性
265         $sheet->setTitle('Product');
266         $sheet->getDefaultColumnDimension()->setWidth(30);
267         $sheet->getStyle('A1:M1')->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
268         $sheet->getStyle('A1:M1')->getFill()->getStartColor()->setARGB('FF808080');
269         $sheet->getStyle('A1:M1')->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);
270         
271         //分类列
272         for($i=2;$i<=$columnNum;$i++){
273             $objValidation = $sheet->getDataValidation('B'.$i);
274             $objValidation -> setType(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST)
275             -> setErrorStyle(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_INFORMATION)
276             -> setAllowBlank(false)
277             -> setShowInputMessage(true)
278             -> setShowErrorMessage(true)
279             -> setShowDropDown(true)
280             -> setErrorTitle('输入的值有误')
281             -> setError('您输入的值不在下拉框列表内')
282             -> setPrompt('请选择下拉框列表中的值')
283             -> setFormula1('data!$C$3:$C$'.(count($categoryNme)+2));
284         }
285         
286         //状态列
287         for($i=2;$i<=$columnNum;$i++){
288             $objValidation = $sheet->getDataValidation('D'.$i);
289             $objValidation -> setType(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST)
290             -> setErrorStyle(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_INFORMATION)
291             -> setAllowBlank(false)
292             -> setShowInputMessage(true)
293             -> setShowErrorMessage(true)
294             -> setShowDropDown(true)
295             -> setErrorTitle('输入的值有误')
296             -> setError('您输入的值不在下拉框列表内')
297             -> setPrompt('请选择下拉框列表中的值')
298             -> setFormula1('data!$A$3:$A$4');
299         }
300         
301         //语言列
302         for($i=2;$i<=$columnNum;$i++){
303             $objValidation = $sheet->getDataValidation('E'.$i);
304             $objValidation -> setType(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST)
305             -> setErrorStyle(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_INFORMATION)
306             -> setAllowBlank(false)
307             -> setShowInputMessage(true)
308             -> setShowErrorMessage(true)
309             -> setShowDropDown(true)
310             -> setErrorTitle('输入的值有误')
311             -> setError('您输入的值不在下拉框列表内')
312             -> setPrompt('请选择下拉框列表中的值')
313             -> setFormula1('data!$B$3:$B$'.(count($languages)+2));
314         }
315         
316         
317         
318         /*******************************************新增一个活动页,放公共数据*********************************/
319         
320         $spreadsheet->createSheet();
321         $spreadsheet->setActiveSheetIndex(1);
322         $sheet = $spreadsheet->getActiveSheet();
323         $sheet->setTitle('data');
324         $sheet->getDefaultColumnDimension()->setWidth(25);
325         $sheet->mergeCells('A1:C1');
326         $styleArray = [
327                 'alignment' => [
328                         'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
329                         'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
330                 ],
331         ];
332         $sheet->getStyle('A1')->applyFromArray($styleArray);
333         $sheet->getRowDimension('1')->setRowHeight(35);
334         
335         $sheet->getStyle('A1')->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
336         $sheet->getStyle('A1')->getFill()->getStartColor()->setARGB('8B0000');
337         $sheet->getStyle('A1')->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);
338         $sheet->setCellValue('A1', '公共数据(请不要修改)');
339         
340         $sheet->getStyle('A2:C2')->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
341         $sheet->getStyle('A2:C2')->getFill()->getStartColor()->setARGB('FF808080');
342         $sheet->getStyle('A2:C2')->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);
343         
344         $sheet->setCellValue('A2', '状态(1=上架|0=下架)');
345         $sheet->setCellValue('A3', '0');    
346         $sheet->setCellValue('A4', '1');
347         
348         $sheet->setCellValue('B2', '语言');
349         foreach ($languages as $key => $value){
350             $sheet->setCellValue('B'.($key+3), $value['name']);
351         }
352         
353         $sheet->setCellValue('C2', '分类名');
354         foreach ($categoryNme as $key => $value){
355             $sheet->setCellValue('C'.($key+3), $value);
356         }
357         
358         $sheet->setSheetState('hidden');
359         
360         //设置第一页为活动页,保存
361         $spreadsheet->setActiveSheetIndex(0);
362         $writer = new Xlsx($spreadsheet);
363         $file_name = $this->session->data['site_id'].'.xlsx';
364         $file_path = DIR_UPLOAD.'excel_template/'.$file_name;
365         $writer->save($file_path);
366         
367         //释放内存
368         $spreadsheet->disconnectWorksheets();
369         unset($spreadsheet);
370     
371         return $file_name;
372     }
373     
374     /**
375      * 验证
376      * @access private
377      * @param array $data
378      * @param string $scenario 验证场景 add
379      * @return bool
380      */
381     private function _validate($data, $scenario = '')
382     {
383     
384         if (!isset($data['excel_file']) || empty($data['excel_file'])) {
385             $this->addError('excel_file', '没有上传产品Excel文件');
386         }
387         
388         if (!isset($data['images_file']) || empty($data['images_file'])) {
389             $this->addError('images_file', '没有上传产品图片文件');
390         }
391     
392         return $this->hasErrors() ? false : true;
393     }
394     
395     /**
396      * 获取产品分类名称
397      * @access private
398      * @param array $data
399      * @return array
400      */
401     private function _getCategoryName($data){
402         
403         if(!empty($data)){
404             
405             foreach ($data as $key => $value){
406                 if(!empty($data['children'])){
407                     $this->_getCategoryName($data['children']);
408                 }else{
409                     $retrun[] = $value['name'];
410                 }
411             }
412             
413         }else{
414             $retrun = array();
415         }
416         
417         return $retrun;
418         
419     }
420     
421     /**
422      * 遍历文件夹
423      * @access private
424      * @param string $dir
425      * @return array
426      */
427     private function _getDirFile($dir) {
428         $files = array();
429         if(@$handle = opendir($dir)) { //注意这里要加一个@,不然会有warning错误提示:)
430             while(($file = readdir($handle)) !== false) {
431                 if($file != ".." && $file != ".") { //排除根目录;
432                     if(is_dir($dir."/".$file)) { //如果是子文件夹,就进行递归
433                         $files[$file] = $this->_getDirFile($dir."/".$file);
434                     } else { //不然就将文件的名字存入数组;
435                         $files[] = $file;
436                     }
437     
438                 }
439             }
440             closedir($handle);
441             return $files;
442         }
443     }
444     
445     /**
446      * 获取产品图片
447      * @access private
448      * @param string $dir
449      * @return array
450      */
451     private function _getImage($key,$images_file){
452 
453         $aliYunOSS = new AliYunOSS();
454         $data = array();
455         $arr_image = $this->_getDirFile($images_file);
456         
457         if(isset($arr_image[$key])){
458 
459             foreach ($arr_image[$key] as $k => $v){
460                 $result = $aliYunOSS->uploadFile($images_file.'/'.$key.'/'.$v, 'upload/images/'.$key.'/'.$v);
461                 if($result['success']==1){
462                     $data[] = array(
463                             'name'=>$v,
464                             'image'=>$result['info']['url']
465                     );
466                 }
467             }
468             
469         }
470         
471         return $data;
472     }
473 
474 }