SpreadsheetExcelService.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace crmeb\services;
  12. use PhpOffice\PhpSpreadsheet\Style\Alignment;
  13. use PhpOffice\PhpSpreadsheet\Writer\Exception;
  14. class SpreadsheetExcelService
  15. {
  16. //
  17. private static $instance = null;
  18. //PHPSpreadsheet实例化对象
  19. private static $spreadsheet = null;
  20. //sheet实例化对象
  21. private static $sheet = null;
  22. //表头计数
  23. protected static $count;
  24. //表头占行数
  25. protected static $topNumber = 3;
  26. //表能占据表行的字母对应self::$cellkey
  27. protected static $cells;
  28. //表头数据
  29. protected static $data = [];
  30. //文件名
  31. protected static $title = '订单导出';
  32. //行宽
  33. protected static $width = 20;
  34. //行高
  35. protected static $height = 50;
  36. //保存文件目录
  37. protected static $path = './phpExcel/';
  38. //设置style
  39. private static $styleArray = [
  40. // 'borders' => [
  41. // 'allBorders' => [
  42. // // PHPExcel_Style_Border里面有很多属性,想要其他的自己去看
  43. // // 'style' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK,//边框是粗的
  44. // // 'style' => \PHPExcel_Style_Border::BORDER_DOUBLE,//双重的
  45. // // 'style' => \PHPExcel_Style_Border::BORDER_HAIR,//虚线
  46. // // 'style' => \PHPExcel_Style_Border::BORDER_MEDIUM,//实粗线
  47. // // 'style' => \PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT,//虚粗线
  48. // // 'style' => \PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT,//点虚粗线
  49. // 'style' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,//细边框
  50. // // 'color' => ['argb' => 'FFFF0000'],
  51. // ],
  52. // ],
  53. 'font' => [
  54. 'bold' => true
  55. ],
  56. 'alignment' => [
  57. 'horizontal' => Alignment::HORIZONTAL_CENTER,
  58. 'vertical' => Alignment::VERTICAL_CENTER
  59. ]
  60. ];
  61. private function __construct()
  62. {
  63. }
  64. private function __clone()
  65. {
  66. }
  67. public static function instance()
  68. {
  69. if (self::$instance === null) {
  70. self::$instance = new self();
  71. self::$spreadsheet = $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
  72. self::$sheet = $spreadsheet->getActiveSheet();
  73. }
  74. return self::$instance;
  75. }
  76. /**
  77. *设置字体格式
  78. * @param $title string 必选
  79. * return string
  80. */
  81. public static function setUtf8(string $title)
  82. {
  83. return iconv('utf-8', 'gb2312', $title);
  84. }
  85. /**
  86. * 创建保存excel目录
  87. * return string
  88. */
  89. public static function savePath()
  90. {
  91. if (!is_dir(self::$path)) {
  92. if (mkdir(self::$path, 0700) == false) {
  93. return false;
  94. }
  95. }
  96. //年月一级目录
  97. $mont_path = self::$path . date('Ym');
  98. if (!is_dir($mont_path)) {
  99. if (mkdir($mont_path, 0700) == false) {
  100. return false;
  101. }
  102. }
  103. //日二级目录
  104. $day_path = $mont_path . '/' . date('d');
  105. if (!is_dir($day_path)) {
  106. if (mkdir($day_path, 0700) == false) {
  107. return false;
  108. }
  109. }
  110. return $day_path;
  111. }
  112. /**
  113. * 设置标题
  114. * @param $title string || array ['title'=>'','name'=>'','info'=>[]]
  115. * @param $Name string
  116. * @param $info string || array;
  117. * @return $this
  118. */
  119. public function setExcelTile(string $title = '', string $Name = '', $info = [])
  120. {
  121. //设置参数
  122. if (is_array($title)) {
  123. if (isset($title['title'])) $title = $title['title'];
  124. if (isset($title['name'])) $Name = $title['name'];
  125. if (isset($title['info'])) $info = $title['info'];
  126. }
  127. if (empty($title))
  128. $title = self::$title;
  129. else
  130. self::$title = $title;
  131. if (empty($Name)) $Name = time();
  132. //设置Excel属性
  133. self::$spreadsheet->getProperties()
  134. ->setCreator("Neo")
  135. ->setLastModifiedBy("Neo")
  136. ->setTitle(self::setUtf8($title))
  137. ->setSubject($Name)
  138. ->setDescription("")
  139. ->setKeywords($Name)
  140. ->setCategory("");
  141. self::$sheet->setTitle($Name);
  142. self::$sheet->setCellValue('A1', $title);
  143. self::$sheet->setCellValue('A2', self::setCellInfo($info));
  144. //文字居中
  145. self::$sheet->getStyle('A1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
  146. self::$sheet->getStyle('A2')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
  147. //合并表头单元格
  148. self::$sheet->mergeCells('A1:' . self::$cells . '1');
  149. self::$sheet->mergeCells('A2:' . self::$cells . '2');
  150. self::$sheet->getRowDimension(1)->setRowHeight(40);
  151. self::$sheet->getRowDimension(2)->setRowHeight(20);
  152. //设置表头字体
  153. self::$sheet->getStyle('A1')->getFont()->setName('黑体');
  154. self::$sheet->getStyle('A1')->getFont()->setSize(20);
  155. self::$sheet->getStyle('A1')->getFont()->setBold(true);
  156. self::$sheet->getStyle('A2')->getFont()->setName('宋体');
  157. self::$sheet->getStyle('A2')->getFont()->setSize(14);
  158. self::$sheet->getStyle('A2')->getFont()->setBold(true);
  159. self::$sheet->getStyle('A3:' . self::$cells . '3')->getFont()->setBold(true);
  160. return $this;
  161. }
  162. /**
  163. * 设置第二行标题内容
  164. * @param $info
  165. * @return string|void
  166. * @author: 吴汐
  167. * @email: 442384644@qq.com
  168. * @date: 2023/8/7
  169. */
  170. private static function setCellInfo($info)
  171. {
  172. $content = ['操作者:', '导出日期:' . date('Y-m-d', time()), '地址:', '电话:'];
  173. if (is_array($info) && !empty($info)) {
  174. if (isset($info['name'])) {
  175. $content[0] .= $info['name'];
  176. } else {
  177. $content[0] .= $info[0] ?? '';
  178. }
  179. if (isset($info['site'])) {
  180. $content[2] .= $info['site'];
  181. } else {
  182. $content[2] .= $info[1] ?? '';
  183. }
  184. if (isset($info['phone'])) {
  185. $content[3] .= $info['phone'];
  186. } else {
  187. $content[3] .= $info[2] ?? '';
  188. }
  189. return implode(' ', $content);
  190. } else if (is_string($info)) {
  191. return empty($info) ? implode(' ', $content) : $info;
  192. }
  193. }
  194. /**
  195. * 设置头部信息
  196. * @param $data array
  197. * @return $this
  198. */
  199. public static function setExcelHeader(array $data)
  200. {
  201. $span = 'A';
  202. foreach ($data as $value) {
  203. self::$sheet->getColumnDimension($span)->setWidth(self::$width);
  204. self::$sheet->setCellValue($span . self::$topNumber, $value);
  205. $span++;
  206. }
  207. self::$sheet->getRowDimension(3)->setRowHeight(self::$height);
  208. self::$cells = $span;
  209. return new self;
  210. }
  211. /**
  212. *
  213. * excl数据导出
  214. * @param $data 需要导出的数据 格式和以前的可是一样
  215. *
  216. * 特殊处理:合并单元格需要先对数据进行处理
  217. */
  218. public function setExcelContent($data = [])
  219. {
  220. if (!empty($data) && is_array($data)) {
  221. $span = '';
  222. $column = self::$topNumber + 1;
  223. // 行写入
  224. foreach ($data as $rows) {
  225. $span = 'A';
  226. // 列写入
  227. foreach ($rows as $value) {
  228. self::$sheet->setCellValue($span . $column, $value);
  229. $span++;
  230. }
  231. $column++;
  232. }
  233. self::$sheet->getDefaultRowDimension()->setRowHeight(self::$height);
  234. //设置内容字体样式
  235. self::$sheet->getStyle('A1:' . $span . $column)->applyFromArray(self::$styleArray);
  236. //设置边框
  237. self::$sheet->getStyle('A1:' . $span . $column)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
  238. //设置自动换行
  239. self::$sheet->getStyle('A4:' . $span . $column)->getAlignment()->setWrapText(true);
  240. }
  241. return new self;
  242. }
  243. /**
  244. * 保存表格数据,直接下载
  245. * @param string $fileName
  246. * @param string $suffix 文件后缀名
  247. * @param bool $is_save 是否保存文件
  248. * @return string string
  249. * @throws Exception
  250. */
  251. public function excelSave(string $fileName = '', string $suffix = 'xlsx', bool $is_save = false)
  252. {
  253. if (empty($fileName)) {
  254. $fileName = date('YmdHis') . time();
  255. }
  256. if (empty($suffix)) {
  257. $suffix = 'xlsx';
  258. }
  259. // 重命名表(UTF8编码不需要这一步)
  260. if (mb_detect_encoding($fileName) != "UTF-8") {
  261. $fileName = iconv("utf-8", "gbk//IGNORE", $fileName);
  262. }
  263. if ($suffix == 'xlsx') {
  264. header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  265. $class = "\PhpOffice\PhpSpreadsheet\Writer\Xlsx";
  266. } elseif ($suffix == 'xls') {
  267. header('Content-Type:application/vnd.ms-excel');
  268. $class = "\PhpOffice\PhpSpreadsheet\Writer\Xls";
  269. }
  270. // 清理缓存
  271. // ob_end_clean();
  272. $spreadsheet = self::$spreadsheet;
  273. $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
  274. if (!$is_save) {//直接下载
  275. header('Content-Disposition: attachment;filename="' . $fileName . '.' . $suffix . '"');
  276. header('Cache-Control: max-age=0');
  277. $writer->save('php://output');
  278. // 删除清空 释放内存
  279. $spreadsheet->disconnectWorksheets();
  280. unset($spreadsheet);
  281. exit;
  282. } else {//保存文件
  283. $path = self::savePath() . '/' . $fileName . '.' . $suffix;
  284. //$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
  285. //$writer->save($path);
  286. $writer->save(public_path() . $path);
  287. // 删除清空 释放内存
  288. $spreadsheet->disconnectWorksheets();
  289. unset($spreadsheet);
  290. return $path;
  291. }
  292. }
  293. }