1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Excelデータをweb上でも管理するアプリ作成[laravel]

Posted at

題名の通り
Excelにあるデータをweb上でも管理するアプリを作成しました。

こちらにあるExcelファイルのデータをWeb上で管理します
Excelファイル
※Macだと登録シートでデータの登録、一覧表示、変更、削除機能が使えないです。

#要件
・Web上でも顧客管理がしたい。(バックアップも兼ねて)
・検索したい
・検索した結果をExcelに出力したい

#画面
スクリーンショット 2021-08-24 21.58.20.png

#機能
・ログイン
・Excelデータ取り込み & 出力
・検索

#実装
今回はExcelデータ取り込み & 出力のみ書いていこうと思います。
参考:検索機能

Web.php
Route::middleware('auth')->group(function () {
    Route::get('/', 'ClientsController@index')->name('client.index');
    Route::get('/export', 'ClientsController@export')->name('export');
    Route::post('/import', 'ClientsController@import')->name('import');
});
ClientsController.php
<?php

namespace App\Http\Controllers;

use App\Client;
use Illuminate\Http\Request;
use App\Exports\ClientExport;
use App\Imports\ClientImport;
use Maatwebsite\Excel\Facades\Excel;

class ClientsController extends Controller
{
    /**
     * 顧客一覧
     */
    public function index(Request $request)
    {

        $query = Client::query();

        $client_name = $request->client_name;

        //顧客名の値が存在&商品名の値が空ではなかった場合
        if ($request->has('client_name') && $client_name !== '') {
            $query->where('client_name', 'like', '%' . $client_name . '%')->get();
        }

        $datas = $query->paginate(15);


        return view('client.index', ['datas' => $datas, 'client_name' => $client_name]);
    }

    /**
     * Excelファイル出力
     */
    public function export(Request $request)
    {
        $client_name = $request->client_name;
        $export_name = $request->export_name;

        if (!isset($export_name)) {
            return back()->withErrors('ファイル名を入力して下さい');
        }

        if (!isset($client_name)) {
            $client_name = "";
        }

        return Excel::download(new ClientExport($client_name), $export_name . '.xlsx');
    }

    /**
     * Excelファイル取り込み
     */
    public function import(Request $request)
    {
        $file = $request->file('file');

        if (!isset($file)) {
            return back()->withErrors('ファイルを選択して下さい');
        }

        if ($file->getClientOriginalName() <> "顧客データ.xlsm") {
            return back()->withErrors('顧客データ.xlsmを選択して下さい');
        }
        $import = new ClientImport();
        $import->onlySheets('データ');  //シート指定

        Excel::import($import, $file);

        return back()->withStatus('保存しました'); //withStatus()は戻った時にメッセージを表示
    }
}


views\client\index.blade.php
@extends('layouts.app')

@section('content')

<!-- エラーメッセージ表示 -->
@if ($errors->any())
<div class="alert alert-danger">
    <ul>
        @foreach ($errors->all() as $error)
        <li>{{ $error }}</li>
        @endforeach
    </ul>
</div>
@endif

<!-- 成功メッセージ表示 -->
@if (session('status'))
<div class="alert alert-success" role="alert">
    {{ session('status') }}
</div>
@endif
 
<div class="client">
    <div class="container mt-4 offset-2 flex">
        <div class="a a1" style="width:400px;">
            <form class="search" enctype="multipart/form-data" action="{{route('client.index')}}" accept-charset="UTF-8" method="get">
                @csrf
                <div class="searchBox">
                    <div class="a2">
                        <h2 class="mr-2">顧客名</h2>
                        <input type="text" name="client_name" class="form-control" value="{{isset($client_name) ? $client_name : "" }}">
                    </div>
                    <div class="a2">
                        <h2 class="mr-2"> </h2>
                        <span class="input-group-btn">
                            <input type="submit" class="btn btn-success ml-4" value="検索">
                        </span>
                    </div>
                </div>

            </form>
        </div>
        <div class="a a2">
            <form action="{{ route('import') }}" method="POST" enctype="multipart/form-data">
                @csrf
                <div class="form-group">
                    <input type="file" name="file">
                    <button class="btn btn-success">&emsp;取込&emsp;</button>
                </div>
            </form>
            <form action="{{ route('export') }}" method="GET" enctype="multipart/form-data">
                @csrf
                    <div class="form-group" >
                        <input type="hidden" name="client_name" class="form-control" value="{{$client_name ? $client_name : "" }}">
                       <input type="text" name="export_name" placeholder="ファイル名を入力">
                        <button class="btn btn-secondary" style="width: 90px; margin-left: 121px;">出力</button>
                    </div>
            </form>
            <!-- <input type="submit" class="b btn btn-danger" value="登録"> -->
        </div>
    </div>
</div>


<div class="container mt-4">
    <div class="panel panel-default">
        <div class="panel-heading">全件{{$datas->total()}}</div>
        <div class="panel-body">
        </div>
        <table border="1" class="table" style="border-collapse: collapse">
            @foreach($datas as $data)
            <thead class="bg-success">
                <tr>
                    <th>名前</th>
                    <th>連絡先</th>
                    <th>メールアドレス</th>
                </tr>
            </thead>
            <tbody>

                <tr>
                    <td>{{$data->client_name}}</td>
                    <td>{{$data->client_PhoneNumber}}</td>
                    <td>{{$data->client_email}}</td>
                </tr>

            </tbody>
            @endforeach 
        </table>
        <!-- 検索結果を保持したままページネーションできる-->
        {{ $datas->appends(request()->input())->links() }}
    </div>
</div>
</div>
@endsection
app\Imports\ClientImport.php

<?php

namespace App\Imports;

use App\Client;
use Maatwebsite\Excel\Row;
use Maatwebsite\Excel\Concerns\OnEachRow;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Concerns\WithConditionalSheets;

class ClientImport implements OnEachRow, WithHeadingRow, WithMultipleSheets
{
    /**
     * トレイト
     */
    use WithConditionalSheets;

    /**
     * どのシートをインポートするか指定
     */
    public function conditionalSheets(): array
    {
        return [
            'データ' => new ClientImport()
        ];
    }

    /**
     * データ保存
     */
    public function OnRow(Row $row)
    {
        $row = $row->toArray();
        
        $client = Client::FirstOrNew(
            // 重複除外カラムを指定
            ['client_email' => $row['メールアドレス']],
            // データベースのカラムとエクセルのカラムを紐づけ
            [
                'client_PhoneNumber' => $row['連絡先'],
                'client_name' => $row['顧客名'],
                'type_id' => 1,
            ]
        );

        $client->save();
    }
}
app\Exports\ClientExport.php
<?php

namespace App\Exports;

use App\Client;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\FromCollection;

class ClientExport implements WithHeadings, FromCollection
{
    /**
     * コンストラクト
     */
    public function __construct(string $client_name)
    {
        $this->client_name = $client_name; // Where句のデータ
    }

    /**
     * 条件データ取得
     */
    public function collection()
    {
        return Client::where('client_name', 'like', '%' . $this->client_name . '%')->get(['client_name','client_PhoneNumber','client_email']);
    }

    /**
     * Excel1フィールド指定
     */
    public function headings(): array
    {
        return [
            '顧客名',
            '電話番号',
            'メールアドレス'
        ];
    }
}

#感想
・もっと工夫すればいいものが作れそうな気がする。
・出力したシートの名前もちゃんと設定できるようにしたらよかった。

今回はExcelファイルのデータをWeb上で管理するというのが目的だったので、いい感じにできたのではないのでしょうか。※実務で使うとなればまだまだですが・・・

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?