rabin 14 órája
szülő
commit
fed483be11
2 módosított fájl, 150 hozzáadás és 51 törlés
  1. 76 51
      lib/Export.php
  2. 74 0
      lib/Import.php

+ 76 - 51
lib/Export.php

@@ -1,6 +1,8 @@
 <?php namespace Excel\Lib;
 use Dever;
 Dever::apply('autoload', 'excel', 'vendor');
+use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
+
 class Export extends Core
 {
     public function act($data = array(), $header = array(), $fileName = '', $sheet = 0, $sheetName = '', $return = false, $xls = false, $password = '', $save = '')
@@ -15,40 +17,73 @@ class Export extends Core
         if ($sheetName) {
             $act->setTitle($sheetName);
         }
+
+        $dropdownOptions = []; // 存下拉列配置
+
+        // ====== 多行表头处理 ======
         $row = 1;
-        if($header) {
-            $i = 0;
-            if (isset($header['top'])) {
-                foreach($header['top'] as $v) {
-                    $act->setCellValue($this->cell[$i] . $row, $v);
-                    $act->getColumnDimension($this->cell[$i])->setWidth(30);
-                    $i++;
+        if ($header) {
+            $headerRowCount = count($header);
+            $colCount = max(array_map('count', $header));
+
+            for ($r = 0; $r < $headerRowCount; $r++) {
+                $rowHeader = $header[$r];
+                for ($c = 0; $c < $colCount; $c++) {
+                    $col = $this->cell[$c];
+                    $value = $rowHeader[$c] ?? null;
+                    if (is_array($value)) {
+                        $act->setCellValue($col . $row, $value[0]);
+                        $dropdownOptions[$col] = $value[1] ?? [];
+                    } else {
+                        $act->setCellValue($col . $row, $value);
+                    }
+                    $act->getColumnDimension($col)->setWidth(30);
                 }
                 $row++;
-                unset($header['top']);
             }
-            $i = 0;
-            foreach($header as $v) {
-                $act->setCellValue($this->cell[$i] . $row, $v);
-                $act->getColumnDimension($this->cell[$i])->setWidth(30);
-                $i++;
+
+            // 自动合并空单元格
+            for ($r = 0; $r < $headerRowCount; $r++) {
+                $rowHeader = $header[$r];
+                $startCol = null;
+                $mergeCount = 0;
+                for ($c = 0; $c < $colCount; $c++) {
+                    $col = $this->cell[$c];
+                    $cellVal = $act->getCell($col . ($r+1))->getValue();
+                    if ($cellVal !== null && $cellVal !== '') {
+                        if ($mergeCount > 1 && $startCol !== null) {
+                            $act->mergeCells($this->cell[$startCol] . ($r+1) . ':' . $this->cell[$c-1] . ($r+1));
+                        }
+                        $startCol = $c;
+                        $mergeCount = 1;
+                    } else {
+                        $mergeCount++;
+                    }
+                }
+                if ($mergeCount > 1 && $startCol !== null) {
+                    $act->mergeCells($this->cell[$startCol] . ($r+1) . ':' . $this->cell[$colCount-1] . ($r+1));
+                }
             }
-            $row++;
         }
 
+        // ====== 数据处理 ======
         if($data) {
             $i = 0;
             $height = $max = 80;
             foreach($data as $v) {
                 $j = 0;
                 foreach($v as $cell) {
-                    //$cell = strip_tags($cell);
+                    $col = $this->cell[$j];
+                    $addr = $col . ($i+$row);
+
                     $html = \Dever\Helper\Str::ishtml($cell);
                     if ($html) {
                         $wizard = new \PhpOffice\PhpSpreadsheet\Helper\Html;
                         $cell = $wizard->toRichTextObject('<?xml encoding="UTF-8">' . $cell);
                     }
+
                     if (!$html && (strstr($cell, '.jpg') || strstr($cell, '.gif') || strstr($cell, '.png'))) {
+                        // === 图片处理逻辑保持原样 ===
                         $key = ($i+$row);
                         $value = false;
 
@@ -58,67 +93,57 @@ class Export extends Core
                             $value = $t[0];
                         }
                         $temp = explode(',', $cell);
-
                         foreach ($temp as $ck => $cv) {
                             $objDrawing[$ck] = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
-                            /*
-                            if (Dever::project('upload')) {
-                                $cv = str_replace('.jpg', '_t1.jpg', $cv);
-                                $cv = str_replace('.png', '_t1.png', $cv);
-                                $cv = Dever::load('upload/view')->get($cv);
-                            }
-                            $cv = Dever::local($cv);
-                            */
-                            if (!is_file($cv)) {
-                                continue;
-                            }
+                            if (!is_file($cv)) continue;
                             $objDrawing[$ck]->setPath($cv);
                             $objDrawing[$ck]->setHeight($height);
-                            //$objDrawing[$ck]->setWidth(150);
-                            $objDrawing[$ck]->setCoordinates($this->cell[$j] . ($i+$row));
+                            $objDrawing[$ck]->setCoordinates($addr);
                             $objDrawing[$ck]->setOffsetX(12);
-                            if ($ck == 0) {
-                                $offsetY = 5;
-                            } else {
-                                $offsetY = $offsetY + $height + 5;
-                            }
+                            $offsetY = ($ck == 0) ? 5 : ($offsetY + $height + 5);
                             $objDrawing[$ck]->setOffsetY($offsetY);
                             $objDrawing[$ck]->setWorksheet($act);
                         }
                         if ($value) {
-                            $act->setCellValue($this->cell[$j] . ($i+$row), $value);
+                            $act->setCellValue($addr, $value);
                         }
-                        
                         $th = $height * count($temp);
-                        if ($th > $max) {
-                            $max = $th;
-                        }
+                        if ($th > $max) $max = $th;
                         $act->getRowDimension($i+$row)->setRowHeight($max);
-                        
                     } else {
-                        if (!$cell) {
-                            //$cell = "";
-                        }
-                        if (is_numeric($cell) && mb_strlen($cell) >= 10) {
-                            $cell .= "\t";
-                        }
-                        $act->setCellValue($this->cell[$j] . ($i+$row), $cell);
-                        $act->getStyle($this->cell[$j] . ($i+$row))->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
+                        if (is_numeric($cell) && mb_strlen($cell) >= 10) $cell .= "\t";
+                        $act->setCellValue($addr, $cell);
+                        $act->getStyle($addr)->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
+                    }
+
+                    // ==== 下拉逻辑保持不变 ====
+                    if (!empty($dropdownOptions[$col])) {
+                        $validation = $act->getCell($addr)->getDataValidation();
+                        $validation->setType(DataValidation::TYPE_LIST);
+                        $validation->setErrorStyle(DataValidation::STYLE_INFORMATION);
+                        $validation->setAllowBlank(false);
+                        $validation->setShowInputMessage(true);
+                        $validation->setShowErrorMessage(true);
+                        $validation->setShowDropDown(true);
+                        $validation->setFormula1('"' . implode(',', $dropdownOptions[$col]) . '"');
                     }
-                    
-                    $act->getColumnDimension($this->cell[$j])->setAutoSize(true);
-                    $act->getColumnDimension($this->cell[$j])->setWidth(30);
+
+                    $act->getColumnDimension($col)->setAutoSize(true);
+                    $act->getColumnDimension($col)->setWidth(30);
                     $j++;
                 }
                 $i++;
             }
         }
+
+        // ====== 保存逻辑保持原样 ======
         if ($header && $return) {
             return $xls;
         }
         if (!$fileName) {
             $fileName = uniqid(time(),true);
         }
+        $fileName .= '-' . date('Ymd-His') . '-' . rand(1000,9999);
         $write = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($xls, "Xlsx");
         if ($save) {
             $save = Dever::file('excel/' . $save . '.xlsx');

+ 74 - 0
lib/Import.php

@@ -1,3 +1,76 @@
+<?php
+namespace Excel\Lib;
+use Dever;
+Dever::apply('autoload', 'excel', 'vendor');
+use PhpOffice\PhpSpreadsheet\IOFactory;
+use PhpOffice\PhpSpreadsheet\RichText\RichText;
+use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
+
+class Import extends Core
+{
+    /**
+     * 流式读取 Excel,每次返回一行
+     * @param string $file Excel 文件路径
+     * @param int $sheetIndex sheet 下标(默认 0)
+     * @param int $offset 跳过前几行
+     * @return \Generator
+     */
+    public function act($file = '', $sheetIndex = 0, $offset = 0, $head = [])
+    {
+        $file = mb_convert_encoding($file, "UTF-8", "gbk");
+        if (empty($file) || !file_exists($file)) {
+            Dever::error('file not exists!');
+        }
+
+        try {
+            $type = IOFactory::identify($file);
+            $reader = IOFactory::createReader($type);
+            //$reader->setReadDataOnly(true);
+            $spreadsheet = $reader->load($file);
+        } catch (\Exception $e) {
+            Dever::error('加载文件发生错误:"'.$file.'": ' . $e->getMessage());
+        }
+
+        $sheet = $spreadsheet->getSheet($sheetIndex);
+        $highestRow = $sheet->getHighestRow();
+        $highestCol = $sheet->getHighestColumn();
+        $columnCnt = array_search($highestCol, $this->cell) ?: 0;
+
+        $draws = $sheet->getDrawingCollection();
+        $pictures = [];
+        foreach ($draws as $img) {
+            list($col, $row) = Coordinate::coordinateFromString($img->getCoordinates());
+            $pictures[$row][$col][] = Dever::load('save', 'upload')->init(1)->act($img->getPath())['url'];
+        }
+        for ($row = $offset + 1; $row <= $highestRow; $row++) {
+            $rowData = [];
+            for ($col = 0; $col <= $columnCnt; $col++) {
+                $key = $this->cell[$col];
+                if (isset($pictures[$row][$key])) {
+                    $cellValue = $pictures[$row][$key];
+                } else {
+                    $cellId = $key . $row;
+                    $cellValue = $sheet->getCell($cellId)->getCalculatedValue();
+                    if ($cellValue instanceof RichText) {
+                        $cellValue = $cellValue->__toString();
+                    }
+                }
+                if ($head && $key = Dever::issets($head, $col)) {
+                    if (is_array($key)) {
+                        $rowData[$key[0]][$key[1]] = $cellValue;
+                    } else {
+                        $rowData[$key] = $cellValue;
+                    }
+                } else {
+                    $rowData[$key] = $cellValue;
+                }
+            }
+            yield $rowData;
+        }
+    }
+}
+
+/*
 <?php namespace Excel\Lib;
 use Dever;
 Dever::apply('autoload', 'excel', 'vendor');
@@ -52,3 +125,4 @@ class Import extends Core
         return $data;  
     }
 }
+*/