php vue elementUI 实现zip,excel,图片等导出功能
1.HTML:导出模板和数据按钮
<el-button type="success" v-if="canImport" @click="export(true)" :disabled="disableExportTemplateBtn">导出模板</el-button>
<el-button type="success" v-if="canExport" @click="export(false)" :disabled="disableExportDataBtn">导出数据</el-button>
- v-if根据导入导出权限是否显示按钮
- @click导出事件
- :disabled根据导出状态判断按钮是否可点
2.VUE:导出事件
exportTransformer(isTemplate){
//判断是否为导出模板,按钮不可点
if(isTemplate){
this.disableExportTemplateBtn = true;
}
else{
this.disableExportDataBtn = true;
}
//传入后台的参数(自行修改相应参数)
let params = {
'Id':this.$route.params.Id,'isTemplate':isTemplate?isTemplate:''};
//路由地址(自行修改地址)
let url= '/api/exportMultiple';
this.APIRequest(
url,
'get',
params,
//返回数据类型(数据来源后边介绍)
'blob'
).then(res => {
if(res){
//创建一个a链接
const link = document.createElement('a');
//根据Blob 对象生成一个url
link.href = window.URL.createObjectURL(res.blob);
//导出的文件名
if(res.fileName){
link.download = res.fileName;
}
//a标签点击
link.click();
this.$notify.success('导出成功');
}else{
this.$notify.error('导出失败');
}
//判断是否为导出模板,按钮可点
if(isTemplate){
this.disableExportTemplateBtn = false;
}
else{
this.disableExportDataBtn = false;
}
});
},
3.blob返回数据类型
export const APIRequest = function(url, method, params,responseType){
let tempData = {
url: url,
method: method,
params: params,
};
if(responseType != undefined){
tempData.responseType = responseType;
}
return request(tempData);
};
在axios的request.js中
service.interceptors.response.use(
response => {
if (response.status === 200) {
//判断如果数据类型为blob,获取文件名和返回的相应数据
if(response.request.responseType == 'blob'){
let disposition = response.headers['content-disposition'];
let fileName = decodeURI(disposition.substring(disposition.indexOf('filename="')+10, disposition.length-1));
return {
fileName: fileName, blob:response.data};
}
return response.data;
} else {
Promise.reject();
}
},
);
4.PHP:control层和model层
//control
public function exportMultiple(Request $request){
$id=$request->input('Id', false);
$isTemplate=$request->input('isTemplate', true);
$data=getData($id);
$exportName='自定义名称'.date('YmdHis', time());
$export=new ExportMultipleData();
$export->exportMultiple($data,$isTemplate,$exportName);
}
//model 批量导出数据(简化版,根据导出格式自行调整数据格式)
public function exportMultiple($data=[],$isTemplate=true, $exportName='测试文件'){
$excelDatas = [];//填写数据的单元格
$excelCellDatas = [];//显示的单元格
$images = [];//图片文件
$borders = [];//边框范围
foreach ($data['experimentData'] as $experimentKey=>$experiment){
$sheetName = '下边每个sheet标题的名称';
$excelCellDatas[$sheetName] = [];
$excelDatas[$sheetName] = [];
$borders[$sheetName] = [];
//从第三行开始
$nowRow = 3;
//MultipleField最多的列数
$colMax=0;
//从B列开始
$nowCol=1;
foreach ($experiment['experimentConfig']['fields'] as $fieldKey => $field){
$nowRow++;
$titleContent=$field['name'];
$excelCellDatas[$sheetName][colNum2colLetter($nowCol)][$nowRow]=getExcelTitleStyle($titleContent);
$nowCol++;
if($field['type']=='Upload'){
$uploadPath='';
if(!empty($experiment['experimentFiles'][$fieldKey][0])){
$uploadPath=$url;//图片的地址
}
$dataContent=$sheetName.'|'.$uploadPath;
if(!$isTemplate){
$images[$sheetName][$field['name']]=$uploadPath;
}
}else{
$dataContent=$experiment['experimentData'][$fieldKey];
}
$dataContent=$isTemplate? '':$dataContent;
$excelCellDatas[$sheetName][colNum2colLetter($nowCol)][$nowRow]=getExcelContentStyle($dataContent);
$excelDatas[$sheetName]['data_'.$nowRow.'_'.$nowCol]=colNum2colLetter($nowCol).$nowRow;
$borders[$sheetName][]=colNum2colLetter($nowCol-1).$nowRow.':'.colNum2colLetter($nowCol).$nowRow;
$nowCol++;
}
$excelCellDatas[$sheetName]['B']['2']=getExcelMainTitleStyle($sheetName,colNum2colLetter($colMax) . '2');
$allData = [
'excelCellDatas' => $excelCellDatas,
'excelDatas' => $excelDatas,
'images' => $images,
'borders' => $borders
];
}
if(empty($images)){
createExcelFile($allData, $exportName);
}else{
getZipFile($allData,$exportName);
}
}
//将数字转换成excel的列号(如:A,B,AA等)
function colNum2colLetter($num){
$cols = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
if($num > 25){
$num1 = (int)($num / 25);
$num2 = (int)($num % 25);
return $cols[$num1].$cols[$num2];
}
return $cols[$num];
}
//获取excel表中内容相应的样式和内容(getExcelTitleStyle和getExcelMainTitleStyle根据实际情况自行调整样式)
function getExcelContentStyle($name){
return [
'content' => $name,
'style' => [
'fontSize' => '10',
'width' =>'20',
'valignment' => 'center',
'alignment' => 'center',
]
];
}
//没有图片,只有excel表的$allData(例子,有图片的只需在$images添加相应的图片地址即可)
Array
(
[excelCellDatas] => Array
(
[测试数据] => Array
(
[B] => Array
(
[3] => Array
(
[content] => 绕组1
[style] => Array
(
[fontSize] => 10
[width] => 20
[bold] => 1
[valignment] => center
[alignment] => center
[autoSize] => 1
)
)
[4] => Array
(
[content] => 1
[style] => Array
(
[fontSize] => 10
[width] => 20
[valignment] => center
[alignment] => center
)
)
[2] => Array
(
[content] => 测试数据
[style] => Array
(
[fontSize] => 20
[height] => 80
[width] => 20
[bold] => 1
[valignment] => center
[alignment] => center
[mergeEnd] => I2
)
)
)
[C] => Array
(
[3] => Array
(
[content] => 分接1
[style] => Array
(
[fontSize] => 10
[width] => 20
[bold] => 1
[valignment] => center
[alignment] => center
[autoSize] => 1
)
)
[4] => Array
(
[content] => 2
[style] => Array
(
[fontSize] => 10
[width] => 20
[valignment] => center
[alignment] => center
)
)
)
[D] => Array
(
[3] => Array
(
[content] => 电压 (V)
[style] => Array
(
[fontSize] => 10
[width] => 20
[bold] => 1
[valignment] => center
[alignment] => center
[autoSize] => 1
)
)
[4] => Array
(
[content] => 3
[style] => Array
(
[fontSize] => 10
[width] => 20
[valignment] => center
[alignment] => center
)
)
)
[E] => Array
(
[3] => Array
(
[content] => 绕组2
[style] => Array
(
[fontSize] => 10
[width] => 20
[bold] => 1
[valignment] => center
[alignment] => center
[autoSize] => 1
)
)
[4] => Array
(
[content] => 4
[style] => Array
(
[fontSize] => 10
[width] => 20
[valignment] => center
[alignment] => center
)
)
)
[F] => Array
(
[3] => Array
(
[content] => 分接2
[style] => Array
(
[fontSize] => 10
[width] => 20
[bold] => 1
[valignment] => center
[alignment] => center
[autoSize] => 1
)
)
[4] => Array
(
[content] => 5
[style] => Array
(
[fontSize] => 10
[width] => 20
[valignment] => center
[alignment] => center
)
)
)
[G] => Array
(
[3] => Array
(
[content] => 电压 (V)
[style] => Array
(
[fontSize] => 10
[width] => 20
[bold] => 1
[valignment] => center
[alignment] => center
[autoSize] => 1
)
)
[4] => Array
(
[content] => 6
[style] => Array
(
[fontSize] => 10
[width] => 20
[valignment] => center
[alignment] => center
)
)
)
[H] => Array
(
[3] => Array
(
[content] => 计算比值
[style] => Array
(
[fontSize] => 10
[width] => 20
[bold] => 1
[valignment] => center
[alignment] => center
[autoSize] => 1
)
)
[4] => Array
(
[content] => 7
[style] => Array
(
[fontSize] => 10
[width] => 20
[valignment] => center
[alignment] => center
)
)
)
[I] => Array
(
[3] => Array
(
[content] => 实测偏差 (%)
[style] => Array
(
[fontSize] => 10
[width] => 20
[bold] => 1
[valignment] => center
[alignment] => center
[autoSize] => 1
)
)
[4] => Array
(
[content] => 8
[style] => Array
(
[fontSize] => 10
[width] => 20
[valignment] => center
[alignment] => center
)
)
)
)
)
[excelDatas] => Array
(
[测试数据] => Array
(
[data_4_1] => B4
[data_4_2] => C4
[data_4_3] => D4
[data_4_4] => E4
[data_4_5] => F4
[data_4_6] => G4
[data_4_7] => H4
[data_4_8] => I4
)
)
[images] => Array
(
)
[borders] => Array
(
[测试数据] => Array
(
[0] => B3:I4
)
)
)
5.最终导出excel表和zip(由于文章太多了,Excel类和ZipArchive类自行引入)
function createExcelFile($allData, $fileName, $store = false)
{
if (stripos($_SERVER['SystemRoot'], 'windows') !== false) {
$fileName = urlencode($fileName);
}
$excelFile = Excel::create($fileName, function ($excel) use ($allData) {
$excelCellDatas = $allData['excelCellDatas'];
$borders = $allData['borders'];
$excelDatas = $allData['excelDatas'];
foreach ($excelCellDatas as $sheetName => $createSheet) {
$excelSheetDatas = isset($excelDatas[$sheetName]) ? $excelDatas[$sheetName] : [];
if (is_numeric($sheetName)) {
$sheetName = "$sheetName";
}
$excel->sheet($sheetName, function ($sheet) use ($createSheet, $borders, $excelSheetDatas, $sheetName) {
//某表格数据,边框参数,设置颜色区域,表格标题
$rowMax=0;
foreach ($createSheet as $col => $rows) {
$colMaxContentLen = 0;
foreach ($rows as $row => $cellData) {
if($row.$col!='2B'){
$colMaxContentLen = max($colMaxContentLen, strlen($cellData['content']));
}
if (isset($cellData['style'])) {
if (isset($cellData['style']['width']) || isset($cellData['style']['height'])) {
$width = isset($cellData['style']['width']) ? (int)$cellData['style']['width'] : 8.43;
$height = isset($cellData['style']['height']) ? (int)$cellData['style']['height'] : 15;
$sheet->setSize($col . $row, $width, $height);
}
if (isset($cellData['style']['mergeEnd'])) {
$sheet->mergeCells($col . $row . ':' . $cellData['style']['mergeEnd']);
}
}
$sheet->cell($col . $row, function ($cell) use ($cellData, $sheet, $excelSheetDatas, $col, $row) {
if (isset($cellData['style']['fontSize'])) {
$cell->setFontSize((int)$cellData['style']['fontSize']);
}
if (isset($cellData['style']['bold']) && $cellData['style']['bold'] != 0) {
$cell->setFontWeight();
}
if (in_array($col . $row, $excelSheetDatas)) {
$cell->setBackground('#99CCFF');
}
$isImage = false;
$cellContentArray = explode('|', $cellData['content']);
if ($cellContentArray[0] != $cellData['content']) {
if (isset($cellContentArray[1]) && strstr($cellContentArray[1], '/uploads/') !== false) {
$imgName=explode('/',$cellContentArray[1]);
$imgName=end($imgName);
$cell->setValue($cellContentArray[0].DIRECTORY_SEPARATOR.$imgName);
$isImage = true;
}
}
if ($isImage === false) {
$sheet->getCell($cell->cells)->setValueExplicit($cellData['content'], PHPExcel_Cell_DataType::TYPE_STRING);
}
if (isset($cellData['style'])) {
if (isset($cellData['style']['alignment'])) {
$cell->setAlignment($cellData['style']['alignment']);
}
if (isset($cellData['style']['valignment'])) {
$cell->setValignment($cellData['style']['valignment']);
}
}
});
$rowMax=max((int)$row,$rowMax);
}
foreach($rows as $row => $cellData){
$autoSize = isset($cellData['style']['autoSize']) && $cellData['style']['autoSize'];
if($autoSize) {
$sheet->setSize($col . $row, $colMaxContentLen * 0.8, $height);
}
}
}
$sheet->mergeCells('B'.($rowMax+1) .':B'.($rowMax+1));
foreach ($borders[$sheetName] as $border) {
$leftBorder = false;
$rightBorder = false;
$borderArray = explode(':', $border);
$borderArray[1] = isset($borderArray[1]) ? $borderArray[1] : $borderArray[0];
preg_match('/([A-Z]{1,})(\d{1,})/', $borderArray[0], $left);
preg_match('/([A-Z]{1,})(\d{1,})/', $borderArray[1], $right);
if (isset($left[2]) && isset($right[2])) {
$leftBorder = $left[1] . $left[2] . ':' . $left[1] . $right[2];
$rightBorder = $right[1] . $left[2] . ':' . $right[1] . $right[2];
}
$sheet->getStyle($border)->applyFromArray([
'borders' => [
'inside' => ['style' => 'thin'],
'top' => ['style' => 'medium'],
'bottom' => ['style' => 'medium'],
'left' => ['style' => $leftBorder ? 'medium' : 'thin'],
'right' => ['style' => $rightBorder ? 'medium' : 'thin'],
]
]);
}
});
}
});
if ($store === false) {
$excelFile->export('xls');
return true;
}
if ($store) {
$excelFile->store('xls', storage_path('temp'));
return true;
}
return false;
}
function getZipFile($allData = [], $name = '测试文件')
{
$downloadFileName = $name .'.zip';
$fileName = date('YmdHis');
if (createExcelFile($allData, $fileName, true)) {
$zipFile = new ZipArchive();
$zipFileName = $fileName . '.zip';
$zipFilePath = storage_path('temp') . DIRECTORY_SEPARATOR . $zipFileName;
if (is_file($zipFilePath)) {
@unlink($zipFilePath);
}
if ($zipFile->open($zipFilePath, ZipArchive::CREATE) === true) {
$excelFileName = $fileName . '.xls';
if (stripos($_SERVER['SystemRoot'], 'windows') !== false) {
$excelFileName = iconv('UTF-8', 'GB2312//IGNORE', $fileName) . '.xls';
}
$zipFile->addFile(storage_path('temp') . DIRECTORY_SEPARATOR . $excelFileName, $name. '.xls');
foreach ($allData['images'] as $imagePath => $images) {
foreach ($images as $imageName => $image) {
$image = str_replace('/uploads/', '', $image);
if (is_file(public_path('uploads') . DIRECTORY_SEPARATOR . $image)) {
$exportImageName=explode('/',$image);
$zipFile->addFile(public_path('uploads') . DIRECTORY_SEPARATOR . $image, $imagePath . '/' . end($exportImageName));
}
}
}
$zipFile->close();
ob_end_clean();
$downloadFileName = urlencode($downloadFileName);
header("Content-Type: application/force-download");//告诉浏览器强制下载
header("Content-Transfer-Encoding: binary");//声明一个下载的文件
header('Content-Type: application/zip');//设置文件内容类型为zip
header('Content-Disposition:attachment;filename="'.$downloadFileName.'"');//声明文件名
header('Content-Length: ' . filesize($zipFilePath));//声明文件大小
error_reporting(0);
readfile($zipFilePath);
flush();
exit;
}
}
}