spatie / simple-excel
读取和写入简单的Excel和CSV文件
Requires
- php: ^8.1
- illuminate/support: ^9.0|^10.0|^11.0
- openspout/openspout: ^4.19
Requires (Dev)
- pestphp/pest-plugin-laravel: ^1.3|^2.3
- phpunit/phpunit: ^9.4|^10.5
- spatie/pest-plugin-snapshots: ^1.1|^2.1
- spatie/phpunit-snapshot-assertions: ^4.0|^5.1
- spatie/temporary-directory: ^1.2|^2.2
- dev-main
- v3.x-dev
- 3.6.0
- 3.5.0
- 3.4.0
- 3.3.0
- 3.2.1
- 3.2.0
- 3.1.0
- 3.0.1
- 3.0.0
- 2.5.0
- 2.4.0
- 2.3.0
- 2.2.0
- 2.1.0
- 2.0.0
- 1.15.1
- 1.15.0
- 1.14.1
- 1.14.0
- 1.13.1
- 1.13.0
- 1.12.0
- 1.11.0
- 1.10.2
- 1.10.1
- 1.10.0
- 1.9.1
- 1.9.0
- 1.8.1
- 1.8.0
- 1.7.1
- 1.7.0
- 1.6.0
- 1.5.0
- 1.4.0
- 1.3.1
- 1.3.0
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.0
- 1.0.0
- 0.0.3
- 0.0.2
- 0.0.1
This package is auto-updated.
Last update: 2024-09-22 09:38:55 UTC
README
此包允许您轻松读取和写入简单的Excel和CSV文件。在幕后,使用生成器确保即使处理大文件时,内存使用量也较低。
以下是如何读取Excel或CSV的示例。
use Spatie\SimpleExcel\SimpleExcelReader; SimpleExcelReader::create($pathToFile)->getRows() ->each(function(array $rowProperties) { // process the row });
如果 $pathToFile
以 .csv
结尾,则假定是CSV文件。如果以 .xlsx
结尾,则假定是Excel文件。
支持我们
我们投入了大量资源来创建最佳开源包。您可以通过购买我们的付费产品之一来支持我们。
我们非常感谢您从家乡寄给我们明信片,并说明您正在使用我们的哪个包。您可以在我们的联系页面找到我们的地址。我们将所有收到的明信片发布在我们的虚拟明信片墙上。
安装
您可以通过composer安装此包
composer require spatie/simple-excel
用法
读取CSV
假设您有一个包含以下内容的CSV文件。
email,first_name
john@example.com,john
jane@example.com,jane
use Spatie\SimpleExcel\SimpleExcelReader; // $rows is an instance of Illuminate\Support\LazyCollection $rows = SimpleExcelReader::create($pathToCsv)->getRows(); $rows->each(function(array $rowProperties) { // in the first pass $rowProperties will contain // ['email' => 'john@example.com', 'first_name' => 'john'] });
读取Excel文件
读取Excel文件与读取CSV文件相同。只需确保传递给 SimpleExcelReader
的 create
方法的路径以 xlsx
结尾即可。
使用LazyCollections
getRows
将返回一个 Illuminate\Support\LazyCollection
的实例。此类是Laravel框架的一部分。在幕后使用生成器,因此即使对于大文件,内存使用量也将保持较低。
您可以在Laravel文档中找到可以在 LazyCollection
上使用的列表。
以下是一个快速、愚蠢的示例,其中我们只想处理具有超过5个字符的 first_name
的行。
SimpleExcelReader::create($pathToCsv)->getRows() ->filter(function(array $rowProperties) { return strlen($rowProperties['first_name']) > 5; }) ->each(function(array $rowProperties) { // processing rows });
读取无标题行的文件
如果您正在读取的文件不包含标题行,则应使用 noHeaderRow()
方法。
// $rows is an instance of Illuminate\Support\LazyCollection $rows = SimpleExcelReader::create($pathToCsv) ->noHeaderRow() ->getRows() ->each(function(array $rowProperties) { // in the first pass $rowProperties will contain // [0 => 'john@example', 1 => 'john'] });
手动设置标题
如果您想使用特定数组值作为标题,可以使用 useHeaders()
方法。
// $rows is an instance of Illuminate\Support\LazyCollection $rows = SimpleExcelReader::create($pathToCsv) ->useHeaders(['email_address', 'given_name']) ->getRows() ->each(function(array $rowProperties) { // in the first pass $rowProperties will contain // ['email_address' => 'john@example', 'given_name' => 'john'] });
如果您的文件已经包含标题行,它将被忽略并替换为您的自定义标题。
如果您的文件不包含标题行,您还应该使用 noHeaderRow()
,并且您的标题将像上面那样代替数字键。
处理多工作表文档
Excel文件可以包含多个工作表。您可以使用 fromSheet()
方法通过索引选择您想要使用的工作表。
$rows = SimpleExcelReader::create($pathToXlsx) ->fromSheet(3) ->getRows();
对于多个工作表,您也可以使用 fromSheetName()
方法通过名称选择您想要使用的工作表。
$rows = SimpleExcelReader::create($pathToXlsx) ->fromSheetName("sheet1") ->getRows();
如果您想检查工作表是否存在,请使用 hasSheet()
方法。
$hasSheet = SimpleExcelReader::create($pathToXlsx) ->hasSheet("sheet1");
检索标题行值
如果您想将标题行作为数组检索,请使用 getHeaders()
方法。
如果您使用过 useHeaders()
来设置自定义头,那么将返回这些头而不是文件的实际头。要获取文件中的原始头,请使用 getOriginalHeaders()
。
$headers = SimpleExcelReader::create($pathToCsv)->getHeaders(); // $headers will contain // [ 'email', 'first_name' ]
处理不在第一行的头
如果您的文件中的头不在第一行,您可以使用 headerOnRow()
方法来指示头所在的行。任何在此行之上的数据都将从结果中丢弃。
headerOnRow
接受行号作为参数,从 0 开始。空行不计入。
由于空行不计入,此方法主要用于包含实际数据集上方格式的文件,例如 Excel 文件。
This is my data sheet
See worksheet 1 for the data, worksheet 2 for the graphs.
email , firstname
john@example.com,john
jane@example.com,jane
// $rows is an instance of Illuminate\Support\LazyCollection $rows = SimpleExcelReader::create($pathToCsv) ->trimHeaderRow() ->headerOnRow(3) ->getRows() ->each(function(array $rowProperties) { // in the first pass $rowProperties will contain // ['email' => 'john@example', 'first_name' => 'john'] });
修剪头
如果您正在读取的文件包含标题行,但需要在标题值上修剪额外字符,则应使用 trimHeaderRow()
方法。此功能模仿 trim
方法,并且默认要修剪的字符与该函数匹配。
想象您有一个包含以下内容的 csv 文件。
email , first_name
john@example.com,john
jane@example.com,jane
// $rows is an instance of Illuminate\Support\LazyCollection $rows = SimpleExcelReader::create($pathToCsv) ->trimHeaderRow() ->getRows() ->each(function(array $rowProperties) { // in the first pass $rowProperties will contain // ['email' => 'john@example', 'first_name' => 'john'] });
trimHeaderRow()
还接受一个参数来指定要修剪的字符。此参数可以使用与 trim 函数的 $characters
定义相同的函数。
将头转换为 snake_case
如果您希望所有头都转换为 snake_case,请使用 headersToSnakeCase()
方法。
Email,First Name,Last Name
john@example.com,john,doe
mary-jane@example.com,mary jane,doe
$rows = SimpleExcelReader::create($pathToCsv) ->headersToSnakeCase() ->getRows() ->each(function(array $rowProperties) { // rowProperties converted to snake_case // ['email' => 'john@example', 'first_name' => 'John', 'last_name' => 'doe'] });
手动格式化头
您可以使用自定义格式化器通过 formatHeadersUsing
方法并传递一个闭包来更改头。
email,first_name,last_name
john@example.com,john,doe
mary-jane@example.com,mary jane,doe
$rows = SimpleExcelReader::create($pathToCsv) ->formatHeadersUsing(fn($header) => "{$header}_simple_excel") ->getRows() ->each(function(array $rowProperties) { // ['email_simple_excel' => 'john@example', 'first_name_simple_excel' => 'John', 'last_name_simple_excel' => 'doe'] });
手动处理读取器对象
在内部,此包使用 box/spout 包。您可以通过调用 getReader
方法来获取实现 \OpenSpout\Reader\ReaderInterface
的底层读取器。
$reader = SimpleExcelReader::create($pathToCsv)->getReader();
限制结果集
take
方法允许您指定要返回的行数限制。
// $rows is an instance of Illuminate\Support\LazyCollection $rows = SimpleExcelReader::create($pathToCsv) ->take(5) ->getRows();
skip
方法允许您定义从哪一行开始读取数据。在此示例中,我们获取第 11 行到第 16 行。
$rows = SimpleExcelReader::create($pathToCsv) ->skip(10) ->take(5) ->getRows();
读取包含公式的单元格
通常,包含公式的单元格会被解析,并且它们的计算值将被返回。如果您想将实际的公式作为字符串保留,请使用 keepFormulas
方法。
$rows = SimpleExcelReader::create($pathToXlsx) ->keepFormulas() ->getRows();
写入文件
这是写入 CSV 文件的方法
use Spatie\SimpleExcel\SimpleExcelWriter; $writer = SimpleExcelWriter::create($pathToCsv) ->addRow([ 'first_name' => 'John', 'last_name' => 'Doe', ]) ->addRow([ 'first_name' => 'Jane', 'last_name' => 'Doe', ]);
位于 pathToCsv
的文件将包含
first_name,last_name
John,Doe
Jane,Doe
从数组手动设置头
您不必让包自动检测标题行,可以手动设置它。
use Spatie\SimpleExcel\SimpleExcelWriter; $writer = SimpleExcelWriter::create($pathToCsv) ->addHeader(['first_name', 'last_name']) ->addRow(['John', 'Doe']) ->addRow(['Jane', 'Doe'])
写入 Excel 文件
写入 Excel 文件与写入 csv 相同。只需确保给 SimpleExcelWriter
的 create
方法的路径以 xlsx
结尾。在写入 Excel 文件时要注意的另一件事是,文件不会在 SimpleExcelWriter
实例被垃圾回收之前写入。那时将调用 close
方法。close
方法是最终将文件写入磁盘的方法。如果您需要在实例被垃圾回收之前访问文件,您需要先调用 close
方法。
$writer->close();
将 Excel 文件流式传输到浏览器
您可以直接将文件流式传输到浏览器,而不是将其写入磁盘。
$writer = SimpleExcelWriter::streamDownload('your-export.xlsx') ->addRow([ 'first_name' => 'John', 'last_name' => 'Doe', ]) ->addRow([ 'first_name' => 'Jane', 'last_name' => 'Doe', ]) ->toBrowser();
如果您向浏览器发送大型流,请确保调用 flush()
$writer = SimpleExcelWriter::streamDownload('your-export.xlsx'); foreach (range(1, 10_000) as $i) { $writer->addRow([ 'first_name' => 'John', 'last_name' => 'Doe', ]); if ($i % 1000 === 0) { flush(); // Flush the buffer every 1000 rows } } $writer->toBrowser();
您还可以使用回调。
use Spatie\SimpleExcel\SimpleExcelWriter; use OpenSpout\Common\Entity\Row; $writer = SimpleExcelWriter::streamDownload('user-list.xlsx', function ($writerCallback, $downloadName) { $writerCallback->openToBrowser($downloadName); $writerCallback->addRow(Row::fromValues([ 'first_name' => 'First Name', 'last_name' => 'Last Name', ])); $writerCallback->addRow(Row::fromValues([ 'first_name' => 'Rakib', 'last_name' => 'Hossain', ])); foreach (range(1, 10_000) as $i) { $writerCallback->addRow(Row::fromValues([ 'first_name' => 'Rakib', 'last_name' => 'Hossain', ])); if ($i % 1000 === 0) { flush(); } } }); $writer->toBrowser();
一次写入多行
您可以使用 addRows
而不是 addRow
来一次添加多行。
$writer = SimpleExcelWriter::streamDownload('your-export.xlsx') ->addRows([ [ 'first_name' => 'John', 'last_name' => 'Doe', ], [ 'first_name' => 'Jane', 'last_name' => 'Doe', ], ]);
写入不带标题的文件
如果您正在编写的文件不应该自动添加标题行,则应使用 noHeaderRow()
方法。
$writer = SimpleExcelWriter::create($pathToCsv) ->noHeaderRow() ->addRow([ 'first_name' => 'Jane', 'last_name' => 'Doe', ]);
这将输出
Jane,Doe
添加布局
在底层,此包使用 openspout/openspout 包。该包包含一个 Style
构建器,您可以使用它来格式化行。样式只能在 Excel 文档中使用。
use OpenSpout\Common\Entity\Style\Color; use OpenSpout\Common\Entity\Style\CellAlignment; use OpenSpout\Common\Entity\Style\Style; use OpenSpout\Common\Entity\Style\Border; use OpenSpout\Common\Entity\Style\BorderPart; /* Create a border around a cell */ $border = new Border( new BorderPart(Border::BOTTOM, Color::LIGHT_BLUE, Border::WIDTH_THIN, Border::STYLE_SOLID), new BorderPart(Border::LEFT, Color::LIGHT_BLUE, Border::WIDTH_THIN, Border::STYLE_SOLID), new BorderPart(Border::RIGHT, Color::LIGHT_BLUE, Border::WIDTH_THIN, Border::STYLE_SOLID), new BorderPart(Border::TOP, Color::LIGHT_BLUE, Border::WIDTH_THIN, Border::STYLE_SOLID) ); $style = (new Style()) ->setFontBold() ->setFontSize(15) ->setFontColor(Color::BLUE) ->setShouldWrapText() ->setBackgroundColor(Color::YELLOW) ->setBorder($border); $writer->addRow(['values', 'of', 'the', 'row'], $style);
要格式化标题行,只需调用 setHeaderStyle($style)
方法。
$writer->setHeaderStyle($style);
有关样式的更多信息,请访问 Spout 文档。
设置列宽和行高
通过访问底层 OpenSpout Writer,您可以设置默认列宽和行高,并更改特定列的宽度。
SimpleExcelWriter::create( file: 'document.xlsx', configureWriter: function ($writer) { $options = $writer->getOptions(); $options->DEFAULT_COLUMN_WIDTH=25; // set default width $options->DEFAULT_ROW_HEIGHT=15; // set default height // set columns 1, 3 and 8 to width 40 $options->setColumnWidth(40, 1, 3, 8); // set columns 9 through 12 to width 10 $options->setColumnWidthForRange(10, 9, 12); } )
创建额外的工作表
默认情况下,编写器将写入第一个工作表。如果您想写入额外的工作表,可以使用 addNewSheetAndMakeItCurrent
方法。
$writer = SimpleExcelWriter::create($pathToXlsx); Posts::all()->each(function (Post $post) use ($writer) { $writer->nameCurrentSheet($post->title); $post->comments->each(function (Comment $comment) use ($writer) { $writer->addRow([ 'comment' => $comment->comment, 'author' => $comment->author, ]); }); if(!$post->is($posts->last())) { $writer->addNewSheetAndMakeItCurrent(); } });
使用替代分隔符
默认情况下,SimpleExcelReader
将假设分隔符是 ,
。
这是您如何使用替代分隔符的方法
SimpleExcelWriter::create(file: $pathToCsv, delimiter: ';');
获取已写入的行数
您可以获取已写入的行数。此数字包括自动添加的标题行。
$writerWithAutomaticHeader = SimpleExcelWriter::create($this->pathToCsv) ->addRow([ 'first_name' => 'John', 'last_name' => 'Doe', ]); $writerWithAutomaticHeader->getNumberOfRows(); // returns 2
禁用 BOM
您还可以禁用在文件开头添加 BOM。必须在创建时禁用 BOM,并且创建编写器后不能禁用。
BOM(字节顺序标记)表示正在写入的文件的一些内容,包括文件是 Unicode 以及其 UTF 编码类型。
SimpleExcelWriter::createWithoutBom($this->pathToCsv, $type);
有关 BOM 的更多信息,请参阅 此处。
手动处理编写器对象
在底层,此包使用 openspout/openspout 包。您可以通过调用 getWriter
方法来访问实现 \OpenSpout\Reader\WriterInterface
的底层编写器。
$writer = SimpleExcelWriter::create($pathToCsv)->getWriter();
测试
composer test
变更日志
有关最近更改的更多信息,请参阅 变更日志。
贡献
有关详细信息,请参阅 贡献指南。
安全性
如果您发现了关于安全性的错误,请通过 security@spatie.be 邮件联系,而不是使用问题跟踪器。
明信片软件
您可以自由使用此包,但如果它进入了您的生产环境,我们非常欢迎您从家乡寄给我们一张明信片,注明您正在使用我们的哪个包。
我们的地址是:Spatie,Kruikstraat 22,2018 安特卫普,比利时。
我们将发布所有收到的明信片 在我们的公司网站上。
鸣谢
替代方案
许可
MIT 许可证(MIT)。有关更多信息,请参阅 许可文件。