zx/crmeb/services/SpreadsheetExcelService.php

387 lines
14 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace crmeb\services;
use think\exception\ValidateException;
class SpreadsheetExcelService
{
//
private static $instance = null;
//PHPSpreadsheet实例化对象
private static $spreadsheet = null;
//sheet实例化对象
private static $sheet = null;
private static $createsheet = null;
//表头计数
protected static $count;
//表头占行数
protected static $topNumber = 3;
//表能占据表行的字母对应self::$cellkey
protected static $cells;
//表头数据
protected static $data = [];
//文件名
protected static $title = '订单导出';
//行宽
protected static $width = 20;
//行高
protected static $height = 50;
//保存文件目录
protected static $path = 'phpExcel/';
//总行数
protected static $colum = 3;
//设置style
private static $styleArray = [
// 'borders' => [
// 'allBorders' => [
// // PHPExcel_Style_Border里面有很多属性想要其他的自己去看
// // 'style' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK,//边框是粗的
// // 'style' => \PHPExcel_Style_Border::BORDER_DOUBLE,//双重的
// // 'style' => \PHPExcel_Style_Border::BORDER_HAIR,//虚线
// // 'style' => \PHPExcel_Style_Border::BORDER_MEDIUM,//实粗线
// // 'style' => \PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT,//虚粗线
// // 'style' => \PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT,//点虚粗线
// 'style' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,//细边框
// // 'color' => ['argb' => 'FFFF0000'],
// ],
// ],
'font' => [
'bold' => true
],
'alignment' => [
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER
]
];
private function __construct(){}
private function __clone(){}
public static function instance()
{
if (self::$instance === null) {
self::$instance = new self();
self::$spreadsheet = $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
}
return self::$instance;
}
public function createOrActive($i = null)
{
if($i){
self::$sheet = self::$spreadsheet->createSheet();
}else{
self::$sheet = self::$spreadsheet->getActiveSheet();
}
return $this;
}
/**
*设置字体格式
* @param $title string 必选
* return string
*/
public static function setUtf8($title)
{
return iconv('utf-8', 'gb2312', $title);
}
/**
* 创建保存excel目录
* return string
*/
public static function savePath()
{
if(!is_dir(self::$path)){
if (mkdir(self::$path, 0700) == false) {
return false;
}
}
//年月一级目录
$mont_path = self::$path.date('Ym');
if(!is_dir($mont_path)){
if (mkdir($mont_path, 0700) == false) {
return false;
}
}
//日二级目录
$day_path = $mont_path.'/'.date('d');
if(!is_dir($day_path)){
if (mkdir($day_path, 0700) == false) {
return false;
}
}
return $day_path;
}
/**
* 设置标题
* @param $title string || array ['title'=>'','name'=>'','info'=>[]]
* @param $Name string
* @param $info string || array;
* @param $funName function($style,$A,$A2) 自定义设置头部样式
* @return $this
*/
public function setExcelTile(array $data)
{
//设置参数
if (is_array($data)) {
if (isset($data['title'])) $title = $data['title'];
if (isset($data['sheets'])) $sheets = $data['sheets'];
}
empty($title) ? $title = self::$title : self::$title = $title;
if (empty($sheets)) $sheets = time();
//设置Excel属性
self::$spreadsheet->getProperties()
->setCreator("Neo")
->setLastModifiedBy("Neo")
->setTitle(self::setUtf8($title))
->setSubject($sheets)
->setDescription("")
->setKeywords($sheets)
->setCategory("");
self::$sheet->setTitle($sheets);
self::$sheet->mergeCells('A1:' . self::$cells . '1'); //合并表头单元格
self::$sheet->getRowDimension('A')->setRowHeight(40); //设置行高
self::$sheet->setCellValue('A1', $title); //负值
self::$sheet->getStyle('A1')->getFont()->setName('黑体');
self::$sheet->getStyle('A1')->getFont()->setSize(20);
self::$sheet->getStyle('A1')->getFont()->setBold(true);
self::$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); //设置左对齐
if(isset($data['mark']) && !empty($data['mark'])){
foreach ($data['mark'] as $k => $v){
$i = $k + 2;
self::$sheet->mergeCells('A'.$i.':' . self::$cells . $i);
self::$sheet->setCellValue('A'.$i, $v);
self::$sheet->getStyle('A'.$i)->getFont()->setName('宋体');
self::$sheet->getStyle('A'.$i)->getFont()->setSize(16);
self::$sheet->getStyle('A'.$i)->getFont()->setBold(true);
self::$sheet->getStyle('A'.$i)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT);
}
}
return $this;
}
/**
* 设置第二行标题内容
* @param $info array (['name'=>'','site'=>'','phone'=>123] || ['我是表名','我是地址','我是手机号码'] ) || string 自定义
* @return string
*/
private static function setCellInfo($info)
{
$content = ['操作者:', '导出日期:' . date('Y-m-d', time()), '地址:', '电话:'];
if (is_array($info) && !empty($info)) {
if (isset($info['name'])) {
$content[0] .= $info['name'];
} else {
$content[0] .= isset($info[0]) ? $info[0] : '';
}
if (isset($info['site'])) {
$content[2] .= $info['site'];
} else {
$content[2] .= isset($info[1]) ? $info[1] : '';
}
if (isset($info['phone'])) {
$content[3] .= $info['phone'];
} else {
$content[3] .= isset($info[2]) ? $info[2] : '';
}
return implode(' ', $content);
} else if (is_string($info)) {
return empty($info) ? implode(' ', $content) : $info;
}
}
/**
* 设置头部信息
* @param $data array
* @return $this
*/
public function setExcelHeader($data,$topNumber)
{
$span = 'A';
self::$topNumber = $topNumber;
foreach ($data as $key => $value) {
self::$sheet->getColumnDimension($span)->setWidth(self::$width);
self::$sheet->setCellValue($span.self::$topNumber, $value);
self::$sheet->getStyle($span.self::$topNumber)->getFont()->setSize(16);
$span++;
}
$span = chr(ord($span) -1);
self::$sheet->getRowDimension(self::$topNumber)->setRowHeight(25);
self::$sheet->getStyle('A1:' . $span.self::$topNumber)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
self::$cells = $span;
return $this;
}
/**
*
* execl数据导出
* @param $data 需要导出的数据 格式和以前的可是一样
*
* 特殊处理:合并单元格需要先对数据进行处理
*/
public function setExcelContent($data = [])
{
if (!empty($data) && is_array($data)) {
$column = self::$topNumber+1;
// 行写入
foreach ($data as $key => $rows) {
$span = 'A';
// 列写入
foreach ($rows as $keyName => $value) {
self::$sheet->setCellValue($span . $column, $value);
$span++;
}
$column++;
}
$span = chr(ord($span) -1);
self::$colum = $column;
self::$sheet->getDefaultRowDimension()->setRowHeight(self::$height);
//设置内容字体样式
self::$sheet->getStyle('A'.self::$topNumber .':'. $span.$column)->applyFromArray(self::$styleArray);
//设置边框
self::$sheet->getStyle('A1:' . $span.$column )->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
//设置自动换行
self::$sheet->getStyle('A4:' . $span.$column)->getAlignment()->setWrapText(true);
}
return $this;
}
public function setExcelEnd(array $data)
{
if(!empty($data)){
foreach ($data as $key => $value){
$i = self::$colum + $key ;
self::$sheet->mergeCells('A'.$i.':' . self::$cells.$i);
self::$sheet->setCellValue('A'.$i, $value);
self::$sheet->getStyle('A'.$i)->getFont()->setName('宋体');
self::$sheet->getStyle('A'.$i)->getFont()->setSize(16);
self::$sheet->getStyle('A'.$i)->getFont()->setBold(true);
self::$sheet->getStyle('A'.$i)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT);
}
self::$sheet->getStyle('A1:' .self::$cells.$i)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
}
return $this;
}
/**
* 保存表格数据
* @param $filename 文件名称
* @param $suffix 文件后缀名
* @param $path 是否保存文件文件
* @return 保存文件return string
*/
public function excelSave($fileName = '',$suffix = 'xlsx',$path)
{
if(empty($fileName)) $fileName = date('YmdHis').time();
if(empty($suffix)) $suffix = 'xlsx';
// 重命名表UTF8编码不需要这一步
if (mb_detect_encoding($fileName) != "UTF-8") $fileName = iconv("utf-8", "gbk//IGNORE", $fileName);
$save_path = self::$path.$path;
$root_path = app()->getRootPath().'public/'.$save_path;
if(!is_dir($root_path)) mkdir($root_path, 0755,true);
$spreadsheet = self::$spreadsheet;
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$writer->save($root_path.'/'.$fileName.'.'.$suffix);
return $save_path.'/'.$fileName.'.'.$suffix;
}
/**
* TODO
* @param $filePath 文件路径
* @param array $sql 需要入库的字段 => excel表的列 例 [order_sn => 'B']
* @param array $where 每条入库的条件 同上
* @param int $startRow 有效数据从第几行开始
* @return array
* @author Qinii
* @day 3/15/21
*/
public function _import($filePath,array $sql,$where = [],$startRow = 1)
{
if(!file_exists($filePath)) return ;
$ext = ucfirst(pathinfo($filePath, PATHINFO_EXTENSION));
$ret = [];
if (in_array($ext, ['Xlsx', 'Xls'])) {
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($ext);
$spreadsheet = $reader->load($filePath);
$sheet = $spreadsheet->getActiveSheet();
$row_count = $sheet->getHighestDataRow();//取得总行数
for ($row = $startRow; $row <= $row_count; $row++) {
$con = [];
$item = [];
$one = [];
// $getK = $sheet->getCell('A'.$row)->getValue();
// if ($getK) {
// $getV = $sheet->getCell('B'.$row)->getValue();
// $one[] = [$getK => $getV];
// }
if (!empty($where)) {
foreach ($where as $k => $v) {
$con_value = $sheet->getCell($v . $row)->getValue();
if ($con_value) {
$con[$k] = $con_value;
}
}
if (!empty($con)) $one['where'] = $con;
}
if ($con && !empty($sql)) {
foreach ($sql as $key => $value) {
$key_value = $sheet->getCell($value . $row)->getValue();
$item[$key] = $key_value ?? '';
}
if (!empty($item)) $one['value'] = $item;
}
if ($one) $ret[] = $one;
}
}
return $ret;
}
/**
* TODO 检测导入格式
* @param $filePath
* @param array $check
* @return bool
* @author Qinii
* @day 5/7/21
*/
public function checkImport($filePath,$check = [])
{
$ext = ucfirst(pathinfo($filePath, PATHINFO_EXTENSION));
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($ext);
$spreadsheet = $reader->load($filePath);
$sheet = $spreadsheet->getActiveSheet();
if(!empty($check)){
foreach ($check as $s => $c){
$_c = $sheet->getCell($s)->getValue();
if($_c !== $c) throw new ValidateException('表格"'.$s.'"不是"'.$c.'"不可导入');
}
}
return true;
}
}