关于PHP导出Excel的优化详解

针对PHP导出Excel的优化,在我之前的一篇文章里已经做过介绍:关于PHP内存溢出的思考,本文主要是介绍一款高性能的导出组件–xlswriter,他是一个PHP C扩展,官方文档地址,请点击

安装

安装pecl

当我们发现pecl未安装时,则需要安装pecl。一般情况下,是安装在PHP的安装目录,示例命令如下:

  1. # 进入PHP安装目录
  2. cd /usr/local/php/bin
  3. curl -o go-pear.php http://pear.php.net/go-pear.phar
  4. php go-pear.php
  5. # 安装完成后,软连接到bin目录下
  6. ln -s /usr/local/php/bin/pecl /usr/bin/pecl

安装xlswriter

pecl install xlswriter

# 添加 extension = xlswriter.so 到 ini 配置

使用

具体使用可以参考官方文档,会介绍的更加详细,我这就上一段我使用中的代码:

封装的导出service

  1. /**
  2. * 下载
  3. * @param $header
  4. * @param $data
  5. * @param $fileName
  6. * @param $type
  7. * @return bool
  8. * @throws
  9. */
  10. public function download($header, $data, $fileName)
  11. {
  12. $config = [
  13. 'path' => $this->getTmpDir() . '/',
  14. ];
  15. $now = date('YmdHis');
  16. $fileName = $fileName . $now . '.xlsx';
  17. $xlsxObject = new \Vtiful\Kernel\Excel($config);
  18. // Init File
  19. $fileObject = $xlsxObject->fileName($fileName);
  20. // 设置样式
  21. $fileHandle = $fileObject->getHandle();
  22. $format = new \Vtiful\Kernel\Format($fileHandle);
  23. $style = $format->bold()->background(
  24. \Vtiful\Kernel\Format::COLOR_YELLOW
  25. )->align(Format::FORMAT_ALIGN_VERTICAL_CENTER)->toResource();
  26. // Writing data to a file ......
  27. $fileObject->header($header)
  28. ->data($data)
  29. ->freezePanes(1, 0)
  30. ->setRow('A1', 20, $style);
  31. // Outptu
  32. $filePath = $fileObject->output();
  33. // 下载
  34. header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  35. header('Content-Disposition: attachment;filename="' . $fileName . '"');
  36. header('Cache-Control: max-age=0');
  37. header('Content-Length: ' . filesize($filePath));
  38. header('Content-Transfer-Encoding: binary');
  39. header('Cache-Control: must-revalidate');
  40. header('Pragma: public');
  41. ob_clean();
  42. flush();
  43. if (copy($filePath, 'php://output') === false) {
  44. throw new RuntimeException('导出失败');
  45. }
  46. // Delete temporary file
  47. @unlink($filePath);
  48. return true;
  49. }
  50. /**
  51. * 获取临时文件夹
  52. * @return false|string
  53. */
  54. private function getTmpDir()
  55. {
  56. // 目录可以自定义
  57. // return \Yii::$app->params['downloadPath'];
  58. $tmp = ini_get('upload_tmp_dir');
  59. if ($tmp !== False && file_exists($tmp)) {
  60. return realpath($tmp);
  61. }
  62. return realpath(sys_get_temp_dir());
  63. }
  64. /**
  65. * 读取文件
  66. * @param $path
  67. * @param $fileName
  68. * @return array
  69. */
  70. public function readFile($path,$fileName)
  71. {
  72. // 读取测试文件
  73. $config = ['path' => $path];
  74. $excel = new \Vtiful\Kernel\Excel($config);
  75. $data = $excel->openFile($fileName)
  76. ->openSheet()
  77. ->getSheetData();
  78. return $data;
  79. }

调用处代码

导出

  1. /**
  2. * 导出
  3. */
  4. public function actionExport()
  5. {
  6. try {
  7. /**
  8. * @var $searchModel SkuBarCodeSearch
  9. */
  10. $searchModel = Yii::createObject(SkuBarCodeSearch::className());
  11. $queryParams['SkuBarCodeSearch'] = [];
  12. $result = $searchModel->search($queryParams, true);
  13. $formatData = [];
  14. if (!emptyempty($result)) {
  15. foreach ($result as $key => &$value) {
  16. $tmpData = [
  17. 'sku_code' => $value['sku_code'],
  18. 'bar_code' => $value['bar_code'],
  19. 'created_at' => $value['created_at'],
  20. 'updated_at' => $value['updated_at'],
  21. ];
  22. $formatData[] = array_values($tmpData);
  23. }
  24. unset($value);
  25. }
  26. $fields = [
  27. 'sku_code' => 'SKU编码',
  28. 'bar_code' => '条形码',
  29. 'created_at' => '创建时间',
  30. 'updated_at' => '更新时间',
  31. ];
  32. /**
  33. * @var $utilService UtilService
  34. */
  35. $utilService = UtilService::getInstance();
  36. $utilService->download(array_values($fields), $formatData, 'sku_single_code');
  37. } catch (\Exception $e) {
  38. Yii::$app->getSession()->setFlash('error', '导出失败');
  39. }
  40. }

导入

  1. public function actionImportTmpSku()
  2. {
  3. try {
  4. /**
  5. * @var $utilService UtilService
  6. */
  7. $utilService = UtilService::getInstance();
  8. $path = '/tmp/'; // 文件目录
  9. $fileName = 'sku_0320.xlsx';
  10. $excelData = $utilService->readFile($path, $fileName);
  11. unset($excelData[0]);
  12. $excelData = array_merge($excelData);
  13. // ... ... 业务代码
  14. } catch (\Exception $e) {
  15. echo $e->getMessage();
  16. exit;
  17. }
  18. }

结论

整体使用下来,在处理大数据量时,性能相比于原来的PHPExcel确实高了很多。

本文系转载,原文地址是:

https://tsmliyun.github.io/php/PHP%E5%AF%BC%E5%87%BAExcel%E7%9A%84%E4%BC%98%E5%8C%96/