Browse Source

feat: 改写和完善导出功能

wechat_public_accounts
iron 5 years ago
parent
commit
de3877eddf
  1. 61
      common/models/Category.php
  2. 42
      common/models/CategorySearch.php
  3. 3
      composer.json
  4. 356
      composer.lock
  5. 68
      kcadmin/controllers/CategoryController.php
  6. 43
      kcadmin/views/category/index.php
  7. 124
      vendor/blobt/grid/GridView.php
  8. 246
      vendor/iron/grid/ActionColumn.php
  9. 958
      vendor/iron/widget/Excel.php

61
common/models/Category.php

@ -17,7 +17,8 @@ use yii\behaviors\TimestampBehavior;
* @property int $created_at
* @property int $updated_at
*/
class Category extends \yii\db\ActiveRecord {
class Category extends \yii\db\ActiveRecord
{
const ICON_TYPE_BOOSTARAP = 1;
const ICON_TYPE_AWESOME = 2;
@ -30,16 +31,18 @@ class Category extends \yii\db\ActiveRecord {
/**
* {@inheritdoc}
*/
public static function tableName() {
public static function tableName()
{
return 'category';
}
/**
* {@inheritdoc}
*/
public function rules() {
public function rules()
{
return [
[['icon_type','cat_name','created_at'], 'required'],
[['icon_type', 'cat_name', 'created_at'], 'required'],
[['icon_type', 'sort_order', 'created_at', 'updated_at'], 'integer'],
[['description'], 'string'],
[['cat_name', 'icon'], 'string', 'max' => 64],
@ -49,7 +52,8 @@ class Category extends \yii\db\ActiveRecord {
/**
* {@inheritdoc}
*/
public function attributeLabels() {
public function attributeLabels()
{
return [
'id' => 'ID',
'cat_name' => '类名',
@ -62,7 +66,52 @@ class Category extends \yii\db\ActiveRecord {
];
}
public function behaviors() {
public static function columns()
{
return [
[
'class' => 'blobt\grid\CheckboxColumn',
'width' => '2%',
'align' => 'center'
],
[
'attribute' => 'id',
'width' => '5%',
'align' => 'center'
],
[
'attribute' => 'created_at',
'width' => '7%',
'format' => 'date'
],
[
'attribute' => 'cat_name',
'width' => '13%',
],
[
'attribute' => 'icon',
'width' => '5%',
],
[
'attribute' => 'icon_type',
'width' => '7%',
'showConstText' => true
],
[
'attribute' => 'description',
'enableSorting' => false,
'format' => 'ntext',
'width' => '50%',
],
[
'class' => 'iron\grid\ActionColumn',
'align' => 'center',
],
];
}
public function behaviors()
{
return [
TimestampBehavior::className()
];

42
common/models/CategorySearch.php

@ -2,24 +2,27 @@
namespace common\models;
use common\models\Category;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use common\models\Category;
use yii\helpers\ArrayHelper;
/**
* CategorySearch represents the model behind the search form of `\common\models\Category`.
*/
class CategorySearch extends Category {
class CategorySearch extends Category
{
public function attributes() {
public function attributes()
{
return ArrayHelper::merge(['created_at_range'], parent::attributes());
}
/**
* {@inheritdoc}
*/
public function rules() {
public function rules()
{
return [
[['id', 'icon_type', 'sort_order', 'created_at', 'updated_at'], 'integer'],
[['cat_name', 'icon', 'description', 'created_at_range'], 'safe'],
@ -29,11 +32,25 @@ class CategorySearch extends Category {
/**
* {@inheritdoc}
*/
public function scenarios() {
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
public function allData($params)
{
$query = Category::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => false,
'sort' => false
]);
$this->load($params);
return $this->filter($query, $dataProvider);
}
/**
* Creates data provider instance with search query applied
*
@ -41,7 +58,8 @@ class CategorySearch extends Category {
*
* @return ActiveDataProvider
*/
public function search($params) {
public function search($params)
{
$query = Category::find();
// add conditions that should always apply here
@ -57,8 +75,12 @@ class CategorySearch extends Category {
]
],
]);
$this->load($params);
return $this->filter($query, $dataProvider);
}
private function filter($query, $dataProvider)
{
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
@ -66,7 +88,7 @@ class CategorySearch extends Category {
return $dataProvider;
}
// grid filtering conditions
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'icon_type' => $this->icon_type,
@ -76,8 +98,8 @@ class CategorySearch extends Category {
]);
$query->andFilterWhere(['like', 'cat_name', $this->cat_name])
->andFilterWhere(['like', 'icon', $this->icon])
->andFilterWhere(['like', 'description', $this->description]);
->andFilterWhere(['like', 'icon', $this->icon])
->andFilterWhere(['like', 'description', $this->description]);
if ($this->created_at_range) {
$arr = explode(' ~ ', $this->created_at_range);

3
composer.json

@ -13,7 +13,8 @@
"require": {
"php": ">=7.1.0",
"yiisoft/yii2": "~2.0.14",
"yiisoft/yii2-bootstrap": "^2.0@dev"
"yiisoft/yii2-bootstrap": "^2.0@dev",
"moonlandsoft/yii2-phpexcel": "*"
},
"repositories": {
"asset_packagist": {

356
composer.lock

@ -4,14 +4,14 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f3ddaead9bc7b0924e8f9ccf68c842ff",
"content-hash": "3f23bd556b4acf6c2728200635bf4eb6",
"packages": [
{
"name": "bower-asset/bootstrap",
"version": "v3.4.1",
"source": {
"type": "git",
"url": "https://github.com/twbs/bootstrap.git",
"url": "git@github.com:twbs/bootstrap.git",
"reference": "68b0d231a13201eb14acd3dc84e51543d16e5f7e"
},
"dist": {
@ -153,7 +153,7 @@
"version": "v1.3.2",
"source": {
"type": "git",
"url": "https://github.com/bestiejs/punycode.js.git",
"url": "git@github.com:bestiejs/punycode.js.git",
"reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3"
},
"dist": {
@ -322,6 +322,356 @@
],
"time": "2018-02-23T01:58:20+00:00"
},
{
"name": "markbaker/complex",
"version": "1.4.7",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPComplex.git",
"reference": "1ea674a8308baf547cbcbd30c5fcd6d301b7c000"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/1ea674a8308baf547cbcbd30c5fcd6d301b7c000",
"reference": "1ea674a8308baf547cbcbd30c5fcd6d301b7c000",
"shasum": ""
},
"require": {
"php": "^5.6.0|^7.0.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.3",
"phpcompatibility/php-compatibility": "^8.0",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "2.*",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^4.8.35|^5.4.0",
"sebastian/phpcpd": "2.*",
"squizlabs/php_codesniffer": "^3.3.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Complex\\": "classes/src/"
},
"files": [
"classes/src/functions/abs.php",
"classes/src/functions/acos.php",
"classes/src/functions/acosh.php",
"classes/src/functions/acot.php",
"classes/src/functions/acoth.php",
"classes/src/functions/acsc.php",
"classes/src/functions/acsch.php",
"classes/src/functions/argument.php",
"classes/src/functions/asec.php",
"classes/src/functions/asech.php",
"classes/src/functions/asin.php",
"classes/src/functions/asinh.php",
"classes/src/functions/atan.php",
"classes/src/functions/atanh.php",
"classes/src/functions/conjugate.php",
"classes/src/functions/cos.php",
"classes/src/functions/cosh.php",
"classes/src/functions/cot.php",
"classes/src/functions/coth.php",
"classes/src/functions/csc.php",
"classes/src/functions/csch.php",
"classes/src/functions/exp.php",
"classes/src/functions/inverse.php",
"classes/src/functions/ln.php",
"classes/src/functions/log2.php",
"classes/src/functions/log10.php",
"classes/src/functions/negative.php",
"classes/src/functions/pow.php",
"classes/src/functions/rho.php",
"classes/src/functions/sec.php",
"classes/src/functions/sech.php",
"classes/src/functions/sin.php",
"classes/src/functions/sinh.php",
"classes/src/functions/sqrt.php",
"classes/src/functions/tan.php",
"classes/src/functions/tanh.php",
"classes/src/functions/theta.php",
"classes/src/operations/add.php",
"classes/src/operations/subtract.php",
"classes/src/operations/multiply.php",
"classes/src/operations/divideby.php",
"classes/src/operations/divideinto.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with complex numbers",
"homepage": "https://github.com/MarkBaker/PHPComplex",
"keywords": [
"complex",
"mathematics"
],
"time": "2018-10-13T23:28:42+00:00"
},
{
"name": "markbaker/matrix",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPMatrix.git",
"reference": "5348c5a67e3b75cd209d70103f916a93b1f1ed21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/5348c5a67e3b75cd209d70103f916a93b1f1ed21",
"reference": "5348c5a67e3b75cd209d70103f916a93b1f1ed21",
"shasum": ""
},
"require": {
"php": "^5.6.0|^7.0.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"phpcompatibility/php-compatibility": "dev-master",
"phploc/phploc": "^4",
"phpmd/phpmd": "dev-master",
"phpunit/phpunit": "^5.7",
"sebastian/phpcpd": "^3.0",
"squizlabs/php_codesniffer": "^3.0@dev"
},
"type": "library",
"autoload": {
"psr-4": {
"Matrix\\": "classes/src/"
},
"files": [
"classes/src/functions/adjoint.php",
"classes/src/functions/antidiagonal.php",
"classes/src/functions/cofactors.php",
"classes/src/functions/determinant.php",
"classes/src/functions/diagonal.php",
"classes/src/functions/identity.php",
"classes/src/functions/inverse.php",
"classes/src/functions/minors.php",
"classes/src/functions/trace.php",
"classes/src/functions/transpose.php",
"classes/src/operations/add.php",
"classes/src/operations/directsum.php",
"classes/src/operations/subtract.php",
"classes/src/operations/multiply.php",
"classes/src/operations/divideby.php",
"classes/src/operations/divideinto.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with matrices",
"homepage": "https://github.com/MarkBaker/PHPMatrix",
"keywords": [
"mathematics",
"matrix",
"vector"
],
"time": "2019-10-06T11:29:25+00:00"
},
{
"name": "moonlandsoft/yii2-phpexcel",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/moonlandsoft/yii2-phpexcel.git",
"reference": "ccf28ff8ce2c665a7769dd6516098b4a35c8c309"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/moonlandsoft/yii2-phpexcel/zipball/ccf28ff8ce2c665a7769dd6516098b4a35c8c309",
"reference": "ccf28ff8ce2c665a7769dd6516098b4a35c8c309",
"shasum": ""
},
"require": {
"phpoffice/phpspreadsheet": "*",
"yiisoft/yii2": "*"
},
"type": "yii2-extension",
"autoload": {
"psr-4": {
"moonland\\phpexcel\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Moh Khoirul Anam",
"email": "moh.khoirul.anaam@gmail.com"
}
],
"description": "Exporting PHP to Excel or Importing Excel to PHP",
"keywords": [
"excel",
"export",
"extension",
"import",
"xls",
"yii2"
],
"time": "2019-01-31T14:14:03+00:00"
},
{
"name": "phpoffice/phpspreadsheet",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "13eaeb39cfaed16409f7fd9d1968e08be7bfd7e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/13eaeb39cfaed16409f7fd9d1968e08be7bfd7e5",
"reference": "13eaeb39cfaed16409f7fd9d1968e08be7bfd7e5",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"markbaker/complex": "^1.4",
"markbaker/matrix": "^1.1",
"php": "^7.1",
"psr/simple-cache": "^1.0"
},
"require-dev": {
"dompdf/dompdf": "^0.8.0",
"friendsofphp/php-cs-fixer": "@stable",
"jpgraph/jpgraph": "^4.0",
"mpdf/mpdf": "^7.0.0",
"phpcompatibility/php-compatibility": "^8.0",
"phpunit/phpunit": "^7.5",
"squizlabs/php_codesniffer": "^3.3",
"tecnickcom/tcpdf": "^6.2"
},
"suggest": {
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
"jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
},
"type": "library",
"autoload": {
"psr-4": {
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Maarten Balliauw",
"homepage": "https://blog.maartenballiauw.be"
},
{
"name": "Mark Baker",
"homepage": "https://markbakeruk.net"
},
{
"name": "Franck Lefevre",
"homepage": "https://rootslabs.net"
},
{
"name": "Erik Tilt"
},
{
"name": "Adrien Crivelli"
}
],
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
"keywords": [
"OpenXML",
"excel",
"gnumeric",
"ods",
"php",
"spreadsheet",
"xls",
"xlsx"
],
"time": "2019-10-31T23:52:20+00:00"
},
{
"name": "psr/simple-cache",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"time": "2017-10-23T01:57:42+00:00"
},
{
"name": "yiisoft/yii2",
"version": "dev-master",

68
kcadmin/controllers/CategoryController.php

@ -2,9 +2,11 @@
namespace kcadmin\controllers;
use common\models\Cat;
use Yii;
use common\models\Category;
use common\models\CategorySearch;
use yii\helpers\Html;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
@ -12,12 +14,15 @@ use yii\filters\VerbFilter;
/**
* CategoryController implements the CRUD actions for Category model.
*/
class CategoryController extends Controller {
class CategoryController extends Controller
{
public $enableCsrfValidation = false;
/**
* {@inheritdoc}
*/
public function behaviors() {
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
@ -28,24 +33,45 @@ class CategoryController extends Controller {
];
}
public function actions() {
public function actions()
{
return [
'test'=>[
'class'=>'iron\actions\UploadAction',
'test' => [
'class' => 'iron\actions\UploadAction',
]
];
}
public function actionExport()
{
$searchModel = new CategorySearch();
$params = Yii::$app->request->queryParams;
if ($params['page-type'] == 'all') {
$dataProvider = $searchModel->allData($params);
} else {
$dataProvider = $searchModel->search($params);
}
\iron\widget\Excel::export([
'models' => $dataProvider->getModels(),
'format' => 'Xlsx',
'asAttachment' => true,
'fileName' => "category" . "-" . date('Y-m-d H/i/s', time()),
'columns' => Category::columns()
]);
}
/**
* Lists all Category models.
* @return mixed
*/
public function actionIndex() {
public function actionIndex()
{
$searchModel = new CategorySearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'columns' => Category::columns()
]);
}
@ -55,9 +81,10 @@ class CategoryController extends Controller {
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionView($id) {
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
'model' => $this->findModel($id),
]);
}
@ -66,7 +93,8 @@ class CategoryController extends Controller {
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate() {
public function actionCreate()
{
$model = new Category();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
@ -74,7 +102,7 @@ class CategoryController extends Controller {
}
return $this->render('create', [
'model' => $model,
'model' => $model,
]);
}
@ -85,7 +113,8 @@ class CategoryController extends Controller {
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionUpdate($id) {
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
@ -93,7 +122,7 @@ class CategoryController extends Controller {
}
return $this->render('update', [
'model' => $model,
'model' => $model,
]);
}
@ -104,7 +133,8 @@ class CategoryController extends Controller {
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionDelete($id) {
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
@ -113,7 +143,8 @@ class CategoryController extends Controller {
/**
*
*/
public function actionDeletes() {
public function actionDeletes()
{
//获取前端post的记录id
$ids = Yii::$app->request->post('ids');
}
@ -125,7 +156,8 @@ class CategoryController extends Controller {
* @return Category the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id) {
protected function findModel($id)
{
if (($model = Category::findOne($id)) !== null) {
return $model;
}

43
kcadmin/views/category/index.php

@ -11,9 +11,11 @@ use blobt\grid\GridView;
$this->title = 'Categories';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="row">
<div class="col-xs-12">
<?= Html::a('test-export','export',['class'=>'btn btn-default'])?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filter' => $this->render("_search", ['model' => $searchModel]),
@ -27,46 +29,7 @@ $this->params['breadcrumbs'][] = $this->title;
"url" => "/category/others"
],
],
'columns' => [
[
'class' => 'blobt\grid\CheckboxColumn',
'width' => '2%',
'align' => 'center'
],
[
'attribute' => 'id',
'width' => '5%',
'align' => 'center'
],
[
'attribute' => 'created_at',
'width' => '7%',
'format' => 'date'
],
[
'attribute' => 'cat_name',
'width' => '13%',
],
[
'attribute' => 'icon',
'width' => '5%',
],
[
'attribute' => 'icon_type',
'width' => '7%',
'showConstText' => true
],
[
'attribute' => 'description',
'enableSorting' => false,
'format' => 'ntext',
'width' => '50%',
],
[
'class' => 'blobt\grid\ActionColumn',
'align' => 'center',
],
],
'columns' => $columns
]);
?>
</div>

124
vendor/blobt/grid/GridView.php

@ -43,7 +43,8 @@ use blobt\web\GridViewAsset;
* @email 380255922@qq.com
* @created Aug 13, 2019
*/
class GridView extends BaseListView {
class GridView extends BaseListView
{
/**
* @var string 渲染列数据的类,默认是'yii\grid\DataColumn'
@ -221,7 +222,15 @@ class GridView extends BaseListView {
<div class="col-sm-3">
{batch}
<a href="create" class="btn btn-default"><i class="fa fa-plus"></i>添加</a>
<button type="button" class="btn btn-default"><i class="fa fa-file-excel-o"></i>导出</button>
<!-- <a href="#" data-url='export' class="export btn btn-default"><i class="fa fa-file-excel-o"></i>导出</a>-->
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><i class="fa fa-file-excel-o"></i>导出</button>
<ul class="dropdown-menu" role="menu">
<li> <a class="export-page" href="#" data-url="export">本页</a></li>
<li> <a class="export-all" href="#" data-url="export">全部</a></li>
</ul>
</div>
<!-- <button type="button" id="export" class="btn btn-default"><i class="fa fa-file-excel-o"></i>导出</button>-->
</div>
<div class="col-sm-9">
{filter}
@ -262,7 +271,8 @@ HTML;
* 初始化必须的属性和每个列对象
* @return
*/
public function init() {
public function init()
{
parent::init();
if ($this->formatter === null) {
$this->formatter = Yii::$app->getFormatter();
@ -276,21 +286,24 @@ HTML;
$this->initColumns();
}
public function run() {
public function run()
{
$view = $this->getView();
GridViewAsset::register($view);
$this->registerGridJs();
$this->registerIcheckJs();
$this->registerConfirmJs();
$this->registerExportJs();
parent::run();
}
/**
* 注册GridView Js
*/
protected function registerGridJs() {
protected function registerGridJs()
{
$options = Json::htmlEncode(['filterUrl' => Url::to(Yii::$app->request->url),
'filterSelector' => $this->filterSelector]);
'filterSelector' => $this->filterSelector]);
$id = $this->options['id'];
$this->getView()->registerJs("jQuery('#$id').yiiGridView($options);");
}
@ -298,7 +311,8 @@ HTML;
/**
* 注册icheck Js
*/
protected function registerIcheckJs() {
protected function registerIcheckJs()
{
$js = <<<SCRIPT
$('.dataTable input[type="checkbox"]').iCheck({
checkboxClass: 'icheckbox_flat-blue',
@ -324,7 +338,8 @@ SCRIPT;
/**
* 注册批量操作js
*/
protected function registerBatchJs() {
protected function registerBatchJs()
{
$js = <<<SCRIPT
$("a.batch_item").click(function(){
var url = $(this).data("url");
@ -356,7 +371,8 @@ SCRIPT;
$this->getView()->registerJs($js);
}
protected function registerConfirmJs() {
protected function registerConfirmJs()
{
$js = <<<SCRIPT
$("a[alertify-confirm]").click(function(){
var message = $(this).attr('alertify-confirm');
@ -381,11 +397,35 @@ SCRIPT;
$this->getView()->registerJs($js);
}
protected function registerExportJs()
{
$js = <<<SCRIPT
$("a.export-all").click(function(){
var url = $(this).data("url")+location.search;
// var params = location.search.split("&");
// var new_params = [];
// var ret = /page=\d*/
// $.each(params,function(index,value){
// if(!ret.test(value)){
// new_params.push(value);
// }
// });
window.location.replace(url+"&page-type=all");
});
$("a.export-page").click(function(){
var url = $(this).data("url")+location.search;
window.location.replace(url+"&page-type=page");
});
SCRIPT;
$this->getView()->registerJs($js);
}
/**
* 渲染局部
* @return string|bool
*/
public function renderSection($name) {
public function renderSection($name)
{
switch ($name) {
case '{summary}':
return $this->renderSummary();
@ -408,7 +448,8 @@ SCRIPT;
* 渲染表格的html真实table
* @return string
*/
public function renderItems() {
public function renderItems()
{
$tableHeader = $this->showHeader ? $this->renderTableHeader() : false;
$tableBody = $this->renderTableBody();
@ -424,7 +465,8 @@ SCRIPT;
* 初始化每列
* @throws InvalidConfigException
*/
protected function initColumns() {
protected function initColumns()
{
if (empty($this->columns)) {
throw new InvalidConfigException('The "columns" property must be set.');
}
@ -434,9 +476,9 @@ SCRIPT;
$column = $this->createDataColumn($column);
} else {
$column = Yii::createObject(array_merge([
'class' => $this->dataColumnClass ?: DataColumn::className(),
'grid' => $this,
], $column));
'class' => $this->dataColumnClass ?: DataColumn::className(),
'grid' => $this,
], $column));
}
if (!$column->visible) {
unset($this->columns[$i]);
@ -451,7 +493,8 @@ SCRIPT;
* 渲染表头
* @return string
*/
public function renderTableHeader() {
public function renderTableHeader()
{
$cells = [];
foreach ($this->columns as $column) {
/* @var $column Column */
@ -466,7 +509,8 @@ SCRIPT;
* 渲染表格体
* @return string
*/
public function renderTableBody() {
public function renderTableBody()
{
$models = $this->dataProvider->getModels();
$keys = $this->dataProvider->getKeys();
$rows = [];
@ -507,7 +551,8 @@ SCRIPT;
* @param int $index
* @return string
*/
public function renderTableRow($model, $key, $index) {
public function renderTableRow($model, $key, $index)
{
$cells = [];
foreach ($this->columns as $column) {
$cells[] = $column->renderDataCell($model, $key, $index);
@ -517,7 +562,7 @@ SCRIPT;
} else {
$options = $this->rowOptions;
}
$options['data-key'] = is_array($key) ? json_encode($key) : (string) $key;
$options['data-key'] = is_array($key) ? json_encode($key) : (string)$key;
//TODO 各行变色放到这里不合理
if ($index % 2 == 0) {
@ -539,7 +584,8 @@ SCRIPT;
* 渲染摘要显示
* @return string
*/
public function renderSummary() {
public function renderSummary()
{
$count = $this->dataProvider->getCount();
if ($count <= 0) {
return '';
@ -558,20 +604,21 @@ SCRIPT;
}
return Yii::$app->getI18n()->format($this->summary, [
'begin' => $begin,
'end' => $end,
'count' => $count,
'totalCount' => $totalCount,
'page' => $page,
'pageCount' => $pageCount,
'select' => $this->renderCountSelect()
], Yii::$app->language);
'begin' => $begin,
'end' => $end,
'count' => $count,
'totalCount' => $totalCount,
'page' => $page,
'pageCount' => $pageCount,
'select' => $this->renderCountSelect()
], Yii::$app->language);
}
/**
* 渲染批量操作
*/
public function renderBatch() {
public function renderBatch()
{
if (empty($this->batch) && !is_array($this->batch)) {
return "";
}
@ -592,7 +639,8 @@ SCRIPT;
* 渲染表格的页数select
* @return string
*/
protected function renderCountSelect() {
protected function renderCountSelect()
{
$items = [
"20" => 20,
"50" => 50,
@ -614,7 +662,8 @@ SCRIPT;
* 渲染表格的筛选部分
* @return string
*/
protected function renderFilter() {
protected function renderFilter()
{
return $this->filter;
}
@ -624,17 +673,18 @@ SCRIPT;
* @return DataColumn 实例
* @throws InvalidConfigException
*/
protected function createDataColumn($text) {
protected function createDataColumn($text)
{
if (!preg_match('/^([^:]+)(:(\w*))?(:(.*))?$/', $text, $matches)) {
throw new InvalidConfigException('The column must be specified in the format of "attribute", "attribute:format" or "attribute:format:label"');
}
return Yii::createObject([
'class' => $this->dataColumnClass ?: DataColumn::className(),
'grid' => $this,
'attribute' => $matches[1],
'format' => isset($matches[3]) ? $matches[3] : 'text',
'label' => isset($matches[5]) ? $matches[5] : null,
'class' => $this->dataColumnClass ?: DataColumn::className(),
'grid' => $this,
'attribute' => $matches[1],
'format' => isset($matches[3]) ? $matches[3] : 'text',
'label' => isset($matches[5]) ? $matches[5] : null,
]);
}

246
vendor/iron/grid/ActionColumn.php

@ -0,0 +1,246 @@
<?php
/*
* The MIT License
*
* Copyright 2019 Blobt.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace iron\grid;
use Yii;
use yii\helpers\Html;
use yii\helpers\Url;
use blobt\grid\Column;
class ActionColumn extends Column
{
public $config = [
[
'name' => 'view',
'icon' => 'menu-hamburger',
'title' => '详情',
],
[
'name' => 'update',
'icon' => 'edit',
'title' => '修改'
],
[
'name' => 'delete',
'icon' => 'trash',
'title' => '删除',
'contents' => '确定删除?'
]
];
/**
* @var string 处理的控制器ID
*/
public $controller;
/**
* @var string 按钮模板
*/
public $template = '';
/**
* @var array 以按钮名为键,以匿名函数为值,通过匿名函数返回html,用来控制按钮的表现形式
* 匿名函数必须遵循以下申明方式:
*
* ```php
* function ($url, $model, $key) {
* // return the button HTML code
* }
* ```
*
* - `$url`: 按钮的跳转路径
* - `$model`: 每行的模型
* - `$key`: id值
*
* 使用案例:
* ```php
* [
* 'update' => function ($url, $model, $key) {
* return $model->status === 'editable' ? Html::a('Update', $url) : '';
* },
* ],
*
*/
public $buttons = [];
/** @var array 和上述$buttons功能类似,只是匿名函数返回布尔,只控制是否展示
* 匿名函数必须遵循以下申明方式:
*
* ```php
* function ($model, $key, $index) {
* return $model->status === 'editable';
* }
* ```
*
* 使用案例:
* ```php
* [
* 'update' => \Yii::$app->user->can('update'),
* ],
* ```
* @since 2.0.7
*/
public $visibleButtons = [];
/**
* @var callable 匿名函数,用作控制按钮Url
*
* 匿名函数必须遵循以下申明方式:
* ```php
* function (string $action, mixed $model, mixed $key, integer $index, ActionColumn $this) {
* //return string;
* }
* ```
*
* 如果没有设置,默认使用本类的[[createUrl()]].
*/
public $urlCreator;
/**
* @var array 按钮的html属性
*/
public $buttonOptions = [];
/**
* {@inheritdoc}
*/
public function init()
{
parent::init();
foreach ($this->config as $config) {
if (isset($config['contents'])) {
$options = ['alertify-confirm' => Yii::t('yii', "{$config['contents']}?")];
} else {
$options = [];
}
if (isset($config['icon'])) {
$icon = $config['icon'];
} else {
$icon = 'th-large';
}
if (isset($config['title'])) {
$title = $config['title'];
} else {
$title = $config['name'];
}
if (isset($config['hide'])) {
$this->visibleButtons($config['name'], $config['hide']);
}
$this->initButton($config['name'], $icon, $options, $title);
$this->template .= " {{$config['name']}}";
}
}
/**
* 初始化按钮
* @param string $name
* @param string $iconName
* @param array $additionalOptions 附加html属性
*/
protected function initButton($name, $iconName, $additionalOptions = [], $title = '')
{
$this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $additionalOptions, $title) {
$title = $title ?: Yii::t('yii', $name);
$options = array_merge([
'title' => $title,
'aria-label' => $title,
'data-pjax' => '0',
], $additionalOptions, $this->buttonOptions);
$icon = Html::tag('span', '', ['class' => "glyphicon glyphicon-$iconName"]);
return Html::a($icon, $url, $options);
};
}
protected function visibleButtons($name, $config)
{
$this->visibleButtons[$name] = function ($model, $key, $index) use ($config) {
$attributes = $config['attributes'];
$values = $config['values'];
if (isset($config['rule']) && $config['rule'] == 'or') {
foreach ($attributes as $k => $attribute) {
if ($model->$attribute == $values[$k]) {
return false;
}
}
return true;
}else{
foreach ($attributes as $k => $attribute) {
if ($model->$attribute != $values[$k]) {
return true;
}
}
return false;
}
};
}
/**
* 通过给定的action和model创建一个URL.
*
* @param string $action 按钮名
* @param \yii\db\ActiveRecordInterface $model 数据模型
* @param mixed $key 模型的ID
* @param int $index 行号
* @return string the created URL
*/
public function createUrl($action, $model, $key, $index)
{
if (is_callable($this->urlCreator)) {
return call_user_func($this->urlCreator, $action, $model, $key, $index, $this);
}
$params = is_array($key) ? $key : ['id' => (string)$key];
$params[0] = $this->controller ? $this->controller . '/' . $action : $action;
return Url::toRoute($params);
}
/**
* {@inheritdoc}
*/
protected function renderDataCellContent($model, $key, $index)
{
return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($model, $key, $index) {
$name = $matches[1];
if (isset($this->visibleButtons[$name])) {
$isVisible = $this->visibleButtons[$name] instanceof \Closure ? call_user_func($this->visibleButtons[$name], $model, $key, $index) : $this->visibleButtons[$name];
} else {
$isVisible = true;
}
if ($isVisible && isset($this->buttons[$name])) {
$url = $this->createUrl($name, $model, $key, $index);
return call_user_func($this->buttons[$name], $url, $model, $key);
}
return '';
}, $this->template);
}
}

958
vendor/iron/widget/Excel.php

@ -0,0 +1,958 @@
<?php
namespace iron\widget;
use yii\helpers\ArrayHelper;
use yii\base\InvalidConfigException;
use yii\base\InvalidParamException;
use yii\i18n\Formatter;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
/**
* Excel Widget for generate Excel File or for load Excel File.
*
* Usage
* -----
*
* Exporting data into an excel file.
*
* ~~~
*
* // export data only one worksheet.
*
* \moonland\phpexcel\Excel::widget([
* 'models' => $allModels,
* 'mode' => 'export', //default value as 'export'
* 'columns' => ['column1','column2','column3'],
* //without header working, because the header will be get label from attribute label.
* 'headers' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
* ]);
*
* \moonland\phpexcel\Excel::export([
* 'models' => $allModels,
* 'columns' => ['column1','column2','column3'],
* //without header working, because the header will be get label from attribute label.
* 'headers' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
* ]);
*
* // export data with multiple worksheet.
*
* \moonland\phpexcel\Excel::widget([
* 'isMultipleSheet' => true,
* 'models' => [
* 'sheet1' => $allModels1,
* 'sheet2' => $allModels2,
* 'sheet3' => $allModels3
* ],
* 'mode' => 'export', //default value as 'export'
* 'columns' => [
* 'sheet1' => ['column1','column2','column3'],
* 'sheet2' => ['column1','column2','column3'],
* 'sheet3' => ['column1','column2','column3']
* ],
* //without header working, because the header will be get label from attribute label.
* 'headers' => [
* 'sheet1' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
* 'sheet2' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
* 'sheet3' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3']
* ],
* ]);
*
* \moonland\phpexcel\Excel::export([
* 'isMultipleSheet' => true,
* 'models' => [
* 'sheet1' => $allModels1,
* 'sheet2' => $allModels2,
* 'sheet3' => $allModels3
* ],
* 'columns' => [
* 'sheet1' => ['column1','column2','column3'],
* 'sheet2' => ['column1','column2','column3'],
* 'sheet3' => ['column1','column2','column3']
* ],
* //without header working, because the header will be get label from attribute label.
* 'headers' => [
* 'sheet1' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
* 'sheet2' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
* 'sheet3' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3']
* ],
* ]);
*
* ~~~
*
* New Feature for exporting data, you can use this if you familiar yii gridview.
* That is same with gridview data column.
* Columns in array mode valid params are 'attribute', 'header', 'format', 'value', and footer (TODO).
* Columns in string mode valid layout are 'attribute:format:header:footer(TODO)'.
*
* ~~~
*
* \moonland\phpexcel\Excel::export([
* 'models' => Post::find()->all(),
* 'columns' => [
* 'author.name:text:Author Name',
* [
* 'attribute' => 'content',
* 'header' => 'Content Post',
* 'format' => 'text',
* 'value' => function($model) {
* return ExampleClass::removeText('example', $model->content);
* },
* ],
* 'like_it:text:Reader like this content',
* 'created_at:datetime',
* [
* 'attribute' => 'updated_at',
* 'format' => 'date',
* ],
* ],
* 'headers' => [
* 'created_at' => 'Date Created Content',
* ],
* ]);
*
* ~~~
*
*
* Import file excel and return into an array.
*
* ~~~
*
* $data = \moonland\phpexcel\Excel::import($fileName, $config); // $config is an optional
*
* $data = \moonland\phpexcel\Excel::widget([
* 'mode' => 'import',
* 'fileName' => $fileName,
* 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
* 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
* 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
* ]);
*
* $data = \moonland\phpexcel\Excel::import($fileName, [
* 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
* 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
* 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
* ]);
*
* // import data with multiple file.
*
* $data = \moonland\phpexcel\Excel::widget([
* 'mode' => 'import',
* 'fileName' => [
* 'file1' => $fileName1,
* 'file2' => $fileName2,
* 'file3' => $fileName3,
* ],
* 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
* 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
* 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
* ]);
*
* $data = \moonland\phpexcel\Excel::import([
* 'file1' => $fileName1,
* 'file2' => $fileName2,
* 'file3' => $fileName3,
* ], [
* 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
* 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
* 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
* ]);
*
* ~~~
*
* Result example from the code on the top :
*
* ~~~
*
* // only one sheet or specified sheet.
*
* Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2));
*
* // data with multiple worksheet
*
* Array([Sheet1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)),
* [Sheet2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)));
*
* // data with multiple file and specified sheet or only one worksheet
*
* Array([file1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)),
* [file2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)));
*
* // data with multiple file and multiple worksheet
*
* Array([file1] => Array([Sheet1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)),
* [Sheet2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2))),
* [file2] => Array([Sheet1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)),
* [Sheet2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2))));
*
* ~~~
*
* @property string $mode is an export mode or import mode. valid value are 'export' and 'import'
* @property boolean $isMultipleSheet for set the export excel with multiple sheet.
* @property array $properties for set property on the excel object.
* @property array $models Model object or DataProvider object with much data.
* @property array $columns to get the attributes from the model, this valid value only the exist attribute on the model.
* If this is not set, then all attribute of the model will be set as columns.
* @property array $headers to set the header column on first line. Set this if want to custom header.
* If not set, the header will get attributes label of model attributes.
* @property string|array $fileName is a name for file name to export or import. Multiple file name only use for import mode, not work if you use the export mode.
* @property string $savePath is a directory to save the file or you can blank this to set the file as attachment.
* @property string $format for excel to export. Valid value are 'Xls','Xlsx','Xml','Ods','Slk','Gnumeric','Csv', and 'Html'.
* @property boolean $setFirstTitle to set the title column on the first line. The columns will have a header on the first line.
* @property boolean $asAttachment to set the file excel to download mode.
* @property boolean $setFirstRecordAsKeys to set the first record on excel file to a keys of array per line.
* If you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
* @property boolean $setIndexSheetByName to set the sheet index by sheet name or array result if the sheet not only one
* @property string $getOnlySheet is a sheet name to getting the data. This is only get the sheet with same name.
* @property array|Formatter $formatter the formatter used to format model attribute values into displayable texts.
* This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
* instance. If this property is not set, the "formatter" application component will be used.
*
* @author Moh Khoirul Anam <moh.khoirul.anaam@gmail.com>
* @copyright 2014
* @since 1
*/
class Excel extends \yii\base\Widget
{
// Border style
const BORDER_NONE = 'none';
const BORDER_DASHDOT = 'dashDot';
const BORDER_DASHDOTDOT = 'dashDotDot';
const BORDER_DASHED = 'dashed';
const BORDER_DOTTED = 'dotted';
const BORDER_DOUBLE = 'double';
const BORDER_HAIR = 'hair';
const BORDER_MEDIUM = 'medium';
const BORDER_MEDIUMDASHDOT = 'mediumDashDot';
const BORDER_MEDIUMDASHDOTDOT = 'mediumDashDotDot';
const BORDER_MEDIUMDASHED = 'mediumDashed';
const BORDER_SLANTDASHDOT = 'slantDashDot';
const BORDER_THICK = 'thick';
const BORDER_THIN = 'thin';
// Colors
const COLOR_BLACK = 'FF000000';
const COLOR_WHITE = 'FFFFFFFF';
const COLOR_RED = 'FFFF0000';
const COLOR_DARKRED = 'FF800000';
const COLOR_BLUE = 'FF0000FF';
const COLOR_DARKBLUE = 'FF000080';
const COLOR_GREEN = 'FF00FF00';
const COLOR_DARKGREEN = 'FF008000';
const COLOR_YELLOW = 'FFFFFF00';
const COLOR_DARKYELLOW = 'FF808000';
// Horizontal alignment styles
const HORIZONTAL_GENERAL = 'general';
const HORIZONTAL_LEFT = 'left';
const HORIZONTAL_RIGHT = 'right';
const HORIZONTAL_CENTER = 'center';
const HORIZONTAL_CENTER_CONTINUOUS = 'centerContinuous';
const HORIZONTAL_JUSTIFY = 'justify';
const HORIZONTAL_FILL = 'fill';
const HORIZONTAL_DISTRIBUTED = 'distributed'; // Excel2007 only
// Vertical alignment styles
const VERTICAL_BOTTOM = 'bottom';
const VERTICAL_TOP = 'top';
const VERTICAL_CENTER = 'center';
const VERTICAL_JUSTIFY = 'justify';
const VERTICAL_DISTRIBUTED = 'distributed'; // Excel2007 only
// Read order
const READORDER_CONTEXT = 0;
const READORDER_LTR = 1;
const READORDER_RTL = 2;
// Fill types
const FILL_NONE = 'none';
const FILL_SOLID = 'solid';
const FILL_GRADIENT_LINEAR = 'linear';
const FILL_GRADIENT_PATH = 'path';
const FILL_PATTERN_DARKDOWN = 'darkDown';
const FILL_PATTERN_DARKGRAY = 'darkGray';
const FILL_PATTERN_DARKGRID = 'darkGrid';
const FILL_PATTERN_DARKHORIZONTAL = 'darkHorizontal';
const FILL_PATTERN_DARKTRELLIS = 'darkTrellis';
const FILL_PATTERN_DARKUP = 'darkUp';
const FILL_PATTERN_DARKVERTICAL = 'darkVertical';
const FILL_PATTERN_GRAY0625 = 'gray0625';
const FILL_PATTERN_GRAY125 = 'gray125';
const FILL_PATTERN_LIGHTDOWN = 'lightDown';
const FILL_PATTERN_LIGHTGRAY = 'lightGray';
const FILL_PATTERN_LIGHTGRID = 'lightGrid';
const FILL_PATTERN_LIGHTHORIZONTAL = 'lightHorizontal';
const FILL_PATTERN_LIGHTTRELLIS = 'lightTrellis';
const FILL_PATTERN_LIGHTUP = 'lightUp';
const FILL_PATTERN_LIGHTVERTICAL = 'lightVertical';
const FILL_PATTERN_MEDIUMGRAY = 'mediumGray';
// Pre-defined formats
const FORMAT_GENERAL = 'General';
const FORMAT_TEXT = '@';
const FORMAT_NUMBER = '0';
const FORMAT_NUMBER_00 = '0.00';
const FORMAT_NUMBER_COMMA_SEPARATED1 = '#,##0.00';
const FORMAT_NUMBER_COMMA_SEPARATED2 = '#,##0.00_-';
const FORMAT_PERCENTAGE = '0%';
const FORMAT_PERCENTAGE_00 = '0.00%';
const FORMAT_DATE_YYYYMMDD2 = 'yyyy-mm-dd';
const FORMAT_DATE_YYYYMMDD = 'yy-mm-dd';
const FORMAT_DATE_DDMMYYYY = 'dd/mm/yy';
const FORMAT_DATE_DMYSLASH = 'd/m/yy';
const FORMAT_DATE_DMYMINUS = 'd-m-yy';
const FORMAT_DATE_DMMINUS = 'd-m';
const FORMAT_DATE_MYMINUS = 'm-yy';
const FORMAT_DATE_XLSX14 = 'mm-dd-yy';
const FORMAT_DATE_XLSX15 = 'd-mmm-yy';
const FORMAT_DATE_XLSX16 = 'd-mmm';
const FORMAT_DATE_XLSX17 = 'mmm-yy';
const FORMAT_DATE_XLSX22 = 'm/d/yy h:mm';
const FORMAT_DATE_DATETIME = 'd/m/yy h:mm';
const FORMAT_DATE_TIME1 = 'h:mm AM/PM';
const FORMAT_DATE_TIME2 = 'h:mm:ss AM/PM';
const FORMAT_DATE_TIME3 = 'h:mm';
const FORMAT_DATE_TIME4 = 'h:mm:ss';
const FORMAT_DATE_TIME5 = 'mm:ss';
const FORMAT_DATE_TIME6 = 'h:mm:ss';
const FORMAT_DATE_TIME7 = 'i:s.S';
const FORMAT_DATE_TIME8 = 'h:mm:ss;@';
const FORMAT_DATE_YYYYMMDDSLASH = 'yy/mm/dd;@';
const FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0.00_-';
const FORMAT_CURRENCY_USD = '$#,##0_-';
const FORMAT_CURRENCY_EUR_SIMPLE = '#,##0.00_-"€"';
const FORMAT_CURRENCY_EUR = '#,##0_-"€"';
/**
* @var string mode is an export mode or import mode. valid value are 'export' and 'import'.
*/
public $mode = 'export';
/**
* @var boolean for set the export excel with multiple sheet.
*/
public $isMultipleSheet = false;
/**
* @var array properties for set property on the excel object.
*/
public $properties;
/**
* @var Model object or DataProvider object with much data.
*/
public $models;
/**
* @var array columns to get the attributes from the model, this valid value only the exist attribute on the model.
* If this is not set, then all attribute of the model will be set as columns.
*/
public $columns = [];
/**
* @var array header to set the header column on first line. Set this if want to custom header.
* If not set, the header will get attributes label of model attributes.
*/
public $headers = [];
/**
* @var string|array name for file name to export or save.
*/
public $fileName;
/**
* @var string save path is a directory to save the file or you can blank this to set the file as attachment.
*/
public $savePath;
/**
* @var string format for excel to export. Valid value are 'Xls','Xlsx','Xml','Ods','Slk','Gnumeric','Csv', and 'Html'.
*/
public $format;
/**
* @var boolean to set the title column on the first line.
*/
public $setFirstTitle = true;
/**
* @var boolean to set the file excel to download mode.
*/
public $asAttachment = false;
/**
* @var boolean to set the first record on excel file to a keys of array per line.
* If you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
*/
public $setFirstRecordAsKeys = true;
/**
* @var boolean to set the sheet index by sheet name or array result if the sheet not only one.
*/
public $setIndexSheetByName = false;
/**
* @var string sheetname to getting. This is only get the sheet with same name.
*/
public $getOnlySheet;
/**
* @var boolean to set the import data will return as array.
*/
public $asArray;
/**
* @var array to unread record by index number.
*/
public $leaveRecordByIndex = [];
/**
* @var array to read record by index, other will leave.
*/
public $getOnlyRecordByIndex = [];
/**
* @var array|Formatter the formatter used to format model attribute values into displayable texts.
* This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
* instance. If this property is not set, the "formatter" application component will be used.
*/
public $formatter;
/**
* @var boolean define the column autosize
*/
public $autoSize = false;
/**
* @var boolean if true, this writer pre-calculates all formulas in the spreadsheet. This can be slow on large spreadsheets, and maybe even unwanted.
*/
public $preCalculationFormula = false;
/**
* @var boolean Because of a bug in the Office2003 compatibility pack, there can be some small issues when opening Xlsx spreadsheets (mostly related to formula calculation)
*/
public $compatibilityOffice2003 = false;
/**
* @var custom CSV delimiter for import. Works only with CSV files
*/
public $CSVDelimiter = ";";
/**
* @var custom CSV encoding for import. Works only with CSV files
*/
public $CSVEncoding = "UTF-8";
/**
* (non-PHPdoc)
* @see \yii\base\Object::init()
*/
public function init()
{
parent::init();
if ($this->formatter == null) {
$this->formatter = \Yii::$app->getFormatter();
} elseif (is_array($this->formatter)) {
$this->formatter = \Yii::createObject($this->formatter);
}
if (!$this->formatter instanceof Formatter) {
throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
}
}
/**
* Setting data from models
*/
public function executeColumns(&$activeSheet = null, $models, $columns = [], $headers = [])
{
if ($activeSheet == null) {
$activeSheet = $this->activeSheet;
}
$hasHeader = false;
$row = 1;
$char = 26;
foreach ($models as $model) {
if (empty($columns)) {
$columns = $model->attributes();
}
if ($this->setFirstTitle && !$hasHeader) {
$isPlus = false;
$colplus = 0;
$colnum = 1;
foreach ($columns as $key=>$column) {
$col = '';
if ($colnum > $char) {
$colplus += 1;
$colnum = 1;
$isPlus = true;
}
if ($isPlus) {
$col .= chr(64+$colplus);
}
$col .= chr(64+$colnum);
$header = '';
if (is_array($column)) {
if (isset($column['header'])) {
$header = $column['header'];
}elseif(isset($column['label'])){
$header = $column['label'];
} elseif (isset($column['attribute']) && isset($headers[$column['attribute']])) {
$header = $headers[$column['attribute']];
} elseif (isset($column['attribute'])) {
$header = $model->getAttributeLabel($column['attribute']);
} elseif (isset($column['cellFormat']) && is_array($column['cellFormat'])) {
$activeSheet->getStyle($col.$row)->applyFromArray($column['cellFormat']);
}
} else {
if(isset($headers[$column])) {
$header = $headers[$column];
} else {
$header = $model->getAttributeLabel($column);
}
}
if (isset($column['width'])) {
$activeSheet->getColumnDimension(strtoupper($col))->setWidth($column['width']);
}
$activeSheet->setCellValue($col.$row,$header);
$colnum++;
}
$hasHeader=true;
$row++;
}
$isPlus = false;
$colplus = 0;
$colnum = 1;
foreach ($columns as $key=>$column) {
$col = '';
if ($colnum > $char) {
$colplus++;
$colnum = 1;
$isPlus = true;
}
if ($isPlus) {
$col .= chr(64+$colplus);
}
$col .= chr(64+$colnum);
if (is_array($column)) {
$column_value = $this->executeGetColumnData($model, $column);
if (isset($column['cellFormat']) && is_array($column['cellFormat'])) {
$activeSheet->getStyle($col.$row)->applyFromArray($column['cellFormat']);
}
} else {
$column_value = $this->executeGetColumnData($model, ['attribute' => $column]);
}
$activeSheet->setCellValue($col.$row,$column_value);
$colnum++;
}
$row++;
if($this->autoSize){
foreach (range(0, $colnum) as $col) {
$activeSheet->getColumnDimensionByColumn($col)->setAutoSize(true);
}
}
}
}
/**
* Setting label or keys on every record if setFirstRecordAsKeys is true.
* @param array $sheetData
* @return multitype:multitype:array
*/
public function executeArrayLabel($sheetData)
{
$keys = ArrayHelper::remove($sheetData, '1');
$new_data = [];
foreach ($sheetData as $values)
{
$new_data[] = array_combine($keys, $values);
}
return $new_data;
}
/**
* Leave record with same index number.
* @param array $sheetData
* @param array $index
* @return array
*/
public function executeLeaveRecords($sheetData = [], $index = [])
{
foreach ($sheetData as $key => $data)
{
if (in_array($key, $index))
{
unset($sheetData[$key]);
}
}
return $sheetData;
}
/**
* Read record with same index number.
* @param array $sheetData
* @param array $index
* @return array
*/
public function executeGetOnlyRecords($sheetData = [], $index = [])
{
foreach ($sheetData as $key => $data)
{
if (!in_array($key, $index))
{
unset($sheetData[$key]);
}
}
return $sheetData;
}
/**
* Getting column value.
* @param Model $model
* @param array $params
* @return Ambigous <NULL, string, mixed>
*/
public function executeGetColumnData($model, $params = [])
{
$value = null;
if (isset($params['value']) && $params['value'] !== null) {
if (is_string($params['value'])) {
$value = ArrayHelper::getValue($model, $params['value']);
} else {
$value = call_user_func($params['value'], $model, $this);
}
} elseif (isset($params['attribute']) && $params['attribute'] !== null) {
$value = ArrayHelper::getValue($model, $params['attribute']);
}
if (isset($params['format']) && $params['format'] != null)
$value = $this->formatter()->format($value, $params['format']);
return $value;
}
/**
* Populating columns for checking the column is string or array. if is string this will be checking have a formatter or header.
* @param array $columns
* @throws InvalidParamException
* @return multitype:multitype:array
*/
public function populateColumns($columns = [])
{
$_columns = [];
foreach ($columns as $key => $value)
{
if (is_string($value))
{
$value_log = explode(':', $value);
$_columns[$key] = ['attribute' => $value_log[0]];
if (isset($value_log[1]) && $value_log[1] !== null) {
$_columns[$key]['format'] = $value_log[1];
}
if (isset($value_log[2]) && $value_log[2] !== null) {
$_columns[$key]['header'] = $value_log[2];
}
} elseif (is_array($value)) {
if(isset($value['class'])){
continue;
}
if (!isset($value['attribute']) && !isset($value['value'])) {
throw new \InvalidArgumentException('Attribute or Value must be defined.');
}
$_columns[$key] = $value;
}
}
return $_columns;
}
/**
* Formatter for i18n.
* @return Formatter
*/
public function formatter()
{
if (!isset($this->formatter))
$this->formatter = \Yii::$app->getFormatter();
return $this->formatter;
}
/**
* Setting header to download generated file xls
*/
public function setHeaders()
{
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="' . $this->getFileName() .'"');
header('Cache-Control: max-age=0');
}
/**
* Getting the file name of exporting xls file
* @return string
*/
public function getFileName()
{
$fileName = 'exports.xlsx';
if (isset($this->fileName)) {
$fileName = $this->fileName;
if (strpos($fileName, '.xlsx') === false)
$fileName .= '.xlsx';
}
return $fileName;
}
/**
* Setting properties for excel file
* @param PHPExcel $objectExcel
* @param array $properties
*/
public function properties(&$objectExcel, $properties = [])
{
foreach ($properties as $key => $value)
{
$keyname = "set" . ucfirst($key);
$objectExcel->getProperties()->{$keyname}($value);
}
}
/**
* saving the xls file to download or to path
*/
public function writeFile($sheet)
{
if (!isset($this->format))
$this->format = 'Xlsx';
$objectwriter = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($sheet, $this->format);
$path = 'php://output';
if (isset($this->savePath) && $this->savePath != null) {
$path = $this->savePath . '/' . $this->getFileName();
}
$objectwriter->setOffice2003Compatibility($this->compatibilityOffice2003);
$objectwriter->setPreCalculateFormulas($this->preCalculationFormula);
$objectwriter->save($path);
if ($path == 'php://output')
exit();
return true;
}
/**
* reading the xls file
*/
public function readFile($fileName)
{
if (!isset($this->format))
$this->format = \PhpOffice\PhpSpreadsheet\IOFactory::identify($fileName);
$objectreader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($this->format);
if ($this->format == "Csv") {
$objectreader->setDelimiter($this->CSVDelimiter);
$objectreader->setInputEncoding($this->CSVEncoding);
}
$objectPhpExcel = $objectreader->load($fileName);
$sheetCount = $objectPhpExcel->getSheetCount();
$sheetDatas = [];
if ($sheetCount > 1) {
foreach ($objectPhpExcel->getSheetNames() as $sheetIndex => $sheetName) {
if (isset($this->getOnlySheet) && $this->getOnlySheet != null) {
if(!$objectPhpExcel->getSheetByName($this->getOnlySheet)) {
return $sheetDatas;
}
$objectPhpExcel->setActiveSheetIndexByName($this->getOnlySheet);
$indexed = $this->getOnlySheet;
$sheetDatas[$indexed] = $objectPhpExcel->getActiveSheet()->toArray(null, true, true, true);
if ($this->setFirstRecordAsKeys) {
$sheetDatas[$indexed] = $this->executeArrayLabel($sheetDatas[$indexed]);
}
if (!empty($this->getOnlyRecordByIndex)) {
$sheetDatas[$indexed] = $this->executeGetOnlyRecords($sheetDatas[$indexed], $this->getOnlyRecordByIndex);
}
if (!empty($this->leaveRecordByIndex)) {
$sheetDatas[$indexed] = $this->executeLeaveRecords($sheetDatas[$indexed], $this->leaveRecordByIndex);
}
return $sheetDatas[$indexed];
} else {
$objectPhpExcel->setActiveSheetIndexByName($sheetName);
$indexed = $this->setIndexSheetByName==true ? $sheetName : $sheetIndex;
$sheetDatas[$indexed] = $objectPhpExcel->getActiveSheet()->toArray(null, true, true, true);
if ($this->setFirstRecordAsKeys) {
$sheetDatas[$indexed] = $this->executeArrayLabel($sheetDatas[$indexed]);
}
if (!empty($this->getOnlyRecordByIndex) && isset($this->getOnlyRecordByIndex[$indexed]) && is_array($this->getOnlyRecordByIndex[$indexed])) {
$sheetDatas = $this->executeGetOnlyRecords($sheetDatas, $this->getOnlyRecordByIndex[$indexed]);
}
if (!empty($this->leaveRecordByIndex) && isset($this->leaveRecordByIndex[$indexed]) && is_array($this->leaveRecordByIndex[$indexed])) {
$sheetDatas[$indexed] = $this->executeLeaveRecords($sheetDatas[$indexed], $this->leaveRecordByIndex[$indexed]);
}
}
}
} else {
$sheetDatas = $objectPhpExcel->getActiveSheet()->toArray(null, true, true, true);
if ($this->setFirstRecordAsKeys) {
$sheetDatas = $this->executeArrayLabel($sheetDatas);
}
if (!empty($this->getOnlyRecordByIndex)) {
$sheetDatas = $this->executeGetOnlyRecords($sheetDatas, $this->getOnlyRecordByIndex);
}
if (!empty($this->leaveRecordByIndex)) {
$sheetDatas = $this->executeLeaveRecords($sheetDatas, $this->leaveRecordByIndex);
}
}
return $sheetDatas;
}
/**
* (non-PHPdoc)
* @see \yii\base\Widget::run()
*/
public function run()
{
if ($this->mode == 'export')
{
$sheet = new Spreadsheet();
if (!isset($this->models))
throw new InvalidConfigException('Config models must be set');
if (isset($this->properties))
{
$this->properties($sheet, $this->properties);
}
if ($this->isMultipleSheet) {
$index = 0;
$worksheet = [];
foreach ($this->models as $title => $models) {
$sheet->createSheet($index);
$sheet->getSheet($index)->setTitle($title);
$worksheet[$index] = $sheet->getSheet($index);
$columns = isset($this->columns[$title]) ? $this->columns[$title] : [];
$headers = isset($this->headers[$title]) ? $this->headers[$title] : [];
$this->executeColumns($worksheet[$index], $models, $this->populateColumns($columns), $headers);
$index++;
}
} else {
$worksheet = $sheet->getActiveSheet();
$this->executeColumns($worksheet, $this->models, isset($this->columns) ? $this->populateColumns($this->columns) : [], isset($this->headers) ? $this->headers : []);
}
if ($this->asAttachment) {
$this->setHeaders();
}
$this->writeFile($sheet);
$sheet->disconnectWorksheets();
unset($sheet);
}
elseif ($this->mode == 'import')
{
if (is_array($this->fileName)) {
$datas = [];
foreach ($this->fileName as $key => $filename) {
$datas[$key] = $this->readFile($filename);
}
return $datas;
} else {
return $this->readFile($this->fileName);
}
}
}
/**
* Exporting data into an excel file.
*
* ~~~
*
* \moonland\phpexcel\Excel::export([
* 'models' => $allModels,
* 'columns' => ['column1','column2','column3'],
* //without header working, because the header will be get label from attribute label.
* 'header' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
* ]);
*
* ~~~
*
* New Feature for exporting data, you can use this if you familiar yii gridview.
* That is same with gridview data column.
* Columns in array mode valid params are 'attribute', 'header', 'format', 'value', and footer (TODO).
* Columns in string mode valid layout are 'attribute:format:header:footer(TODO)'.
*
* ~~~
*
* \moonland\phpexcel\Excel::export([
* 'models' => Post::find()->all(),
* 'columns' => [
* 'author.name:text:Author Name',
* [
* 'attribute' => 'content',
* 'header' => 'Content Post',
* 'format' => 'text',
* 'value' => function($model) {
* return ExampleClass::removeText('example', $model->content);
* },
* ],
* 'like_it:text:Reader like this content',
* 'created_at:datetime',
* [
* 'attribute' => 'updated_at',
* 'format' => 'date',
* ],
* ],
* 'headers' => [
* 'created_at' => 'Date Created Content',
* ],
* ]);
*
* ~~~
*
* @param array $config
* @return string
*/
public static function export($config=[])
{
$config = ArrayHelper::merge(['mode' => 'export'], $config);
return self::widget($config);
}
/**
* Import file excel and return into an array.
*
* ~~~
*
* $data = \moonland\phpexcel\Excel::import($fileName, ['setFirstRecordAsKeys' => true]);
*
* ~~~
*
* @param string!array $fileName to load.
* @param array $config is a more configuration.
* @return string
*/
public static function import($fileName, $config=[])
{
$config = ArrayHelper::merge(['mode' => 'import', 'fileName' => $fileName, 'asArray' => true], $config);
return self::widget($config);
}
/**
* @param array $config
* @return string
*/
public static function widget($config = [])
{
if ((isset($config['mode']) and $config['mode'] == 'import') && !isset($config['asArray'])) {
$config['asArray'] = true;
}
if (isset($config['asArray']) && $config['asArray']==true)
{
$config['class'] = get_called_class();
$widget = \Yii::createObject($config);
return $widget->run();
} else {
return parent::widget($config);
}
}
}
Loading…
Cancel
Save