v2.0 Excel导入
2021-05-18优化
1、在view层加一个入口,打开upload的页面
- <?= Html::createLayer(["upload"],'excel批量导入', ['class' => 'btn btn-danger btn-outline','data-title'=>'excel批量导入']) ?>
也可以指定标题和窗口大小:
- <?= Html::createLayer(["import-member", "org_id" => $org_id], "<span>excel批量导入</span>", [
- "class" => "dropdown-item modify-selected-item",
- "data-title" => "批量导入成员",
- "data-height" => "570px"
- ]) ?>
2、在controller层加控制器:
- public function actionUpload(){
- if (Yii::$app->request->isPost){
- $projectId = Yii::$app->request->post("project_id");
- $path = date("Ymd")."/"; //后缀一定要加/
- $file = UploadedFile::getInstancesByName("file");
- if(!$file){
- Yii::$app->session->setFlash("error","未获取到提交的文件,请检查");
- return $this->render('upload');
- }
- $res = InvestmentContract::import($path,$file[0],"local",$projectId);
- if(!$res){
- Yii::$app->session->setFlash("success", "导入成功");
- }else{
- Yii::$app->session->setFlash("error", $res);
- }
- }
- return $this->render('upload');
- }
在model层添加:
use common\helpers\ExcelHelper;
use common\modules\attachment\components\UploadedFile;
use common\modules\attachment\models\Attachment;
- /**
- * excel导入
- * @param $uploadBaseLocalPath *文件上传后存储在本地的前缀
- * @param UploadedFile $uploadedFile *文件二进制流
- * @param string $drive *存储引擎,oss / local
- * @param int $projectId
- * @return bool|mixed
- * @throws \PhpOffice\PhpSpreadsheet\Exception
- * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
- */
- public static function import($uploadBaseLocalPath, UploadedFile $uploadedFile, $drive = "local", $projectId = 0)
- {
- // 先上传
- $uploadFile = Attachment::uploadFromPost($uploadBaseLocalPath, $uploadedFile, $drive);
- if ($uploadFile->extension == "xlsx") {
- $excelData = ExcelHelper::importOnlyXlsx(Yii::$app->storage->getFullPath($uploadFile->path), 2);
- } else {
- $excelData = ExcelHelper::import(Yii::$app->storage->getFullPath($uploadFile->path), 2);
- }
- // Excel的数据过滤
- $model = new self();
- foreach ($excelData as $k => $v) {
- if ($v[0] && $v[1]) {
- // 必须编号和名称都存在,否则不予处理
- // 当前是否存在
- $ifExist = self::find()->where(["code" => $v[0], "title" => $v[1], "project_id" => $projectId])->one();
- if (!$ifExist) {
- // 如果不存在,重新写入
- // p2($v);
- // 使用AR写入
- $_model = clone $model;
- $_model->code = strval($v[0]);// 转string
- $_model->title = $v[1];
- $_model->second_part = $v[2];
- $_model->contract_amount = $v[3];//DebrisHelper::floatNumber(
- $_model->temp_amount = $v[4];//DebrisHelper::floatNumber(
- $_model->no_cost_amount = $v[5]; //不需要转换成万元
- $_model->sign_amount_hs = $v[6];
- $_model->sign_amount_bhs = $v[7]; //不需要转换成万元
- $_model->sign_time = $v[8];
- $_model->project_id = $projectId;
- // p($_model);
- if (!$_model->save()) {
- return current($_model->firstErrors);
- };
- // 使用原生写入
- // Yii::$app->db->createCommand()->insert(self::tableName(), [
- // 'name' => $name,
- // 'project_id' => $projectId,
- // 'parent_id' => $bclassid
- // ])->execute();
- }
- }
- }
- return false;
- }
如果有父级编号:
- /**
- * excel导入
- * @param $uploadBaseLocalPath *文件上传后存储在本地的前缀
- * @param UploadedFile $uploadedFile *文件二进制流
- * @param string $drive *存储引擎,oss / local
- * @param int $projectId
- * @return bool|mixed
- * @throws \PhpOffice\PhpSpreadsheet\Exception
- * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
- */
- public static function import($uploadBaseLocalPath, UploadedFile $uploadedFile, $drive = "local", $projectId = 0)
- {
- // 先上传
- $uploadFile = Attachment::uploadFromPost($uploadBaseLocalPath, $uploadedFile, $drive);
- if ($uploadFile->extension == "xlsx") {
- $excelData = ExcelHelper::importOnlyXlsx(Yii::$app->storage->getFullPath($uploadFile->path), 2);
- } else {
- $excelData = ExcelHelper::import(Yii::$app->storage->getFullPath($uploadFile->path), 2);
- }
- // Excel的数据过滤
- $model = new self();
- foreach ($excelData as $k => $v) {
- if ($v[0] && $v[2]) {
- // 必须编号和名称都存在,否则不予处理
- // 当前是否存在
- $ifExist = self::find()->where(["code" => $v[0]])->one();
- if ($v[1]) {
- // 如果有父编号
- $parentId = self::find()->select("class_id")->where(["code" => $v[1]])->scalar();
- } else {
- $parentId = 0;
- }
- if (!$ifExist) {
- // 如果不存在,重新写入
- // 使用AR写入
- $_model = clone $model;
- } else {
- // 如果存在就更新
- $_model = $ifExist;
- }
- $_model->code = strval($v[0]);// 转string
- $_model->parent_class_id = intval($parentId);// 转string
- $_model->title = $v[2];
- $_model->project_id = $projectId;
- if (!$_model->save()) {
- return current($_model->firstErrors);
- };
- }
- }
- return false;
- }
3、upload的view:
- <?php
- use common\helpers\Html;
- use backend\widgets\ActiveForm;
- ?>
- <div class="page material-create">
- <div class="page-content">
- <?php $form = ActiveForm::begin([
- 'options' => [
- "enctype" => "multipart/form-data",
- ],
- ]); ?>
- <div class="panel">
- <div class="panel-body">
- <div class="form-group form-material">
- <label class="col-form-label" for="select">选择项目</label>
- <?= Html::dropDownList("project_id", null, \common\modules\project\models\Project::getDropDownList(), ['encode' => false, 'class' => 'form-control','prompt' => '不限项目']) ?>
- </div>
- <div class="form-group form-material">
- <label class="col-form-label" for="inputFile">文件域</label>
- <input type="text" class="form-control" placeholder="请选择文件.." readonly="">
- <input type="file" id="inputFile" name="file">
- </div>
- </div>
- <div class="panel-footer">
- <button class="btn btn-primary">开始导入</button>
- </div>
- </div>
- <?php ActiveForm::end(); ?>
- </div>
- </div>
v2.0 excel 导出
view层添加:
- <?= Html::a('excel导出',["export"], ['class' => 'btn btn-success btn-outline mr-5','data-title'=>'excel批量导出']) ?>
controller控制器添加:
- /**
- * Excel导出
- * @return bool
- * @throws \PhpOffice\PhpSpreadsheet\Exception
- * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
- */
- public function actionExport()
- {
- $list = ProjectProphaseScheduleCommon::find()->with("parent")->all();
- $header = [
- ['编号', 'code', 'text', 'attribute' => ['width' => 8]],
- ['父编号', 'parent_id', 'function', function ($model) {
- return $model["parent_id"] ? $model->parent->code : $model["parent_id"];
- }, 'attribute' => ['width' => 8]],
- ['副标题', 'sub_title', 'text', 'attribute' => ['width' => 10]],
- ['标题', 'title', 'text', 'attribute' => ['width' => 80,'wrap' => true]],
- ['说明', 'description', 'text', 'attribute' => ['width' => 10]],
- ['前端边框样式', 'type', 'text', 'attribute' => ['width' => 10]],
- ['是否展示子级', 'is_show_children', 'text', 'attribute' => ['width' => 10]],
- ];
- ExcelHelper::exportData($list, $header,"拆迁前期公共配置项导出");
- return $this->goBack();
- }
- // [名称, 字段名, 类型, 类型规则]
- $header = [
- ['ID', 'id', 'text'],
- ['手机号码', 'mobile'], // 规则不填默认text
- ['openid', 'fans.openid', 'text'],
- ['昵称', 'fans.nickname', 'text'],
- ['关注/扫描', 'type', 'selectd', [1 => '关注', 2 => '扫描']],
- ['性别', 'sex', 'function', function($model){
- return $model['sex'] == 1 ? '男' : '女';
- }],
- ['创建时间', 'created_at', 'date', 'Y-m-d'],
- ];
- $list = [
- [
- 'id' => 1,
- 'type' => 1,
- 'fans' => [
- 'openid' => '123',
- 'nickname' => '昵称',
- ],
- 'sex' => 1,
- 'create_at' => time(),
- ]
- ];
- // attribute传参表格列宽度 ,width 设置列宽度,wrap是否自动换行
- $list = ProjectProphaseScheduleCommon::find()->with("parent")->all();
- $header = [
- ['编号', 'code', 'text', 'attribute' => ['width' => 20]],
- ['父编号', 'parent_id', 'function', function ($model) {
- return $model["parent_id"] ? $model->parent->code : $model["parent_id"];
- }],
- ['副标题', 'sub_title', 'text'],
- ['标题', 'title', 'text'],
- ['说明', 'description', 'text'],
- ['前端边框样式', 'type', 'text'],
- ['是否展示子级', 'is_show_children', 'text'],
- ];
- ExcelHelper::exportData($list, $header);
- // 简单使用
- return ExcelHelper::exportData($list, $header);
- // 定制 默认导出xlsx 支持 : xlsx/xls/html/csv
- return ExcelHelper::exportData($list, $header, '测试', 'xlsx');
1、在view层加一个入口,打开upload的页面
- <?= Html::createLayer(["upload"],'excel批量导入', ['class' => 'btn btn-danger btn-outline','data-title'=>'excel批量导入']) ?>
2、在controller层加控制器:
- public function actionUpload(){
- if (Yii::$app->request->isPost){
- $projectId = Yii::$app->request->post("project_id");
- $path = date("Ymd")."/"; //后缀一定要加/
- $file = UploadedFile::getInstancesByName("file");
- if(!$file){
- Yii::$app->session->setFlash("error","未获取到提交的文件,请检查");
- return $this->render('upload');
- }
- $uploadFile = Attachment::uploadFromPost($path,$file[0],"local");
- if($uploadFile->extension == "xlsx"){
- $excelData = ExcelHelper::importOnlyXlsx( Yii::$app->storage->getFullPath($uploadFile->path),2);
- }else{
- $excelData = ExcelHelper::import( Yii::$app->storage->getFullPath($uploadFile->path),2);
- }
- // Excel的数据过滤
- $data = [];
- foreach ($excelData as $k => $v){
- if($v[0]){
- // 过滤名称为空的物资
- $data[] = $v;
- }
- }
- $excelData = $data;
- // Excel数据过滤完成
- if($excelData && is_array($excelData)){
- foreach ($excelData as $k =>&$v){
- $v[] = $projectId;
- }
- Yii::$app->db->createCommand()->batchInsert(Material::tableName(), ['title', 'branch','subentry','category','specification','unit','cmt_total','cmt_cur_total','cmt_alm','project_id'], $excelData)->execute();
- Yii::$app->session->setFlash("success","导入成功");
- }else{
- Yii::$app->session->setFlash("error","读取失败,请检查文件");
- }
- }
- return $this->render('upload');
- }
3、upload的view:
use common\helpers\ExcelHelper;
use common\modules\attachment\components\UploadedFile;
use common\modules\attachment\models\Attachment;
- <?php
- use common\helpers\Html;
- use backend\widgets\ActiveForm;
- ?>
- <div class="page material-create">
- <div class="page-content">
- <?php $form = ActiveForm::begin([
- 'options' => [
- "enctype" => "multipart/form-data",
- ],
- ]); ?>
- <div class="panel">
- <div class="panel-body">
- <div class="form-group form-material">
- <label class="col-form-label" for="select">选择项目</label>
- <?= Html::dropDownList("project_id", null, \common\modules\project\models\Project::getDropDownList(), ['encode' => false, 'class' => 'form-control']) ?>
- </div>
- <div class="form-group form-material">
- <label class="col-form-label" for="inputFile">文件域</label>
- <input type="text" class="form-control" placeholder="请选择文件.." readonly="">
- <input type="file" id="inputFile" name="file">
- </div>
- </div>
- <div class="panel-footer">
- <button class="btn btn-primary">开始导入</button>
- </div>
- </div>
- <?php ActiveForm::end(); ?>
- </div>
- </div>
1、报错:The 'gridview' module MUST be setup in your Yii configuration file.
config中添加module:
- 'modules' => [
- 'gridview' => [
- 'class' => 'kartik\grid\Module'
- ],
- ...
- ]
示例:excel导出
use backend\widgets\export\ExportMenu;
尽量不使用导出为excel2007的,宽度不生效,所以在ExportMenu中作了判断处理,如果强制加setWidth,在excel2007中会出现未写入,空白表格,有熟悉的小伙伴有解决方案可直接留言,谢谢
- $gridColumns = [
- // ['class' => 'kartik\grid\SerialColumn'],
- [
- 'attribute' => 'parent_id',
- 'label' => '上级部门',
- 'vAlign' => 'middle',
- 'width' => '18',
- 'value' => function ($model, $key, $index, $widget) {
- return $model->parentName;
- },
- 'format' => 'raw'
- ],
- [
- 'attribute' => 'department_name',
- 'vAlign' => 'middle',
- 'width' => '18',
- 'format' => 'raw'
- ],
- 'level',
- ];
- echo ExportMenu::widget([
- 'dataProvider' => $dataProvider,
- 'columns' => $gridColumns,
- 'filename' => '部门列表',
- 'autoWidth' => false, //如果上面传了width,这里的自适应宽度,必须为false
- 'exportConfig' => [
- // ExportMenu::FORMAT_HTML => false,
- // ExportMenu::FORMAT_CSV => false,
- // ExportMenu::FORMAT_PDF => false,
- // ExportMenu::FORMAT_TEXT => false,
- // ExportMenu::FORMAT_EXCEL_X => false,
- ExportMenu::FORMAT_PDF => [
- 'pdfConfig' => [
- 'options' => [
- 'ignore_invalid_utf8' => true,
- 'tabSpaces' => 4,
- 'autoLangToFont' => true, //这几个配置加上可以显示中文
- 'autoScriptToLang' => true, //这几个配置加上可以显示中文
- 'autoVietnamese' => true, //这几个配置加上可以显示中文
- 'autoArabic' => true, //这几个配置加上可以显示中文
- ]
- ],
- ],
- ],
- // 'showConfirmAlert' => false //是否弹出确认框
- ]);
示例:excel导入(参考 用户管理 - 部门管理)
controller加入:
- public function actions()
- {
- return [
- 'import' => [
- 'class' => 'backend\\actions\\AjaxImportAction',
- 'entity' => Department::className(),
- // 'function' => 'import', //默认为import,选填,导入的方法,多个可添加不同的方法
- ],
- ];
- }
model中添加import方法:
- /**
- * 导入
- * @param $uploadfile * 上传的文件完整物理路径
- * @param $post * 导入的post表单中传递的参数,如类型://1是质量问题,2是安全问题
- * @return bool
- * @throws \PhpOffice\PhpSpreadsheet\Exception
- * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
- */
- function import($uploadfile,$post){
- $type = $post['type'];
- $tool = new \common\components\Tool();
- $excel = $tool->readExcel($uploadfile,2); //读取excel内容,从第二行开始,第一行是标题
- if($excel["errcode"] != 0){
- return $excel["errmsg"];
- }
- $data = $excel["data"];
- $model = new self();
- $projectId = Yii::$app->session->get("project_id");
- foreach ($data as $k => $v){
- $parentName = $v[1]; //父级名称
- $name = $v[2]; //部门名称
- $level = $v[3]; //部门级别
- if(!$name){
- // 如果没有部门名称,跳出循环
- continue;
- }
- $m = clone $model;
- // 重要,加条件project_id
- $r = $model->find()->where(["department_name"=>$name,"project_id"=>$projectId])->one();
- if($r){
- $m = $r;
- }
- // 重要,加条件project_id
- $parentId = $m->find()->select('department_id')->where(['department_name' => $parentName,"project_id"=>$projectId])->scalar();
- if($parentId){
- $m->parent = $parentId;
- }else{
- $newM = clone $model;
- $newM->department_name = $parentName;
- $newM->project_id = $projectId;
- $newM->save();
- $m->parent = $newM->department_id;
- }
- $m->project_id = $projectId;
- $m->department_name = $name;
- $m->level = $level;
- $m->save();
- };
- return false;
- }
- echo ExportMenu::widget([
- 'dataProvider' => $dataProvider,
- 'columns' => $gridColumns,
- 'filename' => '库存列表',
- 'clearBuffers' => true,
- 'autoWidth' => false,
- 'dropdownOptions' => [
- 'label' => '选择导出格式',
- 'class' => 'btn btn-secondary'
- ],
- 'columnSelectorOptions'=>[
- 'label' => '选择导出字段',
- // 'icon' => '<i class="glyphicon glyphicon-heart"></i>',
- // 'title' => '鼠标放上去显示的文字'
- ],
- 'exportConfig' => [
- // ExportMenu::FORMAT_HTML => false,
- ExportMenu::FORMAT_CSV => false,
- // ExportMenu::FORMAT_PDF => false,
- // ExportMenu::FORMAT_TEXT => false,
- ExportMenu::FORMAT_EXCEL_X => false,
- ExportMenu::FORMAT_PDF => [
- 'pdfConfig' => [
- 'options' => [
- 'ignore_invalid_utf8' => true,
- 'tabSpaces' => 4,
- 'autoLangToFont' => true, //这几个配置加上可以显示中文
- 'autoScriptToLang' => true, //这几个配置加上可以显示中文
- 'autoVietnamese' => true, //这几个配置加上可以显示中文
- 'autoArabic' => true, //这几个配置加上可以显示中文
- ]
- ],
- ],
- ],
- ]);