Skip to content

Commit 879898d

Browse files
authored
Add Excel OpenSpout exporter (#332)
* Basic OpenSpout Excel exporter * ExcelOpenSpoutExporter: test case for exporter collection --------- Co-authored-by: Maarten Visscher <[email protected]>
1 parent 668e7bd commit 879898d

File tree

5 files changed

+206
-1
lines changed

5 files changed

+206
-1
lines changed

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"friendsofphp/php-cs-fixer": "^v3.40.0",
4141
"mongodb/mongodb": "^1.17",
4242
"ocramius/package-versions": "^2.8",
43+
"openspout/openspout": "^4.23",
4344
"phpoffice/phpspreadsheet": "^1.29.0 || ^2.0",
4445
"phpstan/extension-installer": "^1.3.1",
4546
"phpstan/phpstan": "^1.10.55",
@@ -65,7 +66,8 @@
6566
"mongodb/mongodb": "For integration with MongoDB collections",
6667
"ruflin/elastica": "For integration with Elasticsearch indexes",
6768
"symfony/twig-bundle": "To use default Twig based rendering and TwigColumn",
68-
"phpoffice/phpspreadsheet": "To export the data from DataTables to Excel"
69+
"phpoffice/phpspreadsheet": "To export the data from DataTables to Excel",
70+
"openspout/openspout": "To use the OpenSpout Excel exporter"
6971
},
7072
"autoload": {
7173
"psr-4": { "Omines\\DataTablesBundle\\": "src/"}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* Symfony DataTables Bundle
5+
* (c) Omines Internetbureau B.V. - https://omines.nl/
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace Omines\DataTablesBundle\Exporter\Excel;
14+
15+
use Omines\DataTablesBundle\Exporter\DataTableExporterInterface;
16+
use OpenSpout\Common\Entity\Row;
17+
use OpenSpout\Common\Entity\Style\Style;
18+
use OpenSpout\Writer\XLSX\Writer;
19+
20+
/**
21+
* Excel exporter using OpenSpout.
22+
*/
23+
class ExcelOpenSpoutExporter implements DataTableExporterInterface
24+
{
25+
public function export(array $columnNames, \Iterator $data): \SplFileInfo
26+
{
27+
$filePath = sys_get_temp_dir() . '/' . uniqid('dt') . '.xlsx';
28+
29+
$writer = new Writer();
30+
$writer->openToFile($filePath);
31+
32+
// Write header
33+
$boldStyle = (new Style())->setFontBold();
34+
$writer->addRow(Row::fromValues($columnNames, $boldStyle));
35+
36+
// Write data
37+
foreach ($data as $row) {
38+
// Remove HTML tags
39+
$values = array_map('strip_tags', $row);
40+
41+
$writer->addRow(Row::fromValues($values));
42+
}
43+
44+
$writer->close();
45+
46+
return new \SplFileInfo($filePath);
47+
}
48+
49+
public function getMimeType(): string
50+
{
51+
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
52+
}
53+
54+
public function getName(): string
55+
{
56+
return 'excel-openspout';
57+
}
58+
}

src/Resources/config/services.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
<tag name="datatables.exporter"/>
3939
</service>
4040

41+
<service id="Omines\DataTablesBundle\Exporter\Excel\ExcelOpenSpoutExporter">
42+
<tag name="datatables.exporter"/>
43+
</service>
44+
4145
<service id="Omines\DataTablesBundle\Exporter\Csv\CsvExporter">
4246
<tag name="datatables.exporter"/>
4347
</service>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
3+
/*
4+
* Symfony DataTables Bundle
5+
* (c) Omines Internetbureau B.V. - https://omines.nl/
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace Tests\Functional\Exporter\Excel;
14+
15+
use PhpOffice\PhpSpreadsheet\IOFactory;
16+
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
17+
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
18+
use Symfony\Component\HttpFoundation\BinaryFileResponse;
19+
20+
class ExcelOpenSpoutExporterTest extends WebTestCase
21+
{
22+
/** @var KernelBrowser */
23+
private $client;
24+
25+
protected function setUp(): void
26+
{
27+
self::ensureKernelShutdown();
28+
$this->client = self::createClient();
29+
}
30+
31+
public function testExport(): void
32+
{
33+
$this->client->request('POST', '/exporter', ['_dt' => 'dt', '_exporter' => 'excel-openspout']);
34+
35+
$response = $this->client->getResponse();
36+
37+
// Using PhpSpreadsheet for tests
38+
$sheet = IOFactory::load($response->getFile()->getPathname())->getActiveSheet();
39+
40+
static::assertSame('dt.columns.firstName', $sheet->getCell('A1')->getFormattedValue());
41+
static::assertSame('dt.columns.lastName', $sheet->getCell('B1')->getFormattedValue());
42+
43+
static::assertSame('FirstName0', $sheet->getCell('A2')->getFormattedValue());
44+
static::assertSame('LastName0', $sheet->getCell('B2')->getFormattedValue());
45+
46+
static::assertSame('FirstName1', $sheet->getCell('A3')->getFormattedValue());
47+
static::assertSame('LastName1', $sheet->getCell('B3')->getFormattedValue());
48+
49+
static::assertSame('FirstName2', $sheet->getCell('A4')->getFormattedValue());
50+
static::assertSame('LastName2', $sheet->getCell('B4')->getFormattedValue());
51+
52+
static::assertSame('FirstName3', $sheet->getCell('A5')->getFormattedValue());
53+
static::assertSame('LastName3', $sheet->getCell('B5')->getFormattedValue());
54+
55+
static::assertSame('FirstName4', $sheet->getCell('A6')->getFormattedValue());
56+
static::assertSame('LastName4', $sheet->getCell('B6')->getFormattedValue());
57+
}
58+
59+
public function testEmptyDataTable(): void
60+
{
61+
$this->client->request('POST', '/exporter-empty-datatable', ['_dt' => 'dt', '_exporter' => 'excel-openspout']);
62+
63+
/** @var BinaryFileResponse $response */
64+
$response = $this->client->getResponse();
65+
66+
static::assertTrue($response->isSuccessful());
67+
68+
// Using PhpSpreadsheet for tests
69+
$sheet = IOFactory::load($response->getFile()->getPathname())->getActiveSheet();
70+
71+
static::assertSame('dt.columns.firstName', $sheet->getCell('A1')->getFormattedValue());
72+
static::assertSame('dt.columns.lastName', $sheet->getCell('B1')->getFormattedValue());
73+
74+
static::assertEmpty($sheet->getCell('A2')->getFormattedValue());
75+
static::assertEmpty($sheet->getCell('B2')->getFormattedValue());
76+
}
77+
78+
public function testWithSearch(): void
79+
{
80+
$this->client->request('POST', '/exporter', [
81+
'_dt' => 'dt',
82+
'_exporter' => 'excel-openspout',
83+
'search' => ['value' => 'FirstName124'],
84+
]);
85+
86+
/** @var BinaryFileResponse $response */
87+
$response = $this->client->getResponse();
88+
89+
// Using PhpSpreadsheet for tests
90+
$sheet = IOFactory::load($response->getFile()->getPathname())->getActiveSheet();
91+
92+
static::assertSame('dt.columns.firstName', $sheet->getCell('A1')->getFormattedValue());
93+
static::assertSame('dt.columns.lastName', $sheet->getCell('B1')->getFormattedValue());
94+
95+
static::assertSame('FirstName124', $sheet->getCell('A2')->getFormattedValue());
96+
static::assertSame('LastName124', $sheet->getCell('B2')->getFormattedValue());
97+
98+
static::assertEmpty($sheet->getCell('A3')->getFormattedValue());
99+
static::assertEmpty($sheet->getCell('B3')->getFormattedValue());
100+
}
101+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* Symfony DataTables Bundle
5+
* (c) Omines Internetbureau B.V. - https://omines.nl/
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace Tests\Unit\Exporter;
14+
15+
use Omines\DataTablesBundle\Exporter\DataTableExporterCollection;
16+
use Omines\DataTablesBundle\Exporter\Excel\ExcelOpenSpoutExporter;
17+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
18+
19+
class ExcelOpenSpoutExporterTest extends KernelTestCase
20+
{
21+
/** @var DataTableExporterCollection */
22+
private $exporterCollection;
23+
24+
protected function setUp(): void
25+
{
26+
$this->bootKernel();
27+
28+
$this->exporterCollection = $this->getContainer()->get(DataTableExporterCollection::class);
29+
}
30+
31+
public function testTag(): void
32+
{
33+
$this->assertInstanceOf(ExcelOpenSpoutExporter::class, $this->exporterCollection->getByName('excel-openspout'));
34+
}
35+
36+
public function testName(): void
37+
{
38+
$this->assertSame('excel-openspout', $this->exporterCollection->getByName('excel-openspout')->getName());
39+
}
40+
}

0 commit comments

Comments
 (0)