PHP code example of intragile / laravel-spreadsheet

1. Go to this page and download the library: Download intragile/laravel-spreadsheet library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

intragile / laravel-spreadsheet example snippets


use IntrAgile\LaravelSpreadsheet\Export\Column;
use IntrAgile\LaravelSpreadsheet\Export\Export;

return Export::fromQuery(Partner::query()->where('active', true))
    ->withColumns([
        Column::make('Name'),
        Column::make('Email'),
        Column::make('Revenue', 'revenue')->format('#,##0.00'),
    ])
    ->download('partners.xlsx');

$result = PartnerImport::from($request->file('file')->getRealPath())->run();

// $result->created, $result->updated, $result->skipped, $result->failed, $result->failedRowsPath

use IntrAgile\LaravelSpreadsheet\Export\Column;
use IntrAgile\LaravelSpreadsheet\Export\Export;
use IntrAgile\Spreadsheet\Style;

$export = Export::fromQuery(Order::query()->where('year', 2026))
    ->withColumns([
        Column::make('Order number', 'number')->asText(),           // "00123" stays text
        Column::make('Customer', 'customer.name'),                   // data_get path
        Column::make('Total', 'total')->format('#,##0.00')->width(14),
        Column::make('Ordered at', 'created_at')->format('yyyy-mm-dd'),
        Column::make('Status', fn (Order $order) => $order->status->label()),
    ])
    ->sortBy('created_at', 'desc')
    ->sheet('Orders')
    ->headerStyle(Style::make()->bold()->fill('D9E1F2'));

return $export->download('orders.xlsx');       // StreamedResponse
$path = $export->store('exports/orders.xlsx', 's3');
$rows = $export->writeTo('/tmp/orders.csv');  // local file, returns the row count

use Illuminate\Database\Eloquent\Builder;
use IntrAgile\LaravelSpreadsheet\Export\Column;
use IntrAgile\LaravelSpreadsheet\Export\Export;

final class PartnersExport extends Export
{
    public function __construct(private readonly int $year) {}

    public function query(): Builder
    {
        return Partner::query()->whereYear('created_at', $this->year);
    }

    public function columns(): array
    {
        return [
            Column::make('Name'),
            Column::make('Tax number', 'tax_number')->asText(),
            Column::make('Revenue', 'revenue')->format('#,##0.00'),
        ];
    }
}

return (new PartnersExport(2026))->download('partners-2026.xlsx');

(new PartnersExport(2026))
    ->onConnection('redis')
    ->onQueue('exports')
    ->queue('exports/partners-2026.xlsx', 's3');

use IntrAgile\LaravelSpreadsheet\Events\ExportCompleted;

Event::listen(function (ExportCompleted $event) {
    $user->notify(new ExportReady(Storage::disk($event->disk)->temporaryUrl($event->path, now()->addDay())));
});

use IntrAgile\LaravelSpreadsheet\Import\Field;
use IntrAgile\LaravelSpreadsheet\Import\FieldType;
use IntrAgile\LaravelSpreadsheet\Import\Import;
use IntrAgile\LaravelSpreadsheet\Matching\MatchPolicy;
use IntrAgile\LaravelSpreadsheet\Matching\MatchRule;

final class PartnerImport extends Import
{
    public function model(): string
    {
        return Partner::class;
    }

    public function fields(): array
    {
        return [
            Field::make('name')->label(['en' => 'Name', 'hu' => 'Név'])->
                'inactive' => ['en' => 'Inactive', 'hu' => 'Inaktív'],
            ]),
        ];
    }

    public function rules(): array
    {
        return ['email' => ['email'], 'revenue' => ['nullable', 'numeric', 'min:0']];
    }

    public function matchRules(): array
    {
        return [MatchRule::sure('tax_number'), MatchRule::suspicious('name')];
    }

    public function onMatch(): MatchPolicy
    {
        return MatchPolicy::FillMissing;
    }
}

use IntrAgile\LaravelSpreadsheet\Import\ImportStatus;

$result = PartnerImport::from('uploads/partners.xlsx', 'local')   // path and disk; no disk = local path
    ->sheet('Partners')        // optional: index or name; default is the first visible sheet with data
    ->headerRow(3)             // optional: detected when not given
    ->chunkSize(500)           // optional: rows per transaction
    ->run();

if ($result->status === ImportStatus::NeedsConfirmation) {
    // show $result->mapping to the user, see below
}

$result->created;          // new records
$result->updated;          // matched records written under FillMissing, Overwrite or a callback
$result->skipped;          // in-file duplicates, matches under Skip, rows sent to review
$result->failed;           // rows with an error
$result->failedRowsDisk;   // where the failed-rows file was stored (null when every row went through)
$result->failedRowsPath;

$pending = PartnerImport::from($path);

$mapping = $pending->inspect();           // ColumnMapping; no data row is read

foreach ($mapping->columns as $column) {  // ColumnMatch: column, header, field, score, confidence
    echo "{$column->header} -> ".($column->field ?? '-')." ({$column->confidence})\n";
}

$mapping->missingRequiredFields();        // ['name'] when no column holds the name

$confirmed = $mapping->with(3, 'phone')   // map column 3 to phone (with(3, null) clears it)
    ->confirm();

$result = PartnerImport::from($path)->mapping($confirmed)->run();

// config/spreadsheet.php
'templates' => ['store' => 'database', 'table' => 'spreadsheet_mapping_templates'],

PartnerImport::from($path)->mapping($confirmed)->saveTemplate('Monthly partner list')->run();

'import' => [
    'locales' => ['hu', 'en'],                 // names accepted for countries, languages and enum labels
    'date_formats' => ['Y-m-d', 'Y.m.d.', 'd.m.Y'],
    'boolean' => ['true' => ['yes', 'igen'], 'false' => ['no', 'nem']],
    'synonyms' => ['phone' => ['hu' => ['telefonszám', 'mobil'], '*' => ['tel']]],
    'currency_symbols' => ['Ft' => 'HUF', '€' => 'EUR'],
    'aliases' => ['country' => ['holland' => 'NL'], 'currency' => ['forint' => 'HUF'], 'language' => []],
],

use IntrAgile\LaravelSpreadsheet\Normalization\NormalizationContext;
use IntrAgile\LaravelSpreadsheet\Normalization\NormalizedValue;

Field::make('vat_rate', FieldType::Decimal)->normalizeUsing(
    fn (mixed $value, Field $field, NormalizationContext $context): NormalizedValue => is_numeric($value)
        ? NormalizedValue::ok((string) $value)
        : NormalizedValue::error('validation.numeric', ['attribute' => 'vat_rate']),
);

MatchRule::sure('tax')->canonicalizeUsing('tax', 'tax_number');
MatchRule::sure('sku')->canonicalizeUsing('sku', new SkuCanonicalizer);

app(CanonicalizerRegistry::class)->extend('sku', new SkuCanonicalizer);   // register by name

use IntrAgile\LaravelSpreadsheet\Matching\ChildMerger;

public function saved(Model $record, array $values, bool $created): void
{
    (new ChildMerger)->merge(
        $record->contacts(),
        ['name' => $values['name'] ?? null, 'email' => $values['email'] ?? null, 'phone' => $values['phone'] ?? null],
        ['email' => 'email', 'phone' => 'phone'],    // attribute => canonicalizer, highest priority first
    );
}

PartnerImport::from('uploads/partners.xlsx', 's3')
    ->mapping($confirmed)
    ->onConnection('redis')
    ->onQueue('imports')
    ->queue();
bash
php artisan vendor:publish --tag=spreadsheet-config
bash
php artisan vendor:publish --tag=spreadsheet-migrations
php artisan migrate