柔晶美网络工作室

柔晶美网络工作室,倾心于web技术的博客站点

关注我 微信公众号

您现在的位置是: 首页 > 博客日记

Laravel6.* 安装excel3.1 导入excel文件的两种方法

2019-10-12 admin laravel  1711

创建项目:

composer create-project laravel/laravel weibo

安装excel 3.1

composer require maatwebsite/excel

编辑config/app.php文件,在providers里面添加一行:

'providers' => [
    /*
     * Package Service Providers...
     */
    Maatwebsite\Excel\ExcelServiceProvider::class,
]

在aliases里面添加一行:

'aliases' => [
    ...
    'Excel' => Maatwebsite\Excel\Facades\Excel::class,
]

生成配置文件(config/excel.php):

php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider"

编辑模型文件app/Imports/UsersImport.php备用,用来导入数据库:

namespace App\Imports;
use App\User;
use Illuminate\Support\Facades\Hash;
use Maatwebsite\Excel\Concerns\ToModel;
class UsersImport implements ToModel
{
    /**
     * @param array $row
     *
     * @return User|null
     */
    public function model(array $row)
    {
      //dd($row);//写入数据库使用
    }
}

导入mysql并自动创建表的内容:

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Imports\UsersImport;
use Maatwebsite\Excel\Facades\Excel;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
class UsersController extends Controller
{
  //文件上传方法
  public function photo(){
    return view('photo');
}
//处理文件上传方法
public function upload(Request $request){
    //获取上传文件
    //var_dump($request->hasFile('excel'));
    if($request->hasFile('excel')){
       //$path = $request->file('excel')->store('excel');
   //文件路径,需要开启php的php_fileinfo扩展,store 方法会自动生成唯一的 ID 作为文件名。文件的扩展名将通过检查文件的 MIME 类型来确定。该文件的路径和文件名会被 store 方法返回,以便后续数据库的存储使用。
      //echo $path;
        $originalName = $request->file('excel')->getClientOriginalName(); // 文件原名
        $ext = $request->file('excel')->getClientOriginalExtension(); //获取后缀名
        $sjkm = str_replace('.'.$ext,"",$originalName);//用于存储数据表名
	$sjkm = preg_replace('/\r|\n/', '', $sjkm);//去除换行
	$sjkm = str_replace(" ",'',$sjkm);//去除空格
	$sjkm = str_replace(".",'',$sjkm);//去除.
	$sjkm = str_replace("'",'',$sjkm);//去除单引号
      
     if ($ext == 'xls' or $ext == 'xlsx')
     {
        $request->file('excel')->move('./Uploads',$originalName); //上传文件移动至指定目录
        $path = './Uploads/'.$originalName;
        echo $path;
        echo '
开始读取excel
';
          $data = Excel::toArray(new UsersImport, $path);
          $data = $data[0];
         //dd($data);//简单的打印一下
		$result = $this->create_table($sjkm,$data);
		if ($result == 1 ){
        echo '导入数据成功!';
        }else{echo '导入数据库失败!
';}
        //Excel::import(new UsersImport,$path);//调用模型写入数据库
     }else{
     echo '文件格式不正确,请上传后缀为xls或xlsx的excel文件!
';
     back();
     }
    }else{
      echo '上传失败!';
      back();
    }
    }
  
	public function create_table($sjkm,$data)//创建数据表并写入数据
	{
		$tmp = $sjkm;
		$va = $data;
      if (Schema::hasTable($tmp))
{
  echo '数据表已存在,请先删除再上传!
';
  //Schema::dropIfExists($tmp);//删除数据表
}else{
		Schema::create($tmp, function(Blueprint $table) use ($tmp,$va)
  //create 方法会接收两个参数:一个是数据表的名称,另一个则是接收 $table(Blueprint 实例)的闭包。    
		{
			$fields = $va[0];  //列字段
			$table->increments('id');//主键
			foreach($fields as $key => $value){
				if($key == 0){
					$table->string($fields[$key])->nullable();//->unique(); 唯一,根据字段酌情使用
				}else{
					$table->string($fields[$key])->nullable();
				}
				//$fileds_count = $fileds_count + 1;
			}
		});
 
		$value_str= array();
		$id = 1;
		foreach($va as $key => $value){
			if($key != 0){
            foreach($value as $zdnr){//批量替换里面的值
                   $zdnr = preg_replace('/\r|\n/', '', $zdnr);//去除换行
		  		   $zdnr = str_replace(" ",'',$zdnr);//去除空格
				   $zdnr = str_replace("'",'',$zdnr);//去除单引号
				   $zdnr = str_replace(",",'',$zdnr);//去除,号
				   $zdnr = str_replace(",",'',$zdnr);//去除,号
                   $value_str[] = "'$zdnr'";
            }  
               //dd($value_str);
				$news = implode(",",$value_str);
				$news = "$id,".$news;
				DB::insert("insert into $tmp values ($news)");
				//$value_str = '';
				$value_str= array();
				$id = $id + 1;
			}
		}
		return 1;
	} 
}
}

上面的方法是直接在控制器获取excel数组,再用查询构造器写入,另一个比较好的方法是,用模型分批写入,这样可以用较小的内存,导入数据很大的excel表:

控制器:

    public function handle(Request $request)
    {
set_time_limit(60);//导入时长限制1分钟之内完成
ini_set('memory_limit', '100M');//我有内存 我豪啊
        $file = $request->file('file');//上传的文件
$bm = 'lssjb';//临时表名
        $xmmc = str_replace(' ','',$request->xmmc);//项目名称
        $zsbm = md5($xmmc);//生成唯一正式表名
$beizhu = $request->beizhu;//备注的查询说明
if (Schema::hasTable($bm)) {//如果临时数据表已存在,则删除
Schema::drop($bm);
    }
Excel::import(new LssjImport, $file);//用model分批导入到临时数据表lssjb
if (Schema::hasTable('lssjb')) {//如果临时数据表创建成功,则可以获取数据量,否则会报错!!!
        $sjl = LssjbModel::count();//数据量
}else{
//临时数据表创建失败,很可能是excel表格只有一行字段,没有数据,是用来填报的,因此需要用另一种方法导入
$array = Excel::toArray(new UsersImport, $file);
$keys = $array[0][0];
//var_dump($keys);
Schema::create('lssjb', function(Blueprint $table) use ($keys)//create接收两个参数:表名,$table(Blueprint 实例)的闭包。    
{
$table->increments('id');//主键
foreach($keys as $key => $value){
$value = str_replace(" ","",$value);//去除空格
if($key == 0){
$table->string($value)->nullable();//->unique(); 唯一,根据字段酌情使用
}else{
$table->string($value)->nullable();
}
}
});
$sjl = LssjbModel::count();//数据量
}
if ($sjl >= 0){
if (Schema::hasTable($zsbm)) {//如果该项目正式数据表已存在,则删除
Schema::drop($zsbm);
    }
Schema::rename($bm, $zsbm);//导入成功,更改临时表为正式表名
//写入bgsx
$cxtj = Schema::getColumnListing($zsbm);//获取所有字段
        array_splice($cxtj,0,1);//去除id
        $creatbgsx = new bgsxModel;
        $creatbgsx->bm = $zsbm;
        $creatbgsx->xmmc = $xmmc;
        $creatbgsx->sjl = $sjl;
        $creatbgsx->sfkf = '关闭';//默认关闭查询
        $creatbgsx->cxtj = $cxtj;//默认所有字段作为查询条件
        $creatbgsx->beizhu = $beizhu;
$creatbgsx->sftb = '关闭';//默认关闭填报
        $creatbgsx->tbzd = $cxtj;//默认所有字段开放填报
        $creatbgsx->save();
return $this->response()->success('导入完成,请设置查询条件!')->refresh();
        }else{
        return $this->response()->error('数据导入失败,请检查Excel内容是否合规!');
}
    }

模型文件:

namespace App\Models;
use App\Models\LssjbModel;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;//创建表
class LssjImport implements ToModel, WithBatchInserts, WithChunkReading, WithHeadingRow{
    public function model(array $row)
    {
if (!Schema::hasTable('lssjb')) {//如果临时数据表不存在,则创建
$keys = array_keys($row);
Schema::create('lssjb', function(Blueprint $table) use ($keys)//create接收两个参数:表名,$table(Blueprint 实例)的闭包。    
{
$table->increments('id');//主键
foreach($keys as $key => $value){
$value = str_replace(" ","",$value);//去除空格
if($key == 0){
$table->string($value)->nullable();//->unique(); 唯一,根据字段酌情使用
}else{
$table->string($value)->nullable();
}
}
});
}
        return new LssjbModel($row);//批量赋值到数据库
    }
    //批量导入1000条
    public function batchSize(): int    {
        return 1000;
    }
    //以1000条数据基准切割数据
    public function chunkSize(): int    {
        return 1000;
    }
}

当然,如果需要过滤数据,或者转换数据样式,可以在模型里设置。

文章评论


需要 登录 才能发表评论
热门评论
0条评论

暂时没有评论!