3

ref: https://github.com/PHPOffice/PhpSpreadsheet/issues/1608

What is the expected behavior?

html

Without Events

enter image description here

What is the current behavior?

html

What are the steps to reproduce?

the issue is based on Maatwebsite/Laravel-Excel which internally use PhpSpreadsheet https://github.com/Maatwebsite/Laravel-Excel/issues/2784

<table style="width:100%" border="1">
    <thead>
        <tr>
            // ...
            <th style="text-align: center;" colspan="4">{{ __('Items') }}</th>
            // ...
        </tr>
        <tr>
             // ...
        </tr>
    </thead>

    @foreach ($models->cursor() as $model)
        <tbody>
            <tr>
                // ...

                <td colspan="4">
                    <table style="width:100%">
                        @foreach ($model->relation as $item)
                            <tr>
                                // ...
                            </tr>
                        @endforeach
                    </table>
                </td>

                // ...
            </tr>
        </tbody>
    @endforeach
</table>
// this works perfectly with single headers, but not with sub ones
public function registerEvents(): array
    {
        return [
            AfterSheet::class => function (AfterSheet $event) {
                $sheet = $event->sheet->getDelegate();
                $sheet->getRowDimension(1)->setRowHeight(30);

                $header = $sheet->getStyle('A1:' . $sheet->getHighestDataColumn() . '1');
                $header->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
                $header->getFont()->setBold(true);
                $header->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('00000000');
                $header->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);

                $other = $sheet->getStyle('A2:' . $sheet->getHighestDataColumn() . $sheet->getHighestRow());
                $other->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_TOP);

                foreach ([$header, $other] as $item) {
                    $item->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT);
                    $item->getAlignment()->setWrapText(true);
                }
            },
        ];
    }

any help is appreciated & if u need any more info plz ask.

ctf0
  • 6,991
  • 5
  • 37
  • 46
  • 1
    The issue is the missing header, right? Do you also have issue with the borders/styling as well, since you didn't exactly specify this :) My team has been using Laravel-Excel in one of our app, and we do have multiple header as well without using any Events. [Here's a sample of our blade](https://i.imgur.com/YqytFaW.png). – sykez Aug 26 '20 at 04:18
  • What's the result without your styling event? – Will B. Aug 26 '20 at 04:24
  • @fyrye img added "it also have a couple of extra columns from the original but the issue remains the same" – ctf0 Aug 26 '20 at 04:46
  • @sykez its pretty much like urs except that i have to move the `tbody` inside the loop as well & a new `table` for the extra columns or it wont display as expected. `Do you also have issue with the borders/styling as well` do u mean inside the view (if yes then no, am not having any fancy styles except to center the text inside the columns) – ctf0 Aug 26 '20 at 04:47
  • 1
    @ctf0 I see. Yeah, our layout is pretty similar. I believe we've found the issue then. It's the `tbody` loop I'll add my answer in a bit. Also I noticed that without your Events, your second header is now printed. Perhaps you can continue without events until the layout is fixed. The reason I asked about the borders/styling was because the expected and current behavior had those differences – sykez Aug 26 '20 at 06:57

2 Answers2

1

Sub headers or <tr> inside <thead> is valid HTML and should work fine with PhpSpreadsheet/Laravel-Excel. However, multiple <tbody> isn't valid/legal according to the HTML spec, and nested tables aren't supported by Laravel-Excel.

As I've mentioned in the comments, we've been using Laravel-Excel in our application, which uses a pretty similar layout, and works fine with multiple rows in head. So the real issue is with multiple or nested body. I suggest to follow the approach we've used. You can achieve the same layout with proper rowspan and colspan (we're doing count for calculating that).

Edit:

As requested, here's an example in HTML with sample data according to your layout, and below is the blade view with loops.

<table border="1">
  <thead>
    <tr>
        <th rowspan="2">Client Name</th>
        <th rowspan="2">Total</th>
        <th colspan="4">{{ __('Items') }}</th>
        <th rowspan="2">Creation Date</th>
    </tr>
    <tr>
        <th>Title</th>
        <th>Price</th>
        <th>Quantity</th>
        <th>Total</th>
    </tr>
    </thead>
    <tbody>
    @foreach($customers as $customer)
        @php
            $count = count($customer->items);
            $i = 0;
        @endphp

        @foreach($customer->items as $item)
            <tr>
                @if($i == 0)
                    <td rowspan="{{ $count }}">{{ $customer->name }}</td>
                    <td rowspan="{{ $count }}">{{ $customer->total }}</td>
                @endif

                <td>{{ $item->title }}</td>
                <td>{{ $item->price }}</td>
                <td>{{ $item->qty }}</td>
                <td>{{ $item->total }}</td>
            
                @if($i == 0)
                    <td rowspan="{{ $count }}">{{ $customer->date }}</td>
                @endif
            </tr>
            @php
                $i++;
            @endphp
        @endforeach
    @endforeach
  </tbody>
</table>
ctf0
  • 6,991
  • 5
  • 37
  • 46
sykez
  • 2,015
  • 15
  • 14
  • could u plz add a minimal example with similar table structure as the one in the question ? – ctf0 Aug 26 '20 at 11:15
  • I've updated answer with a bit more than minimal example Cheers – sykez Aug 26 '20 at 12:37
  • 1
    man, u r a life saver, thank u so much "ps: the events have to be used otherwise u will get a misaligned render" – ctf0 Aug 26 '20 at 20:10
0

The bug you are facing now is not related to the library you are using.

You are using an HTML table for each relation item inside a master table containing all the stuff you need to display. It cannot work well because of that. Not all web browsers are supporting bad formed HTML documents, and their supports are varying much from one version to the other one.

Write proper HTML: Use DIVs elements to build an smart visual webpage, and display only the relations inside TABLEs elements, so they will not be partially hidden or misdisplayed as we can see here.

So to structure your HTML, if you use Bootstrap as an example, you can use a row for headers, and a row per item. For each relation item, you can put them inside a table, they will be displayed correctly.

BendaThierry.com
  • 2,080
  • 1
  • 15
  • 17
  • actually i have searched and having a nested headers is a valid html & heres [a quick google to prove my findings](https://www.google.com/search?q=html+table+nested+header&oq=html+table+nested+hea&aqs=chrome.1.69i57j0.4086j0j7&sourceid=chrome&ie=UTF-8) also if it works in the browser without any css or styling and it shows the expected results, then its considered a valid html, right ? – ctf0 Aug 22 '20 at 11:31
  • It is maybe valid the way you are trying to do, but 2 things : 1) you must have a working solution, 2) it displays badly. So trying another way to do the things you need to may put your feet on the right road to success. It will work better I think. – BendaThierry.com Aug 22 '20 at 17:19
  • could u plz add an example for the div solution ? – ctf0 Aug 22 '20 at 20:55
  • It won't work with divs, you must use tables for this. [[Source](https://github.com/Maatwebsite/Laravel-Excel/issues/217#issuecomment-82944745)] – sykez Aug 26 '20 at 07:00