PHP如何使用xlswriter進行大數據的導入匯出? (詳解)
PHP如何使用xlswriter進行大數據的導入匯出?以下這篇文章跟大家介紹PHP大數據xlswriter導入導出(最優資料化)的方法,希望對大家有幫助!
本文介紹基於PHP擴充xlswriter的Vtiful\Kernel\Excel類別可以支援無限層級的複雜表頭導出!後續也可能會持續更新最佳化
一、準備xlswriter擴充功能
##1、windows系統:
到PECL網站下載符合自己本地PHP環境的ddl檔案下載位址:https://pecl.php.net/package/xlswriter,並複製到PHP的擴展目錄ext資料夾下,修改php.ini文件, 加上這行extension=xlswriter
2、Linux系統:
使用指令安裝pecl install xlswriter
extension = xlswriter.so
二、封裝匯出類別檔案(重點來了)<?php
namespace App\Services;
use Vtiful\Kernel\Excel;
class MultiFloorXlsWriterService
{
// 默认宽度
private $defaultWidth = 16;
// 默认导出格式
private $exportType = '.xlsx';
// 表头最大层级
private $maxHeight = 1;
// 文件名
private $fileName = null;
private $xlsObj;
private $fileObject;
private $format;
/**
* MultiFloorXlsWriterService constructor.
* @throws \App\Exceptions\ApiException
*/
public function __construct()
{
// 文件默认输出地址
$path = base_path().'/public/uploads/excel';
$config = [
'path' => $path
];
$this->xlsObj = (new \Vtiful\Kernel\Excel($config));
}
/**
* 设置文件名
* @param string $fileName
* @param string $sheetName
* @author LWW
*/
public function setFileName(string $fileName = '', string $sheetName = 'Sheet1')
{
$fileName = empty($fileName) ? (string)time() : $fileName;
$fileName .= $this->exportType;
$this->fileName = $fileName;
$this->fileObject = $this->xlsObj->fileName($fileName, $sheetName);
$this->format = (new \Vtiful\Kernel\Format($this->fileObject->getHandle()));
}
/**
* 设置表头
* @param array $header
* @param bool $filter
* @throws \Exception
* @author LWW
*/
public function setHeader(array $header, bool $filter = false)
{
if (empty($header)) {
throw new \Exception('表头数据不能为空');
}
if (is_null($this->fileName)) {
self::setFileName(time());
}
// 获取单元格合并需要的信息
$colManage = self::setHeaderNeedManage($header);
// 完善单元格合并信息
$colManage = self::completeColMerge($colManage);
// 合并单元格
self::queryMergeColumn($colManage, $filter);
}
/**
* 填充文件数据
* @param array $data
* @author LWW
*/
public function setData(array $data)
{
foreach ($data as $row => $datum) {
foreach ($datum as $column => $value) {
$this->fileObject->insertText($row + $this->maxHeight, $column, $value);
}
}
}
/**
* 添加Sheet
* @param string $sheetName
* @author LWW
*/
public function addSheet(string $sheetName)
{
$this->fileObject->addSheet($sheetName);
}
/**
* 保存文件至服务器
* @return mixed
* @author LWW
*/
public function output()
{
return $this->fileObject->output();
}
/**
* 输出到浏览器
* @param string $filePath
* @throws \Exception
* @author LWW
*/
public function excelDownload(string $filePath)
{
$fileName = $this->fileName;
$userBrowser = $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/MSIE/i', $userBrowser)) {
$fileName = urlencode($fileName);
} else {
$fileName = iconv('UTF-8', 'GBK//IGNORE', $fileName);
}
header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header('Content-Disposition: attachment;filename="' . $fileName . '"');
header('Content-Length: ' . filesize($filePath));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Cache-Control: max-age=0');
header('Pragma: public');
if (ob_get_contents()) {
ob_clean();
}
flush();
if (copy($filePath, 'php://output') === false) {
throw new \Exception($filePath . '地址出问题了');
}
// 删除本地文件
@unlink($filePath);
exit();
}
/**
* 组装单元格合并需要的信息
* @param array $header
* @param int $col
* @param int $cursor
* @param array $colManage
* @param null $parent
* @param array $parentList
* @return array
* @throws \Exception
* @author LWW
*/
private function setHeaderNeedManage(array $header,int $col = 1,int &$cursor = 0,array &$colManage = [], $parent = null,array $parentList = [])
{
foreach ($header as $head) {
if (empty($head['title'])) {
throw new \Exception('表头数据格式有误');
}
if (is_null($parent)) {
// 循环初始化
$parentList = [];
$col = 1;
} else {
// 递归进入,高度和父级集合通过相同父级条件从已有数组中获取,避免递归增加与实际数据不符
foreach ($colManage as $value) {
if ($value['parent'] == $parent) {
$parentList = $value['parentList'];
$col = $value['height'];
break;
}
}
}
// 单元格标识
$column = $this->getColumn($cursor) . $col;
// 组装单元格需要的各种信息
$colManage[$column] = [
'title' => $head['title'], // 标题
'cursor' => $cursor, // 游标
'cursorEnd' => $cursor, // 结束游标
'height' => $col, // 高度
'width' => $this->defaultWidth, // 宽度
'mergeStart' => $column, // 合并开始标识
'hMergeEnd' => $column, // 横向合并结束标识
'zMergeEnd' => $column, // 纵向合并结束标识
'parent' => $parent, // 父级标识
'parentList' => $parentList, // 父级集合
];
if (isset($head['children']) && !empty($head['children']) && is_array($head['children'])) {
// 有下级,高度加一
$col += 1;
// 当前标识加入父级集合
$parentList[] = $column;
$this->setHeaderNeedManage($head['children'], $col, $cursor, $colManage, $column, $parentList);
} else {
// 没有下级,游标加一
$cursor += 1;
}
}
return $colManage;
}
/**
* 完善单元格合并信息
* @param array $colManage
* @return mixed
* @author LWW
*/
private function completeColMerge(array $colManage)
{
$this->maxHeight = max(array_column($colManage, 'height'));
$parentManage = array_column($colManage, 'parent');
foreach ($colManage as $index => $value) {
// 设置横向合并结束范围:存在父级集合,把所有父级的横向合并结束范围设置为当前单元格
if (!is_null($value['parent']) && !empty($value['parentList'])) {
foreach ($value['parentList'] as $parent) {
$colManage[$parent]['hMergeEnd'] = self::getColumn($value['cursor']) . $colManage[$parent]['height'];
$colManage[$parent]['cursorEnd'] = $value['cursor'];
}
}
// 设置纵向合并结束范围:当前高度小于最大高度 且 不存在以当前单元格标识作为父级的项
$checkChildren = array_search($index, $parentManage);
if ($value['height'] < $this->maxHeight && !$checkChildren) {
$colManage[$index]['zMergeEnd'] = self::getColumn($value['cursor']) . $this->maxHeight;
}
}
return $colManage;
}
/**
* 合并单元格
* @param array $colManage
* @param bool $filter
* @author LWW
*/
private function queryMergeColumn(array $colManage,bool $filter)
{
foreach ($colManage as $value) {
$this->fileObject->mergeCells("{$value['mergeStart']}:{$value['zMergeEnd']}", $value['title']);
$this->fileObject->mergeCells("{$value['mergeStart']}:{$value['hMergeEnd']}", $value['title']);
// 设置单元格需要的宽度
if ($value['cursor'] != $value['cursorEnd']) {
$value['width'] = ($value['cursorEnd'] - $value['cursor'] + 1) * $this->defaultWidth;
}
// 设置列单元格样式
$toColumnStart = self::getColumn($value['cursor']);
$toColumnEnd = self::getColumn($value['cursorEnd']);
$this->fileObject->setColumn("{$toColumnStart}:{$toColumnEnd}", $value['width']);
}
// 是否开启过滤选项
if ($filter) {
// 获取最后的单元格标识
$filterEndColumn = self::getColumn(end($colManage)['cursorEnd']) . $this->maxHeight;
$this->fileObject->autoFilter("A1:{$filterEndColumn}");
}
}
/**
* 获取单元格列标识
* @param int $num
* @return string
* @author LWW
*/
private function getColumn(int $num)
{
return Excel::stringFromColumnIndex($num);
}
}
登入後複製
<?php namespace App\Services; use Vtiful\Kernel\Excel; class MultiFloorXlsWriterService { // 默认宽度 private $defaultWidth = 16; // 默认导出格式 private $exportType = '.xlsx'; // 表头最大层级 private $maxHeight = 1; // 文件名 private $fileName = null; private $xlsObj; private $fileObject; private $format; /** * MultiFloorXlsWriterService constructor. * @throws \App\Exceptions\ApiException */ public function __construct() { // 文件默认输出地址 $path = base_path().'/public/uploads/excel'; $config = [ 'path' => $path ]; $this->xlsObj = (new \Vtiful\Kernel\Excel($config)); } /** * 设置文件名 * @param string $fileName * @param string $sheetName * @author LWW */ public function setFileName(string $fileName = '', string $sheetName = 'Sheet1') { $fileName = empty($fileName) ? (string)time() : $fileName; $fileName .= $this->exportType; $this->fileName = $fileName; $this->fileObject = $this->xlsObj->fileName($fileName, $sheetName); $this->format = (new \Vtiful\Kernel\Format($this->fileObject->getHandle())); } /** * 设置表头 * @param array $header * @param bool $filter * @throws \Exception * @author LWW */ public function setHeader(array $header, bool $filter = false) { if (empty($header)) { throw new \Exception('表头数据不能为空'); } if (is_null($this->fileName)) { self::setFileName(time()); } // 获取单元格合并需要的信息 $colManage = self::setHeaderNeedManage($header); // 完善单元格合并信息 $colManage = self::completeColMerge($colManage); // 合并单元格 self::queryMergeColumn($colManage, $filter); } /** * 填充文件数据 * @param array $data * @author LWW */ public function setData(array $data) { foreach ($data as $row => $datum) { foreach ($datum as $column => $value) { $this->fileObject->insertText($row + $this->maxHeight, $column, $value); } } } /** * 添加Sheet * @param string $sheetName * @author LWW */ public function addSheet(string $sheetName) { $this->fileObject->addSheet($sheetName); } /** * 保存文件至服务器 * @return mixed * @author LWW */ public function output() { return $this->fileObject->output(); } /** * 输出到浏览器 * @param string $filePath * @throws \Exception * @author LWW */ public function excelDownload(string $filePath) { $fileName = $this->fileName; $userBrowser = $_SERVER['HTTP_USER_AGENT']; if (preg_match('/MSIE/i', $userBrowser)) { $fileName = urlencode($fileName); } else { $fileName = iconv('UTF-8', 'GBK//IGNORE', $fileName); } header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); header('Content-Disposition: attachment;filename="' . $fileName . '"'); header('Content-Length: ' . filesize($filePath)); header('Content-Transfer-Encoding: binary'); header('Cache-Control: must-revalidate'); header('Cache-Control: max-age=0'); header('Pragma: public'); if (ob_get_contents()) { ob_clean(); } flush(); if (copy($filePath, 'php://output') === false) { throw new \Exception($filePath . '地址出问题了'); } // 删除本地文件 @unlink($filePath); exit(); } /** * 组装单元格合并需要的信息 * @param array $header * @param int $col * @param int $cursor * @param array $colManage * @param null $parent * @param array $parentList * @return array * @throws \Exception * @author LWW */ private function setHeaderNeedManage(array $header,int $col = 1,int &$cursor = 0,array &$colManage = [], $parent = null,array $parentList = []) { foreach ($header as $head) { if (empty($head['title'])) { throw new \Exception('表头数据格式有误'); } if (is_null($parent)) { // 循环初始化 $parentList = []; $col = 1; } else { // 递归进入,高度和父级集合通过相同父级条件从已有数组中获取,避免递归增加与实际数据不符 foreach ($colManage as $value) { if ($value['parent'] == $parent) { $parentList = $value['parentList']; $col = $value['height']; break; } } } // 单元格标识 $column = $this->getColumn($cursor) . $col; // 组装单元格需要的各种信息 $colManage[$column] = [ 'title' => $head['title'], // 标题 'cursor' => $cursor, // 游标 'cursorEnd' => $cursor, // 结束游标 'height' => $col, // 高度 'width' => $this->defaultWidth, // 宽度 'mergeStart' => $column, // 合并开始标识 'hMergeEnd' => $column, // 横向合并结束标识 'zMergeEnd' => $column, // 纵向合并结束标识 'parent' => $parent, // 父级标识 'parentList' => $parentList, // 父级集合 ]; if (isset($head['children']) && !empty($head['children']) && is_array($head['children'])) { // 有下级,高度加一 $col += 1; // 当前标识加入父级集合 $parentList[] = $column; $this->setHeaderNeedManage($head['children'], $col, $cursor, $colManage, $column, $parentList); } else { // 没有下级,游标加一 $cursor += 1; } } return $colManage; } /** * 完善单元格合并信息 * @param array $colManage * @return mixed * @author LWW */ private function completeColMerge(array $colManage) { $this->maxHeight = max(array_column($colManage, 'height')); $parentManage = array_column($colManage, 'parent'); foreach ($colManage as $index => $value) { // 设置横向合并结束范围:存在父级集合,把所有父级的横向合并结束范围设置为当前单元格 if (!is_null($value['parent']) && !empty($value['parentList'])) { foreach ($value['parentList'] as $parent) { $colManage[$parent]['hMergeEnd'] = self::getColumn($value['cursor']) . $colManage[$parent]['height']; $colManage[$parent]['cursorEnd'] = $value['cursor']; } } // 设置纵向合并结束范围:当前高度小于最大高度 且 不存在以当前单元格标识作为父级的项 $checkChildren = array_search($index, $parentManage); if ($value['height'] < $this->maxHeight && !$checkChildren) { $colManage[$index]['zMergeEnd'] = self::getColumn($value['cursor']) . $this->maxHeight; } } return $colManage; } /** * 合并单元格 * @param array $colManage * @param bool $filter * @author LWW */ private function queryMergeColumn(array $colManage,bool $filter) { foreach ($colManage as $value) { $this->fileObject->mergeCells("{$value['mergeStart']}:{$value['zMergeEnd']}", $value['title']); $this->fileObject->mergeCells("{$value['mergeStart']}:{$value['hMergeEnd']}", $value['title']); // 设置单元格需要的宽度 if ($value['cursor'] != $value['cursorEnd']) { $value['width'] = ($value['cursorEnd'] - $value['cursor'] + 1) * $this->defaultWidth; } // 设置列单元格样式 $toColumnStart = self::getColumn($value['cursor']); $toColumnEnd = self::getColumn($value['cursorEnd']); $this->fileObject->setColumn("{$toColumnStart}:{$toColumnEnd}", $value['width']); } // 是否开启过滤选项 if ($filter) { // 获取最后的单元格标识 $filterEndColumn = self::getColumn(end($colManage)['cursorEnd']) . $this->maxHeight; $this->fileObject->autoFilter("A1:{$filterEndColumn}"); } } /** * 获取单元格列标识 * @param int $num * @return string * @author LWW */ private function getColumn(int $num) { return Excel::stringFromColumnIndex($num); } }
#三、使用範例
程式碼如下/** * 导出测试 * @author LWW */ public function export() { $header = [ [ 'title' => '一级表头1', 'children' => [ [ 'title' => '二级表头1', ], [ 'title' => '二级表头2', ], [ 'title' => '二级表头3', ], ] ], [ 'title' => '一级表头2' ], [ 'title' => '一级表头3', 'children' => [ [ 'title' => '二级表头1', 'children' => [ [ 'title' => '三级表头1', ], [ 'title' => '三级表头2', ], ] ], [ 'title' => '二级表头2', ], [ 'title' => '二级表头3', 'children' => [ [ 'title' => '三级表头1', 'children' => [ [ 'title' => '四级表头1', 'children' => [ [ 'title' => '五级表头1' ], [ 'title' => '五级表头2' ] ] ], [ 'title' => '四级表头2' ] ] ], [ 'title' => '三级表头2', ], ] ] ] ], [ 'title' => '一级表头4', ], [ 'title' => '一级表头5', ], ]; $data= []; // header头规则 title表示列标题,children表示子列,没有子列children可不写或为空 for ($i = 0; $i < 100; $i++) { $data[] = [ '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', '这是第'. $i .'行测试', ]; } $fileName = '很厉害的文件导出类'; $xlsWriterServer = new MultiFloorXlsWriterService(); $xlsWriterServer->setFileName($fileName, '这是Sheet1别名'); $xlsWriterServer->setHeader($header, true); $xlsWriterServer->setData($data); $xlsWriterServer->addSheet('这是Sheet2别名'); $xlsWriterServer->setHeader($header); //这里可以使用新的header $xlsWriterServer->setData($data); // 这里也可以根据新的header定义数据格式 $filePath = $xlsWriterServer->output(); // 保存到服务器 $xlsWriterServer->excelDownload($filePath); // 输出到浏览器 }
PHP影片教學》
以上是PHP如何使用xlswriter進行大數據的導入匯出? (詳解)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。
