前言:
在业务中开发中,表格的导入导出功能很常见。但是这里主要是使用phpoffice类库介绍实现导入表格数据的功能。
冲突:
大部分的导入功能,就是通过点击按钮上传一张表格,然后后台读取表格数据根据业务整理后直接插入到数据库,最后再返回给前端。但是如果表格数据庞大,业务逻辑复杂的时候,就会导致导入那一块很臃肿不好维护。
解决方法:
处理方式是把导入与业务数据插入分离,所以在二者之间添加一个队列就可以了。导入只负责将表格数据存入队列。业务部分可以是单独的系统,最后就是消费队列中的数据了。这样一来,不但提升了导入速度,而且还让导入与系统解耦,不会因为异常而影响到其他业务。
编码:
1.下载phpoffice。
composer repuire phpoffice/phpspreadsheet
2.导入导出代码。
<?php
namespace app\common\helper;
use phpoffice\phpspreadsheet\spreadsheet;
use phpoffice\phpspreadsheet\writer\xlsx;
use phpoffice\phpspreadsheet\iofactory;
use phpoffice\phpspreadsheet\cell\coordinate;
use think\exception;
class excel
{
// 导出
public function output($data, $columns, $table = '导出文件')
{
$spreadsheet = new spreadsheet();
$sheet = $spreadsheet->getactivesheet();
// 设置第一栏的标题
foreach ($columns as $k => $v) {
$sheet->setcellvalue($k . "1", $v['title']);
}
//第二行起 设置内容
$baserow = 2; //数据从n-1行开始往下输出 这里是避免头信息被覆盖
foreach ($data as $key => $value) {
foreach ($columns as $k1 => $v1) {
$i = $key + $baserow;
$sheet->setcellvalue($k1 . $i, $value[$v1['field']]);
}
}
$writer = new xlsx($spreadsheet);
$filename = $table . date("y-m-d", time()) . '_' . time() . '.xlsx';
$writer->save('./excel/' . $filename);
return '/excel/' . $filename;
}
// 导入
public function importexcel($file = '', $sheet = 0, $columncnt = 0, &$options = [])
{
try {
$file = iconv("utf-8", "gb2312", $file);
if (empty($file) or !file_exists($file)) {
throw new \exception('文件不存在!');
}
$objread = iofactory::createreader('xlsx');
if (!$objread->canread($file)) {
$objread = iofactory::createreader('xls');
if (!$objread->canread($file)) {
throw new \exception('只支持导入excel文件!');
}
}
/* 如果不需要获取特殊操作,则只读内容,可以大幅度提升读取excel效率 */
empty($options) && $objread->setreaddataonly(true);
/* 建立excel对象 */
$obj = $objread->load($file);
/* 获取指定的sheet表 */
$currsheet = $obj->getsheet($sheet);
//$currsheet = $obj->getsheetbyname($sheet); // 根据名字
if (isset($options['mergecells'])) {
/* 读取合并行列 */
$options['mergecells'] = $currsheet->getmergecells();
}
if (0 == $columncnt) {
/* 取得最大的列号 */
$columnh = $currsheet->gethighestcolumn();
/* 兼容原逻辑,循环时使用的是小于等于 */
$columncnt = coordinate::columnindexfromstring($columnh);
}
/* 获取总行数 */
$rowcnt = $currsheet->gethighestrow();
$data = [];
/* 读取内容 */
for ($_row = 1; $_row <= $rowcnt; $_row++) {
$isnull = true;
for ($_column = 1; $_column <= $columncnt; $_column++) {
$cellname = coordinate::stringfromcolumnindex($_column);
$cellid = $cellname . $_row;
$cell = $currsheet->getcell($cellid);
if (isset($options['format'])) {
/* 获取格式 */
$format = $cell->getstyle()->getnumberformat()->getformatcode();
/* 记录格式 */
$options['format'][$_row][$cellname] = $format;
}
if (isset($options['formula'])) {
/* 获取公式,公式均为=号开头数据 */
$formula = $currsheet->getcell($cellid)->getvalue();
if (0 === strpos($formula, '=')) {
$options['formula'][$cellname . $_row] = $formula;
}
}
if (isset($format) && 'm/d/yyyy' == $format) {
/* 日期格式翻转处理 */
$cell->getstyle()->getnumberformat()->setformatcode('yyyy/mm/dd');
}
$data[$_row][$cellname] = trim($currsheet->getcell($cellid)->getformattedvalue());
if (!empty($data[$_row][$cellname])) {
$isnull = false;
}
}
if ($isnull) {
unset($data[$_row]);
}
}
return $data;
} catch (\exception $e) {
throw $e;
}
}
}3.抽取指定的字段格式化excel数据。
return [
// 导入的表格标题
"bidding" => [
"stock_no" => "编号",
"price" => "价格",
"mobile" => "手机",
"nickname" => "姓名"
]
];
// 格式化指定列数据(默认第一行表头)
public static function formattingcells(array $data, array $cellconfig)
{
$res = array_values($data);
// 表头
$header = $res[0];
$cellkeys = [];
foreach ($header as $key => $value) {
foreach ($cellconfig as $k => $v) {
if ($value == $v) {
$cellkeys[$key] = $k;
}
}
}
if (count($cellkeys) != count($cellconfig)) {
throw new exception('表格不完整');
}
// 需要添加过滤
$temp = [];
for ($i = 1; $i <= count($res) - 1; $i++) {
foreach ($cellkeys as $m => $n) {
$temp[$i][$n] = $res[$i][$m];
}
}
return array_values($temp);
}4.导入部分,上传接口。
// 导入表格,上传接口
public function importexcel()
{
$upload_file = $_files['files']['tmp_name'];
$input = $this->input;
// id
$id = isset($input['id']) ? $input['id'] : 0;
// 默认取第一工作表
$exceldata = (new excel())->importexcel($upload_file, 0);
// 取excel字段
$config = config('excel_export.bidding');
$price_offer = excel::formattingcells($exceldata, $config);
// 判断每条记录的手机和价格格式
// ……
$jsonlist = json_encode(compact('id', 'price_offer'));
//$jsonlist = json_encode($price_offer);
// 入mq
$host = config("mq.host");
$options = config("mq.price_offer_import");
try {
$mq = new productmq($host, $options);
$mq->publish($jsonlist);
$mq->close();
} catch (\exception $e) {
return $this->jsondata(200, $e->getmessage());
}
// 入mq
return $this->jsondata(200, '导入成功');
}5.消费业务逻辑。

以上就是详解如何实现phpoffice的excel导入功能解耦的详细内容,更多关于phpoffice excel导入解耦的资料请关注代码网其它相关文章!
发表评论