php实现Excel导入导出

流氓凡 技术分享 2020-09-21 8.26 K 0

Excel导入

工具:

PHPExcel.zip

此包解压放在vendor文件夹下面,也可以自己使用composer安装下依赖包。

实现原理:将excel前端通过表单提交->读取excel表头和其他数据内容->循环入库

示例代码:

// 执行数据导入
public function doImport()
{
    set_time_limit(0); // 设置超时时间(无限制)
    $excel = request()->file('file')->getInfo();//excel为file中的name
    vendor("PHPExcel.PHPExcel.IOFactory");
    $objPHPExcel = \PHPExcel_IOFactory::load($excel['tmp_name']);//读取上传的文件
    $arrExcel = $objPHPExcel->getSheet()->toArray();//获取其中的数据
    $key = $arrExcel[0]; // 返回 excel 标题(用作数组的键)
    array_splice($arrExcel, 0, 2); // 单独移除两个表头
    // 整理数据(使其变成关联数组)
    foreach ($arrExcel as &$item) {
        $item = array_combine($key, $item);
        // 此处可以直接进行数据预处理
    }
    var_dump($arrExcel); // 返回处理好的excel数据
}

导出Excel文件

这里导出的是csv文件的格式,直接导出xsl格式的excel文件对于数据量大的来说会有点问题。

导出很简单,实现原理:定义导出表头->循环处理导出的表数据->导出csv文件

示例代码:

/**
 * 数据导出到excel(csv文件)  建议放置在全局公共方法中提供调用
 * @param $fileName
 * @param array $tileArray
 * @param array $dataArray
 */
function export_excel($fileName, $tileArray = [], $dataArray = [])
{
    ini_set('memory_limit', '512M');
    ini_set('max_execution_time', 0);
    ob_end_clean();
    ob_start();
    header("Content-Type: text/csv");
    header("Content-Disposition:filename=" . $fileName);
    $fp = fopen('php://output', 'w');
    fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));// 转码 防止乱码
    fputcsv($fp, $tileArray);
    $index = 0;
    foreach ($dataArray as $item) {
        if ($index == 1000) {
            $index = 0;
            ob_flush();
            flush();
        }
        $index++;
        fputcsv($fp, $item);
    }
    ob_flush();
    flush();
    ob_end_clean();
}

在导出数据处理类中调用此方法,首先定义表头:

private $procureArray = [
    '订单编号', '姓名', '联系电话', '商品品牌', '商品编码', '数量'
];

然后进行循环的数据预处理:

/**
 * 订单导出
 * @param $list
 */
public function orderList($list)
{
    // 表格内容
    $dataArray = [];
    foreach ($list as $order) {
        $address = $order['address'];
        $dataArray[] = [
            '订单号' => $this->filterValue($order['order_no']),
            '商品信息' => $this->filterGoodsInfo($order), // 此处可以进行多条信息放在一个表格字段中
            '下单时间' => $this->filterValue($order['create_time']),
            '收货人姓名' => $this->filterValue($order['address']['name']),
            '联系电话' => $this->filterValue($order['address']['phone']),
            '收货人地址' => $this->filterValue($address ? $address->getFullAddress() : ''),
        ];
    }
    // 导出csv文件
    $filename = 'order-' . date('YmdHis');
    return export_excel($filename . '.csv', $this->tileArray, $dataArray); // 执行数据导出
}

/**
 * 表格值过滤
 * @param $value
 * @return string
 */
private function filterValue($value)
{
    return "\t" . $value . "\t";
}

/**
 * 格式化商品信息
 * @param $order
 * @return string
 */
private function filterGoodsInfo($order)
{
    $content = '';
    foreach ($order['goods'] as $key => $goods) {
        $content .= ($key + 1) . ".商品:{$goods_name}\n";
        $content .= " 商品编码:{$goods['goods_number']}\n";
        $content .= " 购买数量:{$goods['total_num']}\n";
        $content .= " 商品总价:{$goods['total_price']}元\n\n";
    }
    return $content;
}

温馨提示

1. 如果导入数据过大,比如说超过了4000行那么可能就需要进行数组分段导入处理,或者excel进行分表处理,否则php长时间无法响应处理或者nginx等服务器过了超时时间,

那么将直接返回503等错误信息。

2. 如果导入的excel表头是中文,想导入的数据是一个英文键值的关联数组,那么需要在excel表中第二行插入英文字段名,然后将以下代码进行调整:

$key = $arrExcel[1]; // 返回 excel 标题(用作数组的键)

3. 数据导入无论是否涉及到多个表均需要进行事务处理,否则你可能有想想不到的麻烦。

评论