ExcelImporter.php 6.94 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
<?php

/**
 * Created by PhpStorm.
 * User: zero
 * Date: 2020/6/1
 * Time: 14:06
 * Description:
 */

namespace Meibuyu\Micro\Tools;

use Hyperf\Contract\ConfigInterface;
use Meibuyu\Micro\Exceptions\HttpResponseException;
use Meibuyu\Micro\Manager\UploadManager;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class ExcelImporter
{
    /**
     * @var ConfigInterface
     */
    private $config;

    /**
     * @var Spreadsheet|null
     */
    private $reader = null;

    /**
     * @var Worksheet|null
     */
    private $sheet = null;

    private $rootPath;
    private $sheetIndex = 0;
    private $filePath;
    private $fileType;
    private $highestRow = 0; // 总行数
    private $highestColumn = 0; // 最后一列字符
    private $errorColumn;

    /**
     * Importer constructor.
     * @param $file
     * @param int $sheetIndex
     * @throws \Meibuyu\Micro\Exceptions\HttpResponseException
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     */
    public function __construct($file, $sheetIndex = 0)
    {
        $this->config = container(ConfigInterface::class);
王源's avatar
王源 committed
56
        $this->fileType = ucfirst($file->getExtension());
57
        $this->rootPath = $this->config->get('server.settings.document_root', BASE_PATH . '/public');
58
        $path = UploadManager::uploadExcelGetRealPath($file, ['temp' => true]);
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
        $this->reader = IOFactory::createReaderForFile($path)->load($path);
        $this->filePath = $path;
        $this->sheet = $this->reader->getSheet($sheetIndex);
        $this->sheetIndex = $sheetIndex;
        $this->highestRow = $this->sheet->getHighestRow();
        $this->highestColumn = $this->sheet->getHighestColumn();
        $this->highestColumn++;
    }

    /**
     * 判断excel表中数据不能为空
     * @param $least
     * @return bool
     * @throws HttpResponseException
     */
    public function checkEmpty($least)
    {
        if ($this->highestRow < $least) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 获取表格字符串
     * @param string $startCol 开始的列,默认为A
     * @param null $endCol 结束的列,默认为表格已有数据的最后一列
     * @return string
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
    public function getHeaderStr($startCol = 'A', $endCol = null): string
    {
        $str = '';
        $endCol = $endCol ? $endCol : $this->highestColumn;
        for ($i = $startCol; $i != $endCol; $i++) {
            $str .= $this->sheet->getCell($i . 1)->getFormattedValue();
        }
        return $str;
    }

    /**
     * 验证表头
     * @param string $headerStr 对比的表头字符串
     * @param string $startCol 开始的列,默认为A
     * @param null $endCol 结束的列,默认为表格已有数据的最后一列
     * @return bool
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
    public function checkHeaderStr(string $headerStr, $startCol = 'A', $endCol = null)
    {
        $excelField = $this->getHeaderStr($startCol, $endCol);
        if (md5($excelField) == md5($headerStr)) {
            return true;
        } else {
            return false;
        }
    }

    /**
王源's avatar
王源 committed
119
     * 检测必填数据
120 121 122 123
     * @param $requires
     * @param $errorCount
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
124
    public function checkRequire($requires, &$errorCount)
125 126
    {
        foreach ($requires as $k => $v) {
王源's avatar
王源 committed
127 128 129
            if ($v == '0') {
                continue;
            }
130
            if (!$v || $v === '') {
131
                $this->setErrorMessage($k . "不能为空", $errorCount);
132
                return false;
133 134
            }
        }
135
        return true;
136 137 138
    }

    /**
王源's avatar
王源 committed
139
     * 检测数字类型数据
140 141 142 143
     * @param $data
     * @param $errorCount
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
144
    public function checkNumeric($data, &$errorCount)
145 146
    {
        foreach ($data as $k => $v) {
王源's avatar
王源 committed
147
            if (!$v || $v === '' || $v == '0') {
王源's avatar
王源 committed
148 149 150 151 152 153
                continue;
            } else {
                if (!is_numeric($v)) {
                    $this->setErrorMessage("{$k}只能是数字", $errorCount);
                    return false;
                }
154 155
            }
        }
156
        return true;
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    }

    /**
     * 设置错误标识
     * @param $p
     * @param $message
     * @param $count
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
    public function setErrorMessage($message, &$count)
    {
        $count++;
        $this->sheet->getCell($this->errorColumn)->setValue($message);
        $this->sheet->getStyle($this->errorColumn)->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);
    }

    /**
     * 保存
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     */
    public function save()
    {
        $this->reader->setActiveSheetIndex(0);
        IOFactory::createWriter($this->reader, $this->fileType)->save($this->filePath);
    }

    /**
     * 返回当前激化的sheet表
     * @return null|Worksheet
     */
    public function getSheet()
    {
        return $this->sheet;
    }

    /**
     * 返回原生的PhpOffice Reader 手动处理数据
     * @return null|Spreadsheet
     */
    public function getReader()
    {
        return $this->reader;
    }

    /**
     * 获取总行数
     * @return int
     */
    public function getHighestRow()
    {
        return $this->highestRow;
    }

王源's avatar
王源 committed
211 212 213 214 215 216 217 218 219
    /**
     * 获取总列数
     * @return int
     */
    public function getHighestColumn()
    {
        return $this->highestColumn;
    }

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
    /**
     * 返回文件本地地址
     * @return string
     */
    public function getFilePath()
    {
        return $this->filePath;
    }

    /**
     * 返回文件网络地址
     * @return string
     */
    public function getFileUrl()
    {
        return $this->config->get('app_domain') . str_replace($this->rootPath, '', $this->filePath);

    }

    public function setErrorColumn($column)
    {
        $this->errorColumn = $column;
    }

    public function getErrorColumn()
    {
        return $this->errorColumn;
    }

249 250 251 252 253
    /**
     * 对比不同的数据,返回是否有不同
     * @param array $list
     * @param array $data
     * @return bool
王源's avatar
王源 committed
254 255
     * @see check_diff_val()
     * @deprecated 此方法废弃,直接调用check_diff_val()
256 257 258 259 260 261 262 263 264 265
     */
    public static function checkDiffVal(array $list, array $data)
    {
        foreach ($list as $key => $val) {
            if (isset($data[$key]) && $data[$key]) {
                if (is_array($val)) {
                    if (self::checkDiffVal($val, $data[$key])) {
                        return true;
                    }
                } else {
266
                    if ($list[$key] != $data[$key]) {
267 268 269 270 271 272 273 274
                        return true;
                    }
                }
            }
        }
        return false;
    }

275
}