ryunosuke / php-excelate
ryunosuke PHP 模板库
Requires
- php: >=7.4
- phpoffice/phpspreadsheet: 1.*
Requires (Dev)
- phpunit/phpunit: 8.*
This package is auto-updated.
Last update: 2024-09-04 14:36:07 UTC
README
描述
这是一个使 PHPSpreadsheet 支持在表格内嵌入代码的库。
- 通过 roweach/coleach 进行行列操作
- 通过 rowshift/colshift 进行行列位移
- 通过 eval 进行类似 PHP 的嵌入标签
安装
{ "require": { "ryunosuke/php-excelate": "dev-master" } }
演示
php /path/to/excelate/demo/run.php
$renderer = new Renderer(); // ブック全体をレンダリング(拡張子に応じて reader/writer が決まり、一時ファイルに書き出される) $renderer->renderBook(__DIR__ . '/template.xlsx', [ 0 => [ // 基本はシート番号 'title' => 'example', 'rows' => [ ['no' => 1, 'name' => 'hoge', 'attrs' => ['attr1', 'attr2']], ['no' => 2, 'name' => 'fuga', 'attrs' => ['attr1', 'attr2', 'attr3']], ], ], 'sheet' => [], // シート名でもよい '' => [], // 空文字はアクティブシートを意味する ]); // あるいはシートを個別にレンダリング $book = IOFactory::load(__DIR__ . '/template.xlsx'); $renderer->renderSheet($book->getSheet(0), [ 'title' => 'example', 'rows' => [ ['no' => 1, 'name' => 'hoge', 'attrs' => ['attr1', 'attr2']], ['no' => 2, 'name' => 'fuga', 'attrs' => ['attr1', 'attr2', 'attr3']], ], ]); IOFactory::createWriter($book, 'Xlsx')->save(__DIR__ . '/template-out.xlsx');
用法
基本上以 demo 为基础进行说明。
标签
可用的语法如下。
template
A1 单元格允许写操作。这个标签可以明确指定渲染范围。例如,写 {template A1:C12}
则除了 A1:C12 外,其他都不会渲染。
不写也行,但默认范围是“有数据的范围”。有时明确指定会更快。
此外,渲染范围是模板原始状态的范围。如果渲染后行和列增加,则会相应扩展。 (“增加多少行”不需要关心)。
row
直接嵌入数组。不能使用任何嵌入语法,需要调用方 PHP 预先整理数组值,但速度会更快。
{row $array}
如果 $array 是 A, B, C 则展开为 3 列 A B C
rowcol
直接嵌入数组的数组。不能使用任何嵌入语法,需要调用方 PHP 预先整理数组值,但速度会更快。常用于直接嵌入从数据库检索的记录数组等。
{rowcol $records:true}
在最前面添加键数组{rowcol $records:false}
不嵌入键数组
rowif
{rowif $condition}
~ {/rowif}
可以根据 $condition 的真假来跳过渲染。$condition 可以使用变量,也可以使用 PHP 表达式。也就是说可以使用 {rowif $flag1 && !$flag2}
这样的逻辑运算或 {rowif strpos($name, 'hoge') === false}
这样的表达式。
当 $condition 为真时,表现得就像没有 if 标签一样。当为假时,会丢弃标签块,将其视为不存在。当为假时,rowif, /rowif 的位置会有以下行为。
- 左右正好符合模板范围时
- 整行会被删除。在 Excel 中相当于选择单元格后选择删除,然后菜单中的“整行”
- 左右不符合模板范围时
- 块会被向上移动。在 Excel 中相当于选择单元格后选择删除,然后菜单中的“向上移动”
基本上应该正好符合范围使用。因为移动会导致列错位,所以使用起来不方便(或者说实际上没什么用)。
{if}
会被当作“强制符合范围的 {rowif}”处理。这是为了允许像 {roweach $items}{if $flag}...{/if}{/roweach}
这样的常见结构。
但将来计划实现“根据 col/row 的上下文自动判断”的实现。 ({coleach $items}{if $flag}...{/if}{/coleach}
中的 if 会被认为是 colif)。也就是说,“{if} 总是 row 模式”的假设可能会被打破,所以请注意。但通常使用的话不需要担心。简单来说,“没有被循环包围的纯 {if} 不要使用”。
colif
rowif 的列版本。用法完全相同,但“正好”的定义是上下而不是左右。
基本上不正好匹配使用。因为列添加会影响到所有行,所以使用起来不方便(或者说实际上没什么用)。
实际上很难想象需要用 col 来 if 的情况,所以只是作为 rowif 的对应来实现的。
roweach
循环元素直到 /roweach
,并复制单元格范围进行渲染。
有几个语法
{roweach $Values}
循环 $Values。元素的引用方法将在后面说明{roweach $Values $Value}
循环 $Values。将元素值分配给 $Value{roweach $Values $Key:$Value}
循环 $Values。将键分配给 $Key,将元素值分配给 $Value
如上所述,可以仅指定循环变量。在这种情况下,键被视为 $k,值被视为 $v。它不会嵌套进入循环,所以请注意不要在嵌套的循环中跟踪父级的 $k 或 $v。
此外,每个循环都会声明 {$index}
{$first}
{$last}
。依次是“基于 0 的循环序列”、“是否是第一个循环的布尔值”、“是否是最后一个循环的布尔值”。这些名称听起来很常见,容易冲突,所以请注意。
循环值(上面所说的 $Values
)必须是变量。不能使用直接值({roweach [1, 2, 3]}
)或表达式({roweach array_filter($Values)}
)。
元素是类似数组的东西,常见的例子是从数据库 fetchAll 来的数组数组。当循环这样的数组时,其子元素会在循环上下文中展开。
{roweach $rows $row} {$row['name']} でもいいし {$name} でも全く同じです {/roweach}
coleach
roweach 的列版本。
我想几乎不会用到。
rowshift
roweach 是增加行数的结构,但 rowshift 不增加减少,而是进行位移。也就是说,周围的单元格会产生错位。在 Excel 中,相当于选择单元格后选择插入,然后菜单中的“整行”是 roweach,“向下移动”是 rowshift。
实际上很少使用 rowshift。colshift 的使用可能更多。
colshift
rowshift 的列版本。
我想这里会有动态列位移的需求,所以使用频率可能更高。
值填充
上述所有 {}
都被视为值填充,并将其内容作为 PHP 表达式进行解释和执行。以下都是有效的描述。
{$value}
{"{$value}hoge"}
{var_export($value, 1)}
{implode(',', $values)}
可能的话,可以将其视为类似于 <?= ?>
短标签。
效果器
一些处理默认嵌入到上下文中,以局部闭包的形式运行。
このセルはシート!セルへリンクが貼られます{$Link('シート!セル')}
このセルは http://example.com が貼られます{$HyperLink('http://example.com', 'link text')}
このセルは文字色が赤になります{$Color('FF0000')}
このセルは罫線がつきます{$Border([['medium','FF0000']])}
このセルはリスト入力規則になります{$ValidationList(['選択肢A', '選択肢B', '選択肢C'])}
このセルを基準にして画像が埋め込まれます{$Image('path/to/image.png')}
このセルを基準にして画像が埋め込まれます{$Image(['path' => 'path/to/image.png', 'width' => 100, 'description' => '配列で属性が指定できます'])}
也可以不使用此机制,而是分配闭包并调用它。几乎相同。只是效果器有一个“第一个参数是单元格”的特点。这部分的行为,包括 Image 效果器的属性等,最好查看源代码。
效果器可以通过 registerEffector
注册。
注意点
关于单元格遍历
为了搜索嵌入标签,会遍历所有单元格,但遍历是行向的。
coleach coleach
/coleach /coleach
这个模板不能工作。因为它是行向的,所以判断左上和右下·右上和左下是成对的。
关于速度和安全性
最初是为了内部使用,并且是简单应用中使用的,所以没有过多考虑。最好不要在太关键的用途中使用。
关于语法解析器
没有做解析。只是尽力使用正则表达式(将来会替换)。所以如果做了太复杂的事情,可能会很快死掉。用于资料制作或内部使用等可能更安全。