此篇博客是本人的开山之篇,旨在记录下平日里的技术心得,同时如果碰巧能解决部分朋友的问题,那笔者感到非常荣幸。
应业务的需要,需要将表格中的数据,进行EXCEL导出(支持分页导出),同时又要使得EXCEL表格进行数据导入。因此本人在TP框架(3.2.3)下整合了PHPExcel。
因为PHPExcel不支持命名空间,所以就用import导入了;
1.首先下载PHPExcel插件(这里不再赘述)。将PHPExcel.class.php文件连同PHPExcel文件夹放到 ThinkPHP\Library\Org\Util路径下。
2.view文件夹下创建Company文件夹,然后创建index.html(自行引入bootstrap框架)。表单部分的代码如下:
1 <form method="post" action="__URL__/importExcel" enctype="multipart/form-data" name='myExcel'> 2 <input type="file" name="inexcel" value="导入"> 3 <button type="type" class="btn btn-primary" id="company-excel">导入Excel</button> 4 </form> 5 <br/> 6 <br/> 7 8 <form method="post" name="myform" action="__URL__/process"> 9 <button type="type" class="btn btn-primary" id="out-excel">导出Excel</button> 10 </form> 11 12 <div class="table-responsive"> 13 <table class="table table-striped table-hover"> 14 <thead> 15 <tr> 16 <th>ID</th> 17 <th>COMPANY_NAME_ZH</th> 18 <th>COMPANY_NAME_EN</th> 19 <th>LOCATION</th> 20 <th>OPTIONS</th> 21 </tr> 22 </thead> 23 <tbody> 24 <volist name="company_name" id="info"> 25 <tr> 26 <td>{$info.id}</td> 27 <td><a href="/Company/1454">{$info.name_zh}</a></td> 28 <td><a href="/Company/1454">{$info.name_en}</a></td> 29 <td>{$info.location}</td> 30 <td><a href="/Company/1454/editBaseInfo">EDIT</a></td> 31 </tr> 32 </volist> 33 </tbody> 34 </table> 35 </div> 36 37 <!--这里是分页部分--> 38 <div class='page_footer clearfix right'> 39 <ul class="pagination pagination-md"> 40 {$page} 41 </ul> 42 <div class='right' > 43 <input name='goto_input' class='form-control' size='3'> 44 <button class='btn btn-default' name='goto_button' link=''>Goto</button> 45 </div> 46 </div> 47
运行效果大致如下:
3.控制器部分:
1 class CompanyController extends CommonController { 2 public function index(){ 3 $p = M('company'); 4 $count = $p->count(); 5 if($count){ 6 $page = new \Think\Page($count,10); 7 $page->setConfig('prev', '<span aria-hidden="true">上一页</span>');//上一页 8 $page->setConfig('next', '<span aria-hidden="true">下一页</span>');//下一页 9 $page->setConfig('first', '<span aria-hidden="true">首页</span>');//第一页 10 $page->setConfig('last', '<span aria-hidden="true">尾页</span>');//最后一页 11 $page->setConfig ( 'theme', '<li><a>当前%NOW_PAGE%/%TOTAL_PAGE%</a></li> %FIRST% %UP_PAGE% %LINK_PAGE% %DOWN_PAGE% %END%' ); 12 $show = $page->show();//分页显示输出 13 } 14 15 $list = $p->limit($page->firstRow.','.$page->listRows)->select(); 16 //将分页数据存入缓存,当然这里可以换别种思路,比如在url上做文章,通过url获取当前分页数据,存入数组.....
F("abc", $list); 17 $this->assign('page',$show);//赋值分页输出 18 $this->assign('company_name',$list);//赋值数据集 19 $this->display(); 20 } 21 22 public function process(){ 23 header("Content-type:text/html;charset=utf-8"); 24 $cache_data = F("abc"); 25 $this->get_data($cache_data); 26 } 27 28 29 /* 导入excel文件的方法import() 30 * 1.导入文件 31 * 2.成功后调用file_import()方法->导入数据的方法 32 * 33 */ 34 public function importExcel(){ 35 header("Content-type:text/html;charset=utf-8"); 36 //判断是否有上传文件 37 if(!empty($_FILES['inexcel']['name'])){ 38 //设置单文件上传方法 39 $upload = new \Think\Upload();// 实例化上传类 40 $upload->maxSize = 3145728 ;// 设置附件上传大小 41 $upload->exts = array('xls','xlsx','csv');// 设置附件上传类型 42 $upload->rootPath = './Public/upfile/excel/'; // 设置附件上传根目录 43 $info = $upload->uploadOne($_FILES['inexcel']); 44 if(!$info) {// 上传错误提示错误信息 45 $this->error($upload->getError()); 46 }else{// 上传成功 获取上传文件信息 47 $filename = $upload->rootPath.$info['savepath'].$info['savename']; 48 $ext = $info['ext']; 49 $this->file_import($filename,$ext); 50 } 51 }else{ 52 $this->error('请选择上传文件'); 53 } 54 55 } 56 57 /* 58 * 导入数据的方法 file_import($filename,$ext) 59 * @ $filename文件名;$ext文件后缀 60 * 61 * 62 */ 63 function file_import($filename,$exts = 'xlsx'){ 64 //导入phpexcel的类库->phpexcel没有命名空间,因而只能import导入 65 import("Org.Util.PHPExcel"); 66 //创建PHPExcel对象,注意,不能少了\ 67 $PHPExcel = new \PHPExcel(); 68 //如果excel文件后缀名为.xls,导入这个类 69 if($exts == 'xls'){ 70 import("Org.Util.PHPExcel.Reader.Excel5"); 71 $PHPReader=new \PHPExcel_Reader_Excel5(); 72 }else if($exts == 'xlsx' || $exts == 'csv'){ 73 import("Org.Util.PHPExcel.Reader.Excel2007"); 74 $PHPReader=new \PHPExcel_Reader_Excel2007(); 75 } 76 77 //载入文件 78 $PHPExcel=$PHPReader->load($filename); 79 //获取表中的第一个工作表,如果要获取第二个,把0改为1,依次类推 80 $currentSheet=$PHPExcel->getSheet(0); 81 //获取总列数 82 $allColumn=$currentSheet->getHighestColumn(); 83 //获取总行数 84 $allRow=$currentSheet->getHighestRow(); 85 //循环获取表中的数据,$currentRow表示当前行,从哪行开始读取数据,索引值从0开始 86 for($currentRow=1;$currentRow<=$allRow;$currentRow++){ 87 //从哪列开始,A表示第一列 88 for($currentColumn='A';$currentColumn<=$allColumn;$currentColumn++){ 89 //数据坐标 90 $address=$currentColumn.$currentRow; 91 //读取到的数据,保存到数组$arr中 92 $data[$currentRow][$currentColumn]=$currentSheet->getCell($address)->getValue(); 93 } 94 } 95 $this->save_import($data); 96 97 } 98 99 //保存存入的数据 100 function save_import($data){ 101 //var_dump($data); 102 $crm = M('company'); 103 foreach ($data as $k=>$v){ 104 //从下标是2的开始读才是真正的数据 1为第一行的caption 105 //PS:excel表格里如果缺少数据,就会在下面的数组里面产生空数据,从而导致数据库写入错误。 106 if($k >= 2){ 107 //对每一行的数据进行去空处理 108 if($v['A']){ 109 $zh=$v['A'];//baidu 110 $info[$k-2]['name_zh'] = $zh; 111 }else{ 112 $info[$k-2]['name_zh'] = ''; 113 } 114 115 if($v['B']){ 116 $en=$v['B'];//wangyi 117 $info[$k-2]['name_en'] = $en; 118 }else{ 119 $info[$k-2]['name_en'] = ''; 120 } 121 122 if($v['c']){ 123 $location=$v['c']; 124 $info[$k-2]['location'] = $location; 125 }else{ 126 $info[$k-2]['location'] = ''; 127 } 128 } 129 } 130 //将来这部分的数据可能会较多,为了保证数据库数据的完整性,如果开启了事物机制,可以考虑采用事物。 131 $result = $crm->addAll($info); 132 if($result){ 133 $this->success('数据插入成功!'); 134 }else{ 135 $this->error('数据插入失败!'); 136 } 137 138 } 139 140 /** 141 ** @@get_data() 方法 根据 检索出来$company_list的值进行excel导出 142 ** 数据结构是一个二维数组$company_list 143 **/ 144 public function get_data($company_list = array()){ 145 header("Content-type:text/html;charset=utf-8"); 146 $result = $company_list; 147 $data = array(); 148 foreach($result as $key=>$val){ 149 $data[$key]['id'] = $val['id']; 150 $data[$key]['name_zh'] = $val['name_zh']; 151 $data[$key]['name_en'] = $val['name_en']; 152 $data[$key]['location'] = $val['location']; 153 } 154 //组装头部名称数组 155 foreach($data as $key=>$v){ 156 if($key == 'id'){ 157 $headArr[] = 'id'; 158 } 159 if($key == 'COMPANY_NAME_ZH'){ 160 $headArr[] = 'COMPANY_NAME_ZH'; 161 } 162 if($key == 'COMPANY_NAME_EN'){ 163 $headArr[] = 'COMPANY_NAME_EN'; 164 } 165 if($key == 'LOCATION'){ 166 $headArr[] = 'LOCATION'; 167 } 168 if($key == 'EDIT'){ 169 $headArr[] = 'EDIT'; 170 } 171 } 172 173 $headArr = array('id','COMPANY_NAME_ZH','COMPANY_NAME_EN','LOCATION','EDIT'); 174 $filename = '合作公司名称'; 175 $this->getExcel($fileName,$headArr,$data); 176 } 177 178 179 private function getExcel($fileName,$headArr,$data){ 180 //导入PHPExcel类库,因为PHPExcel没有用命名空间,只能import导入 181 import("Org.Util.PHPExcel"); 182 import("Org.Util.PHPExcel.Writer.Excel5"); 183 import("Org.Util.PHPExcel.IOFactory.php"); 184 185 $date = date("Y_m_d H:i:s",time()); 186 $fileName .= "_{$date}.xls"; 187 188 //创建PHPExcel对象,注意,不能少了\ 189 $objPHPExcel = new \PHPExcel(); 190 $objProps = $objPHPExcel->getProperties(); 191 192 //设置表头 193 $key = ord("A"); 194 //print_r($headArr);exit; 195 foreach($headArr as $v){ 196 $colum = chr($key); 197 $objPHPExcel->setActiveSheetIndex(0) ->setCellValue($colum.'1', $v); 198 $objPHPExcel->setActiveSheetIndex(0) ->setCellValue($colum.'1', $v); 199 $key += 1; 200 } 201 202 $column = 2; 203 $objActSheet = $objPHPExcel->getActiveSheet(); 204 foreach($data as $key => $rows){ //行写入 205 $span = ord("A"); 206 foreach($rows as $keyName=>$value){// 列写入 207 $j = chr($span); 208 $objActSheet->setCellValue($j.$column, $value); 209 $span++; 210 } 211 $column++; 212 } 213 214 $fileName = iconv("utf-8", "gb2312", $fileName); 215 //重命名表 216 //$objPHPExcel->getActiveSheet()->setTitle('test'); 217 //设置活动单指数到第一个表,所以Excel打开这是第一个表 218 $objPHPExcel->setActiveSheetIndex(0); 219 header('Content-Type: application/vnd.ms-excel'); 220 header("Content-Disposition: attachment;filename=\"$fileName\""); 221 header('Cache-Control: max-age=0'); 222 223 $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5'); 224 $objWriter->save('php://output'); //文件通过浏览器下载 225 exit; 226 } 227 228 229 }
4.导出的EXCEL表如下: