Export.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <?php namespace Excel\Lib;
  2. use Dever;
  3. Dever::apply('autoload', 'excel', 'vendor');
  4. use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
  5. class Export extends Core
  6. {
  7. public function act($data = array(), $header = array(), $fileName = '', $sheet = 0, $sheetName = '', $return = false, $xls = false, $password = '', $save = '')
  8. {
  9. if (!$xls) {
  10. $xls = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
  11. }
  12. if ($sheet > 0) {
  13. $xls->createSheet();
  14. }
  15. $act = $xls->setActiveSheetIndex($sheet);
  16. if ($sheetName) {
  17. $act->setTitle($sheetName);
  18. }
  19. $dropdownOptions = []; // 存下拉列配置
  20. // ====== 多行表头处理 ======
  21. $row = 1;
  22. if ($header) {
  23. $headerRowCount = count($header);
  24. $colCount = max(array_map('count', $header));
  25. for ($r = 0; $r < $headerRowCount; $r++) {
  26. $rowHeader = $header[$r];
  27. for ($c = 0; $c < $colCount; $c++) {
  28. $col = $this->cell[$c];
  29. $value = $rowHeader[$c] ?? null;
  30. if (is_array($value)) {
  31. $act->setCellValue($col . $row, $value[0]);
  32. $dropdownOptions[$col] = $value[1] ?? [];
  33. } else {
  34. $act->setCellValue($col . $row, $value);
  35. }
  36. $act->getColumnDimension($col)->setWidth(30);
  37. }
  38. $row++;
  39. }
  40. // 自动合并空单元格
  41. for ($r = 0; $r < $headerRowCount; $r++) {
  42. $rowHeader = $header[$r];
  43. $startCol = null;
  44. $mergeCount = 0;
  45. for ($c = 0; $c < $colCount; $c++) {
  46. $col = $this->cell[$c];
  47. $cellVal = $act->getCell($col . ($r+1))->getValue();
  48. if ($cellVal !== null && $cellVal !== '') {
  49. if ($mergeCount > 1 && $startCol !== null) {
  50. $act->mergeCells($this->cell[$startCol] . ($r+1) . ':' . $this->cell[$c-1] . ($r+1));
  51. }
  52. $startCol = $c;
  53. $mergeCount = 1;
  54. } else {
  55. $mergeCount++;
  56. }
  57. }
  58. if ($mergeCount > 1 && $startCol !== null) {
  59. $act->mergeCells($this->cell[$startCol] . ($r+1) . ':' . $this->cell[$colCount-1] . ($r+1));
  60. }
  61. }
  62. }
  63. // ====== 数据处理 ======
  64. if($data) {
  65. $i = 0;
  66. $height = $max = 80;
  67. foreach($data as $v) {
  68. $j = 0;
  69. foreach($v as $cell) {
  70. $col = $this->cell[$j];
  71. $addr = $col . ($i+$row);
  72. $html = \Dever\Helper\Str::ishtml($cell);
  73. if ($html) {
  74. $wizard = new \PhpOffice\PhpSpreadsheet\Helper\Html;
  75. $cell = $wizard->toRichTextObject('<?xml encoding="UTF-8">' . $cell);
  76. }
  77. if (!$html && (strstr($cell, '.jpg') || strstr($cell, '.gif') || strstr($cell, '.png'))) {
  78. // === 图片处理逻辑保持原样 ===
  79. $key = ($i+$row);
  80. $value = false;
  81. if (strpos($cell, '||')) {
  82. $t = explode('||', $cell);
  83. $cell = $t[1];
  84. $value = $t[0];
  85. }
  86. $temp = explode(',', $cell);
  87. foreach ($temp as $ck => $cv) {
  88. $objDrawing[$ck] = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
  89. if (!is_file($cv)) continue;
  90. $objDrawing[$ck]->setPath($cv);
  91. $objDrawing[$ck]->setHeight($height);
  92. $objDrawing[$ck]->setCoordinates($addr);
  93. $objDrawing[$ck]->setOffsetX(12);
  94. $offsetY = ($ck == 0) ? 5 : ($offsetY + $height + 5);
  95. $objDrawing[$ck]->setOffsetY($offsetY);
  96. $objDrawing[$ck]->setWorksheet($act);
  97. }
  98. if ($value) {
  99. $act->setCellValue($addr, $value);
  100. }
  101. $th = $height * count($temp);
  102. if ($th > $max) $max = $th;
  103. $act->getRowDimension($i+$row)->setRowHeight($max);
  104. } else {
  105. if (is_numeric($cell) && mb_strlen($cell) >= 10) $cell .= "\t";
  106. $act->setCellValue($addr, $cell);
  107. $act->getStyle($addr)->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
  108. }
  109. // ==== 下拉逻辑保持不变 ====
  110. if (!empty($dropdownOptions[$col])) {
  111. $validation = $act->getCell($addr)->getDataValidation();
  112. $validation->setType(DataValidation::TYPE_LIST);
  113. $validation->setErrorStyle(DataValidation::STYLE_INFORMATION);
  114. $validation->setAllowBlank(false);
  115. $validation->setShowInputMessage(true);
  116. $validation->setShowErrorMessage(true);
  117. $validation->setShowDropDown(true);
  118. $validation->setFormula1('"' . implode(',', $dropdownOptions[$col]) . '"');
  119. }
  120. $act->getColumnDimension($col)->setAutoSize(true);
  121. $act->getColumnDimension($col)->setWidth(30);
  122. $j++;
  123. }
  124. $i++;
  125. }
  126. }
  127. // ====== 保存逻辑保持原样 ======
  128. if ($header && $return) {
  129. return $xls;
  130. }
  131. if (!$fileName) {
  132. $fileName = uniqid(time(),true);
  133. }
  134. $fileName .= '-' . date('Ymd-His') . '-' . rand(1000,9999);
  135. $write = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($xls, "Xlsx");
  136. if ($save) {
  137. $save = Dever::file('excel/' . $save . '.xlsx');
  138. $write->save($save);
  139. if ($password) {
  140. Dever::apply('autoload', 'excel', 'secure');
  141. $encrypt = new \Nick\SecureSpreadsheet\Encrypt();
  142. $encrypt->input($save)->password($password)->output($save);
  143. }
  144. return $save;
  145. } else {
  146. if ($password) {
  147. $save = Dever::file('excel/' . $save . '.xlsx');
  148. $write->save($save);
  149. Dever::apply('autoload', 'excel', 'secure');
  150. $encrypt = new \Nick\SecureSpreadsheet\Encrypt();
  151. $encrypt->input($save)->password($password)->output($save);
  152. header('Content-Type: application/octet-stream');
  153. header('Content-Transfer-Encoding: Binary');
  154. header("Content-disposition: attachment; filename=\"" . basename($save) . "\"");
  155. readfile($save);
  156. @unlink($save);
  157. } else {
  158. ob_end_clean();
  159. header('Content-Type: application/vnd.ms-excel');
  160. header('pragma:public');
  161. header("Content-Disposition:attachment;filename=$fileName.xlsx");
  162. $write->save('php://output');
  163. }
  164. }
  165. }
  166. }