2.model文件
<?php
namespace appmodels;//model层的命名空间
//注意要引用yii的arrayhelper
use yiihelpersArrayHelper;
use Yii;
class Recharge extends yiidbActiveRecord
{
//excel一次导出条数
const EXCEL_SIZE = 10000;
//统计导出
public static function statistics($params){
//导出时间条件
if(empty($params['min'])){
$date_max = date("Y-m-d",strtotime("-1 day"));
$date_min = date("Y-m-d",strtotime("-31 day"));
}else{
$date_min = $params['min'];
$date_max = $params['max'];
}
$where = '';
$where .= '(`issue_date` BETWEEN '.'''.$date_min.'''.' AND '.'''.$date_max.'')';
//查找指定数据
$sql = 'select
article.company_id,
article.cost,
article.company_cost
from article WHERE article.status=2 AND '.$where;
$article = Article::findBySql($sql)->asArray()->all();
$article = ArrayHelper::index($article,null,'company_id');
$companys = [];
foreach ($article as $key=>$v){
if(empty($key)){
continue;
}else{
$number = count($v);
$company = Company::find()->where(['id'=>$key])->select('name')->one();
$company_name = $company['name'];
$cost = 0;
$company_cost = 0;
foreach ($v as $n){
$cost += $n['cost'];
$company_cost += $n['company_cost'];
}
if($company_cost == 0){
$company_cost =1;
}
//这里注意,数据的存储顺序要和输出的表格里的顺序一样
$companys[] = [
//公司名
'company_name' => $company_name,
//收入
'company_cost' => $company_cost,
//成本
'cost' => $cost,
//稿件数
'num' => $number,
//毛利
'gross_margin' => $company_cost-$cost,
//毛利率
'gross_profit_rate' => round(($company_cost-$cost)/$company_cost*100,2).'%',
//ARPU值
'arpu' => round($company_cost/$number,2),
];
}
}
return $companys;
}
}
最终导出的效果(单元格大小导出后调整过)可以看到和网页显示的基本一样。

二.大数据表格导出
这时老板说了,我们不能只看总和的数据,最好是把详细数据也给导出来。既然老板发话了,那就做吧。还是按照第一种的方法去做,结果提示我php崩溃了,再试一次发现提示写入字节超出。打开php的配置文件php.ini
memory_limit = 128M
发现默认内存已经给到128M,应该是足够的了。于是我打开数据库一看,嚯!
接近83万条的数据进行查询并导出,可不是会出问题嘛!怎么办呢,于是我Google了一下,发现对于大数据(2万条以上)的导出,最好是以.csv的形式。不说废话,直接上代码
1.controller文件
//导出清单
public function actionInventory(){
ini_set("memory_limit", "2048M");
set_time_limit(0);
$id = Yii::$app->user->identity->getId();
$user = Employee::find()->where(['id'=>$id])->one();
$params = Yii::$app->request->get();
//类似的,跳转到recharge这个model文件里的inventory方法去处理数据
$data = Recharge::inventory($params);
//设置导出的文件名
$fileName = iconv('utf-8', 'gbk', '代理商统计清单'.date("Y-m-d"));
//设置表头
$headlist = array('代理商','文章ID','文章标题','媒体','统计时间范围','状态','创建时间','审核时间','发稿时间','退稿时间','财务状态','成本','销售额','是否是预收款媒体类型','订单类别');
header('Content-Type: application/vnd.ms-excel');
//指明导出的格式
header('Content-Disposition: attachment;filename="'.$fileName.'.csv"');
header('Cache-Control: max-age=0');
//打开PHP文件句柄,php://output 表示直接输出到浏览器
$fp = fopen('php://output', 'a');
//输出Excel列名信息
foreach ($headlist as $key => $value) {
//CSV的Excel支持GBK编码,一定要转换,否则乱码
$headlist[$key] = iconv('utf-8', 'gbk', $value);
}
//将数据通过fputcsv写到文件句柄
fputcsv($fp, $headlist);
//每隔$limit行,刷新一下输出buffer,不要太大,也不要太小
$limit = 100000;
//逐行取出数据,不浪费内存
foreach ($data as $k => $v) {
//刷新一下输出buffer,防止由于数据过多造成问题
if ($k % $limit == 0 && $k!=0) {
ob_flush();
flush();
}
$row = $data[$k];
foreach ($row as $key => $value) {
$row[$key] = iconv('utf-8', 'gbk', $value);
}
fputcsv($fp, $row);
}
}







