xin / excel
基于OpenSpout封装的轻量级高性能表格处理类库,仅占用3M内存,即可轻松实现上百万行数据的高效导入与导出。
v2.0.0
2025-01-21 15:43 UTC
Requires
- php: >=7.1.9
- openspout/openspout: ^4.25
- xin/capsule: ^1.0
- xin/support: ^1.0
This package is auto-updated.
Last update: 2025-01-22 01:59:57 UTC
README
介绍
基于OpenSpout
封装的轻量级高性能表格处理类库,仅占用3M内存,即可轻松实现上百万行数据的高效导入与导出。
你还在为 PhpSpreadsheet 封装的类库占用内存过大,无法满足业务需求时,而苦恼吗?
那么,Xin-Excel
就是你的救星,它基于OpenSpout
封装的轻量级高性能表格处理类库,仅占用3M内存,即可轻松实现上百万行数据的高效导入与导出。
从此你就可以轻松实现Excel表格数据的导出与导入,轻松解决Excel表格数据导出与导入的问题,专注于业务逻辑,不再为表格数据导出与导入而烦恼。
安装教程
composer require xin/excel
使用说明
<?php
use Xin\Excel\Column;
use Xin\Excel\Dataset;
use Xin\Excel\Export;
use Xin\Excel\Import;
require __DIR__ . '/vendor/autoload.php';
echo "初始化内存: " . (memory_get_usage() / 1024 / 1024) . " MB\n";
$excelFilepath = 'aa.xlsx';
//======================数据导出====================================
$dataset = new Dataset(new MakeBigData(), [
Column::integer('id', 'ID'),
Column::title('goods_title', '商品名称'),
Column::integer('goods_num', '数量')->setWidth(10),
Column::price('goods_price', '单价'),
Column::RMB('total_price', '合计'),
Column::custom(function ($row) {
return "{$row['master_order']['user_nickname']}(用户ID:{$row['master_order']['user_id']})";
}, '买家信息')->setWidth(20),
Column::create('master_order.receiver_name', '收货人姓名')->setWidth(15),
Column::phone('master_order.receiver_phone', '收货人手机号'),
Column::custom(function ($row) {
return "{$row['master_order']['receiver_province']}{$row['master_order']['receiver_city']}{$row['master_order']['receiver_city']}{$row['master_order']['receiver_address']}";
}, '收货人地址'),
Column::create('master_order.pay_type_text', '支付方式')->setWidth(10),
Column::create('master_order.order_no', '订单编号'),
Column::create('master_order.order_status_text', '订单状态'),
Column::datetime('create_time', '下单时间'),
], '订单数据');
// 快速导出数据
Export::data(new MakeBigData(), $dataset->columns(), $excelFilepath, '订单数据');
// 快速导出多个数据源
$dataset2 = clone $dataset;
$dataset2->setTitle('订单数据2');
Export::make([$dataset])->addDataset($dataset2)->save($excelFilepath);
//======================数据导入====================================
// 列映射,支持索引和首行标题两种方式进行映射
$columnsMapping = [
'id' => 'ID',
'goods_time' => 1,
'create_time' => '下单时间',
];
// 加载单个工作表
$data = Import::load(
$excelFilepath, // 加载的文件
$columnsMapping, // 列的映射关系
0, // 读取的起始工作表索引
[
'max_count' => 10,
], // 读取的参数
);
var_dump($data);
// 加载多个工作表
$data = Import::loadMultiple(
$excelFilepath, // 加载的文件
[
$columnsMapping,
$columnsMapping,
],// 每个工作表列的映射关系
[0, 2], // 要读取的工作表索引或名称
[
0 => [
'max_count' => 100,
],
],// 读取的参数
);
var_dump($data);
// 遍历工作表数据
Import::make($excelFilepath)->each(
0,
function ($row) {
var_dump($row);
},
$columnsMapping,
[
'max_count' => 100,
]
);
Import::make($excelFilepath)->chunk(
0,
function ($rows) {
var_dump($rows);
},
$columnsMapping,
10,
[
'max_count' => 100,
]
);
// 遍历所有工作表数据
Import::make($excelFilepath)->eachAll(
function ($row, $count) {
var_dump($row, $count);
return $count < 50;
},
[$columnsMapping],
[],
[
[Import::OPTION_MAX_COUNT => 100],
]
);
// 使用分块遍历所有工作表数据
Import::make($excelFilepath)->chunkAll(
function ($row) {
var_dump($row);
},
[$columnsMapping],
[],
1000,
[
[Import::OPTION_MAX_COUNT => 1000],
]
);
echo "处理后内存: " . (memory_get_usage() / 1024 / 1024) . " MB\n";
echo "内存峰值: " . (memory_get_peak_usage() / 1024 / 1024) . " MB\n";
class MakeBigData implements \Iterator
{
/**
* @var int
*/
protected $index = 0;
/**
* @var int
*/
protected $max = 10000;
const content = <<<TEXT
《追日者与移山人》
在古老的华夏大地上,有两个相邻的部落。一个部落居住在巍峨的太行山脚下,另一个部落则生活在广袤的平原上。太行山部落的首领是一位名叫愚公的长者,而平原部落的首领则是一位名叫追日的勇士。
愚公年事已高,但精神矍铄。他所在的部落被太行山和王屋山阻隔,交通不便,生活困苦。愚公深知,这两座大山是部落发展的最大障碍。于是,他召集族人,提出了一个大胆的计划——移山。族人们虽然对愚公的计划感到震惊,但都被他的决心所打动,纷纷响应。他们用简陋的工具,开始挖掘山石,将土石运往渤海之滨。尽管困难重重,但愚公坚信,只要子孙后代坚持不懈,终有一天会移走这两座大山。
与此同时,平原部落的追日是一位力大无穷的勇士。他的部落曾因十个太阳同时出现而陷入灾难,庄稼枯萎,土地干裂,百姓流离失所。后来,追日的祖先后羿射落九个太阳,拯救了部落。追日从小就听着后羿的故事长大,他渴望像祖先一样,为部落做出伟大的贡献。
有一天,追日得知愚公移山的壮举,深受感动。他决定前往太行山,帮助愚公的部落。当他来到愚公的部落时,看到愚公和族人们正在辛勤地劳作,尽管疲惫不堪,但无人退缩。追日被他们的精神所打动,决定加入他们。
追日的加入为移山的工程带来了巨大的帮助。他力大无穷,能轻松地举起巨石,还能用神力驱散山间的迷雾。在他的帮助下,工程进展得更快了。然而,移山并非易事,愚公的部落面临着诸多困难。智叟曾嘲笑愚公不自量力,但愚公毫不理会,依然坚持自己的信念。
随着时间的推移,愚公和追日的友谊也日益深厚。他们互相鼓励,共同面对困难。愚公告诉追日,移山的意义不仅在于改变地理环境,更在于传承一种不屈不挠的精神。追日则用他的勇气和力量,激励着族人们继续前行。
终于,在愚公和追日的共同努力下,太行山和王屋山被逐渐移平。虽然工程尚未完全结束,但道路已不再阻塞,部落的生活也逐渐改善。愚公的子孙们继承了他的遗志,继续挖掘,而追日也成为了部落的英雄。
故事传遍了大地,人们被愚公的坚持和追日的勇气所感动。他们明白,无论面对多么巨大的困难,只要心中有信念,坚持不懈,就一定能创造出奇迹。正如夸父追日时所展现的勇气和决心,虽然他最终倒在了追日的途中,但他留下的精神却激励了后人。
TEXT;
/**
* @param int $max
*/
public function __construct(int $max = 10000)
{
$this->max = $max;
}
public function current(): mixed
{
return [
'id' => $this->index + 1,
'goods_title' => '商品名称',
'goods_num' => random_int(0, 9999),
'content' => self::content,
'goods_price' => floatval(random_int(0, 99999) . "." . random_int(0, 99)),
'create_time' => date('Y-m-d H:i:s'),
'master_order' => [
'user_id' => '1',
'user_nickname' => 'xxxx',
'receiver_phone' => '13653975075',
'receiver_province' => '',
'receiver_city' => '',
'receiver_address' => '',
],
];
}
public function next(): void
{
$this->index++;
}
public function key(): mixed
{
return $this->index;
}
public function valid(): bool
{
return $this->index < $this->max;
}
public function rewind(): void
{
$this->index = 0;
}
}