SpreadSheet::setRelativePath()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
/**
3
 * @name: SpreadSheet
4
 * @author: JiaMeng <[email protected]>
5
 * @file: Export.php
6
 * @Date: 2024/03/04 10:15
7
 */
8
namespace tinymeng\spreadsheet\Excel;
9
10
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
11
use PhpOffice\PhpSpreadsheet\Exception;
12
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
13
use tinymeng\tools\FileTool;
14
15
trait SpreadSheet{
16
17
    /**
18
     * sheet名称
19
     * @var
20
     */
21
    private $sheetName;
22
    /**
23
     * 定义所有字段
24
     * @var array
25
     */
26
    private $field = [];
27
28
    /**
29
     * 文件信息
30
     * @var array
31
     */
32
    private $fileTitle=[];
33
34
    /**
35
     * 标题占用行数
36
     * @var int
37
     */
38
    private $title_row = 1;
39
40
    /**
41
     * 左侧分组字段
42
     * @var array
43
     */
44
    private $group_left = [];
45
46
47
    /**
48
     * 表头所在行
49
     * @var int
50
     */
51
    public $titleFieldsRow = 1;
52
53
    /**
54
     * 获取表格列数
55
     * @var
56
     */
57
    public $columnCount;
58
59
    /**
60
     * 获取表格行数
61
     * @var
62
     */
63
    public $rowCount;
64
    /**
65
     * title
66
     * @var
67
     */
68
    public $title;
69
    /**
70
     * title字段
71
     * @var
72
     */
73
    public $title_fields;
74
    /**
75
     * @var string[]
76
     */
77
    private $cellName = [];
78
79
    /**
80
     * 文件中图片读取
81
     * 图片存储的相对路径
82
     * @var string
83
     */
84
    public $relative_path = '/images';
85
86
    /**
87
     * 文件中图片读取
88
     * 图片存储的绝对路径
89
     * @var string
90
     */
91
    public $image_path = '/images';
92
93
    public function setTitle($title){
94
        $this->title = $title;
95
        $this->getTitleFields();
96
        return $this;
97
    }
98
99
    /**
100
     * @param $value
101
     * @return $this
102
     */
103
    public function setRelativePath($value){
104
        $this->relative_path = $value;
105
        return $this;
106
    }
107
108
    /**
109
     * @param $value
110
     * @return $this
111
     */
112
    public function setImagePath($value){
113
        $this->image_path = $value;
114
        return $this;
115
    }
116
117
    /**
118
     * getExcelData
119
     * @return array
120
     * @throws Exception
121
     * @author: Tinymeng <[email protected]>
122
     * @time: 2022/2/22 11:30
123
     */
124
    public function getExcelData(){
125
        /* 循环读取每个单元格的数据 */
126
        $result = [];
127
        $dataRow = $this->titleFieldsRow+1;
128
129
        //行数循环
130
        for ($row = $dataRow; $row <= $this->rowCount; $row++){
131
            $rowFlog = false;//行是否有内容(过滤空行)
132
            //列数循环 , 列数是以A列开始
133
            $data = [];
134
            foreach ($this->cellName as $column){
135
                $cell = $this->workSheet->getCell($column.$row);
136
                $value = trim($cell->getFormattedValue());
137
                if(isset($this->title_fields[$column])){
138
                    $data[$this->title_fields[$column]] = $value;
139
                    if(!empty($value)) $rowFlog = true;//有内容
140
                }
141
            }
142
            if($rowFlog) $result[] = $data;
143
        }
144
145
        /*
146
         * 读取表格图片数据
147
         * (如果为空右击图片转为浮动图片)
148
         */
149
        $imageFilename_prefix = time().rand(100,999).$this->sheet;
0 ignored issues
show
Bug introduced by
The property sheet does not exist on tinymeng\spreadsheet\Excel\SpreadSheet. Did you mean sheetName?
Loading history...
150
        foreach ($this->workSheet->getDrawingCollection() as $drawing) {
151
            /**@var $drawing Drawing* */
152
            list($column, $row) = Coordinate::coordinateFromString($drawing->getCoordinates());
153
            $imageFilename = "/{$imageFilename_prefix}-" . $drawing->getCoordinates();
154
            $image_suffix = $this->saveImage($drawing, $imageFilename);
155
            $image_name = ltrim($this->relative_path, '/') . "{$imageFilename}.{$image_suffix}";
156
            if(isset($this->title_fields[$column])) {
157
                $result[$row-($this->titleFieldsRow+1)][$this->title_fields[$column]] = $image_name;
158
            }
159
        }
160
        return $result;
161
    }
162
163
    /**
164
     * getTitle
165
     * @return mixed
166
     * @author: Tinymeng <[email protected]>
167
     * @time: 2022/2/22 11:30
168
     */
169
    public function getTitle(){
170
        return $this->title;
171
    }
172
173
    /**
174
     * getTitleFields
175
     * @return SpreadSheet
176
     * @author: Tinymeng <[email protected]>
177
     * @time: 2022/2/22 11:30
178
     */
179
    public function getTitleFields(){
180
        $title = $this->getTitle();
181
182
        $row = $this->titleFieldsRow;
183
        $titleDataArr = [];
184
185
        foreach ($this->cellName as $column){
186
            $value = trim($this->workSheet->getCell($column.$row)->getValue());
187
            // 规范化表头:移除前导星号(半角/全角)与多余空白
188
            $norm = $this->normalizeHeaderName($value);
189
            if(!empty($norm)){
190
                $titleDataArr[$norm] = $column;
191
            }
192
        }
193
        $title_fields = [];
194
        foreach ($title as $key=>$value) {
195
            $normKey = $this->normalizeHeaderName($key);
196
            if(isset($titleDataArr[$normKey])){
197
                $title_fields[$titleDataArr[$normKey]] = $value;
198
            }
199
        }
200
        $this->title_fields = $title_fields;
201
        return $this;
202
    }
203
204
    /**
205
     * 规范化表头显示名称:
206
     * - 去掉前导的 * 或 *,以及其后的空格
207
     * - 去掉首尾空白
208
     * @param $name
209
     * @return mixed|string
210
     */
211
    private function normalizeHeaderName($name){
212
        $name = is_string($name) ? trim($name) : $name;
213
        if(!is_string($name)) return $name;
214
        // 移除一个或多个半角/全角星号以及紧随的空格
215
        $name = preg_replace('/^[\x{002A}\x{FF0A}]+\s*/u', '', $name);
216
        // 再次trim以防有残余空白
217
        return trim($name);
218
    }
219
220
    /**
221
     * 保存图片到文件相对路径
222
     * @param Drawing $drawing
223
     * @param $imageFilename
224
     * @return string
225
     * @throws Exception
226
     */
227
    protected function saveImage(Drawing $drawing, $imageFilename)
228
    {
229
        FileTool::mkdir($this->image_path);
230
231
        // 获取文件的真实MIME类型
232
        $fInfo = new \finfo(FILEINFO_MIME_TYPE);
233
        $mimeType = $fInfo->file($drawing->getPath());
234
235
        // 根据MIME类型确定真实的图片格式
236
        switch ($mimeType) {
237
            case 'image/jpg':
238
            case 'image/jpeg':
239
                $realExtension = 'jpg';
240
                $imageFilename .= '.'.$realExtension;
241
                $source = imagecreatefromjpeg($drawing->getPath());
242
                imagejpeg($source, $this->image_path . $imageFilename);
243
                break;
244
            case 'image/gif':
245
                $realExtension = 'gif';
246
                $imageFilename .= '.'.$realExtension;
247
                $source = imagecreatefromgif($drawing->getPath());
248
                imagegif($source, $this->image_path . $imageFilename);
249
                break;
250
            case 'image/png':
251
                $realExtension = 'png';
252
                $imageFilename .= '.'.$realExtension;
253
                $source = imagecreatefrompng($drawing->getPath());
254
                // 保持透明度设置
255
                imagealphablending($source, false);
256
                imagesavealpha($source, true);
257
                imagepng($source, $this->image_path . $imageFilename);
258
                break;
259
            default:
260
                throw new Exception('image format error!');
261
        }
262
263
        return $realExtension;
264
    }
265
}
266