spout icon indicating copy to clipboard operation
spout copied to clipboard

Enable est column width calculation

Open xwiz opened this issue 3 years ago • 3 comments

This is a first step to resolving https://github.com/box/spout/issues/129

This approach primarily computes the width size by using an estimate created

After the PR, the library may be used as follows (sample outputs are attached below):

<?php

use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Box\Spout\Common\Type;

require __DIR__ . '/vendor/autoload.php';

function generateRows()
{
    $data = [];
    $headers = [];
    for($i=0;$i<10;$i++) {
        $headers[] = "COL-".generateRandomString(5);
    }
    
    $data = [
        $headers
    ];
    
    for($i=0; $i< 10; $i++) {
        $row = [];
        $rand = mt_rand(1, 30);
        foreach ($headers as $header) {
            $randLen = mt_rand(1, $rand);
            $row[] = generateRandomString($randLen);
        }
        $data[] = $row;
    }
    return $data;
}

function generateRandomString($length = 10) {
    $characters = 'aaaaeeeeiiiiiiiioooouuuubcdefghijklmnopqrstuvwxyz';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

$data = generateRows();

$writer = WriterEntityFactory::createWriter(Type::ODS);
$writer->setWidthCalculation(1);
$writer->openToFile('spouter.ods');

foreach ($data as $row) {
    $writer->addRow(WriterEntityFactory::createRowFromArray($row));
}

$writer->close();

?>

spouter.xlsx spouter.ods

xwiz avatar Feb 04 '22 22:02 xwiz

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar Feb 04 '22 22:02 CLAassistant

@adrilo I noticed two tests are failing and it seems the test has an error... The two particular resource files involved are generated from a unix environment instead of the current environment.. I think those two files should be dynamically generated to ensure they are compatible with the particular environment..

Meanwhile I've attached further examples of using fixed width style calculation below..

<?php

use Box\Spout\Common\Type;
use Box\Spout\Writer\Common\Creator\Style\StyleBuilder;
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;

require __DIR__ . '/vendor/autoload.php';

function generateRows()
{
    $data = [];
    $headers = [];
    for($i=0;$i<10;$i++) {
        $n = $i+1;
        $headers[] = "COL-$n";
    }
    
    $data = [
        $headers
    ];
    
    for($i=0; $i< 10; $i++) {
        $row = [];
        $rand = mt_rand(1, 30);
        foreach ($headers as $header) {
            $randLen = mt_rand(1, $rand);
            $row[] = generateRandomString($randLen);
        }
        $data[] = $row;
    }
    return $data;
}

function generateRandomString($length = 10) {
    $characters = 'aaaaeeeeiiiiiiiioooouuuubcdefghijklmnopqrstuvwxyz';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

$data = generateRows();
$defaultStyle = (new StyleBuilder())
    ->setFontSize(36)
    ->build();
$boldtyle = (new StyleBuilder())
    ->setFontSize(42)
    ->setFontBold()
    ->build();
//$writer = WriterEntityFactory::createWriter(Type::ODS);
$writer = WriterEntityFactory::createWriter(Type::XLSX);
$writer->setWidthCalculation(2)->setDefaultRowStyle($defaultStyle)->openToFile('spoutw.xlsx');
//$writer->openToFile('spouter.xlsx');

foreach ($data as $i => $row) {
    if ($i == 0) {
        $writer->addRow(WriterEntityFactory::createRowFromArray($row, $boldtyle));
    } else {
        $writer->addRow(WriterEntityFactory::createRowFromArray($row));
    }
}

$writer->close();

spoutw.xlsx spoutw.ods

xwiz avatar Feb 05 '22 10:02 xwiz

Hi, instead of overwriting dummy portion of the end file, just like ODS already did it with https://github.com/openspout/openspout/pull/45 now also XLSX writes the rows in a temporary file and only after that it writes all the remaining data, thanks to the speed of stream_copy_to_stream.

So now column with, alongside auto-sizing, could be easily supported and already achievable by user code without affecting performances :rocket:

Slamdunk avatar Mar 23 '22 09:03 Slamdunk