123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- <?php
- namespace addons\shopro\library;
- use PhpOffice\PhpSpreadsheet\Spreadsheet;
- use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
- use PhpOffice\PhpSpreadsheet\Style\Alignment;
- use PhpOffice\PhpSpreadsheet\Style\Border;
- use Cache\Adapter\Redis\RedisCachePool;
- use Cache\Bridge\SimpleCache\SimpleCacheBridge;
- use PhpOffice\PhpSpreadsheet\Settings;
- use addons\shopro\library\Redis;
- class Export
- {
- protected $last_memory_limit = '256M';
- protected $config = [
- 'save_type' => 'download',
- 'list_rows' => 1000,
- 'save_path' => RUNTIME_PATH . 'storage/export/',
- 'memory_limit' => '512M',
- 'time_limit' => 0,
- 'cache_driver' => 'default',
- 'redis_select' => null,
- ];
- public function __construct()
- {
- $this->config['time_limit'] = intval($this->config['time_limit']);
- $this->config['list_rows'] = intval($this->config['list_rows']) ? intval($this->config['list_rows']) : 1000;
-
- $this->setLimit();
-
- $this->setCache();
- }
-
- public function export($params, \Closure $callback)
- {
- $fileName = $params['file_name'];
- $cellTitles = $params['cell_titles'];
- $cell_num = count($cellTitles);
- $total = $params['total'];
- $is_sub_cell = $params['is_sub_cell'] ?? false;
- $sub_start_cell = $params['sub_start_cell'] ?? null;
- $sub_field = $params['sub_field'] ?? null;
- $cellName = array('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', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ');
- $last_cell_key = $cellName[$cell_num - 1];
-
- $last_page = intval(ceil($total / $this->config['list_rows']));
-
- $spreadsheet = new Spreadsheet();
-
- $sheet = $spreadsheet->getActiveSheet(0);
-
- $sheet->getStyle('A1:' . $last_cell_key . '1')->getFont()->setBold(true);
-
- $i = 0;
- foreach ($cellTitles as $key => $cell) {
- $sheet->setCellValue($cellName[$i] . '1', $cell);
- $i++;
- }
- $cell_total = 2;
- for($page = 1;$page <= $last_page;$page++) {
- $is_last_page = $page == $last_page ? true : false;
-
- $datas = $callback([
- 'page' => $page,
- 'list_rows' => $this->config['list_rows'],
- 'is_last_page' => $is_last_page
- ]);
- foreach ($datas as $key => $data) {
- if ($is_last_page && $key == count($datas) - 1 && (!is_array($data) || count($data) == 1)) {
- $total_text = is_array($data) ? current($data) : $data;
- $sheet->mergeCells('A' . $cell_total . ':' . $last_cell_key . $cell_total);
- $sheet->setCellValue('A' . $cell_total, $total_text);
- } else {
- $items_count = 1;
- if ($is_sub_cell) {
- $items_count = count($data[$sub_field]);
- }
- $items_count = $items_count >= 1 ? $items_count : 1;
-
-
- $i = 0;
- $sub_start = false;
- foreach ($cellTitles as $k => $cell) {
- if ($k == $sub_start_cell) {
-
- $sub_start = true;
- }
- if ($is_sub_cell) {
- if (!$sub_start) {
-
- $current_text = $data[$k] ?? '';
- if ($items_count > 1) {
-
- $sheet->mergeCells($cellName[$i] . ($cell_total) . ':' . $cellName[$i] . ($cell_total + $items_count - 1));
- $sheet->getCell($cellName[$i] . ($cell_total))->getStyle()->getAlignment()->setVertical(Alignment::VERTICAL_CENTER);
- }
- $sheet->setCellValue($cellName[$i] . ($cell_total), $current_text);
- } else {
-
- foreach ($data[$sub_field] as $j => $sub) {
- $current_text = $sub[$k] ?? '';
- $sheet->setCellValue($cellName[$i] . ($cell_total + $j), $current_text);
- }
- }
- } else {
- $current_text = $data[$k] ?? '';
- $sheet->setCellValue($cellName[$i] . $cell_total, $current_text);
- }
- $i++;
- }
-
- $cell_total = $cell_total + $items_count;
- }
- }
- }
-
- $sheet->getStyle('A1:' . $last_cell_key . $cell_total)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
-
- return $this->output($spreadsheet, $fileName);
- }
-
- public function output($spreadsheet, $fileName)
- {
- $class_name = '\\PhpOffice\\PhpSpreadsheet\\Writer\\Xlsx';
- if (!class_exists($class_name)) {
- error_stop('文件输出格式不支持');
- }
- if ($this->config['save_type'] == 'save') {
-
- if (!is_dir($this->config['save_path'])) {
- @mkdir($this->config['save_path'], 0755, true);
- }
-
- $save_file = $this->config['save_path'] . $fileName . '-' . date('YmdHis') . '.xlsx';
- $result = [
- 'file_path' => str_replace(ROOT_PATH, '项目目录/', $save_file)
- ];
- } else {
- $save_file = $fileName . '-' . date('YmdHis') . '.xlsx';
- $result = [
- 'file_name' => $save_file
- ];
- ob_end_clean();
- header('pragma:public');
- header("Content-type:application/octet-stream; charset=utf-8; name=" . urlencode($save_file));
- header("Content-Disposition:attachment; filename=" . urlencode($save_file));
- $save_file = 'php://output';
- }
-
- $writer = new $class_name($spreadsheet);
- $writer->save($save_file);
- return $result;
-
-
- }
-
- public function setLimit()
- {
-
- set_time_limit($this->config['time_limit']);
-
- $this->last_memory_limit = ini_get('memory_limit');
- ini_set('memory_limit', $this->config['memory_limit']);
- }
-
- public function setCache()
- {
-
- if ($this->config['cache_driver'] == 'redis') {
-
- if (!class_exists(RedisCachePool::class)) {
-
- error_stop('请安装扩展包:composer require cache/simple-cache-bridge cache/redis-adapter');
- }
- if (is_null($this->config['redis_select'])) {
- error_stop('请在 addons/shopro/library/Export.php 文件,defaultConfig 中配置 redis_select 库');
- }
- $options = [
- 'select' => $this->config['redis_select']
- ];
- $redis = (new Redis($options))->getRedis();
- $pool = new RedisCachePool($redis);
- $simpleCache = new SimpleCacheBridge($pool);
- Settings::setCache($simpleCache);
- }
- }
- public function getConfig()
- {
- return $this->config;
- }
- }
|