Largura da coluna de tamanho automático do PHPExcel

100

Estou tentando dimensionar automaticamente as colunas da minha planilha. Estou escrevendo o arquivo e no final tento redimensionar todas as minhas colunas.

// Add some data
$objPHPExcel->setActiveSheetIndex(0)
            ->setCellValue('B1', 'test1111111111111111111111')
            ->setCellValue('C1', 'test1111111111111')
            ->setCellValue('D1', 'test1111111')
            ->setCellValue('E1', 'test11111')
            ->setCellValue('F1', 'test1')
            ->setCellValue('G1', 'test1');

foreach($objPHPExcel->getActiveSheet()->getColumnDimension() as $col) {
    $col->setAutoSize(true);
}
$objPHPExcel->getActiveSheet()->calculateColumnWidths();

O código acima não funciona. Não altera o tamanho da coluna para caber no texto

ATUALIZAR O escritor que estou usando$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');

Alkis Kalogeris
fonte

Respostas:

195

Se uma coluna é definida como AutoSize, o PHPExcel tenta calcular a largura da coluna com base no valor calculado da coluna (assim no resultado de quaisquer fórmulas) e quaisquer caracteres adicionais adicionados por máscaras de formato, como separadores de milhar.

Por padrão, esta é uma estimatedlargura: um método de cálculo mais preciso está disponível, baseado no uso de GD, que também pode lidar com recursos de estilo de fonte, como negrito e itálico; mas isso é uma sobrecarga muito maior, por isso é desativado por padrão. Você pode habilitar o cálculo mais preciso usando

PHPExcel_Shared_Font::setAutoSizeMethod(PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT);

No entanto, o tamanho automático não se aplica a todos os formatos do Writer ... por exemplo, CSV. Você não menciona o escritor que está usando.

Mas você também precisa identificar as colunas para definir as dimensões:

foreach(range('B','G') as $columnID) {
    $objPHPExcel->getActiveSheet()->getColumnDimension($columnID)
        ->setAutoSize(true);
}

$objPHPExcel->getActiveSheet()->getColumnDimension() espera um ID de coluna.

$objPHPExcel->getActiveSheet()->getColumnDimensions()retornará uma matriz de todos os registros de dimensão de coluna definidos; mas, a menos que um registro de dimensão de coluna tenha sido criado explicitamente (talvez carregando um modelo ou chamando manualmente getColumnDimension()), ele não existirá (economia de memória).

Mark Baker
fonte
Muito obrigado. Funciona. Ele não calcula o espaçamento extra criado a partir da fonte em negrito, embora isso seja esperado (eu li em algum lugar). Você poderia atualizar sua resposta para incluir isso também?
Alkis Kalogeris
1
Se você precisa desse grau de precisão com estilo de fonte, como negrito ou itálico, então você precisa usar PHPExcel_Shared_Font :: AUTOSIZE_METHOD_EXACT, mas é muito mais lento
Mark Baker
Está tudo bem, eu não me importo. Embora eu não saiba como fazer. Estou usando 01simple-download-xls.php da pasta Test. Onde eu adiciono essa linha? Desculpe pela minha total noobness. Acabei de começar a brincar com isso.
Alkis Kalogeris
2
Além disso, se você não quiser iterar por meio de letras de coluna, mas sim de índices, você pode usar o método estático PHPExcel_Cell :: stringFromColumnIndex ($ columnIndex) para obter a letra da coluna
MeatPopsicle
@MarkBaker Existe algum método disponível para fazer com uma única instrução para que possamos definir a largura das colunas fornecidas em uma lista. Atualmente estou usando $ activeSheetObj-> getColumnDimension ('G') -> setWidth (35); as colunas da lista podem ser de qualquer ordem.
Rosa Mystica
55

Se você precisar fazer isso em várias planilhas e várias colunas em cada planilha, veja como você pode iterar por todas elas:

// Auto size columns for each worksheet
foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {

    $objPHPExcel->setActiveSheetIndex($objPHPExcel->getIndex($worksheet));

    $sheet = $objPHPExcel->getActiveSheet();
    $cellIterator = $sheet->getRowIterator()->current()->getCellIterator();
    $cellIterator->setIterateOnlyExistingCells(true);
    /** @var PHPExcel_Cell $cell */
    foreach ($cellIterator as $cell) {
        $sheet->getColumnDimension($cell->getColumn())->setAutoSize(true);
    }
}
MrUpsidown
fonte
7
Esta é a melhor solução, uma vez que não requer uma consideração especial para colunas após Z.
Anthony
2
Posso confirmar que essa resposta funciona perfeitamente no PhpSpreadSheet também. Muito obrigado!
Hissvard,
23

Aqui está uma variante mais flexível baseada na postagem de @Mark Baker:

foreach (range('A', $phpExcelObject->getActiveSheet()->getHighestDataColumn()) as $col) {
        $phpExcelObject->getActiveSheet()
                ->getColumnDimension($col)
                ->setAutoSize(true);
    } 

Espero que isto ajude ;)

Todor Todorov
fonte
14
Isso só funciona até Z, porque range('A', 'AB')retornará apenas um item chamado 'A'. Portanto, usar range()neste caso NÃO é uma boa ideia!
Michael
7
No entanto, isso funciona: for ($ i = 'A'; $ i! = $ PhpExcelObject-> getActiveSheet () -> getHighestColumn (); $ i ++) {$ worksheet-> getColumnDimension ($ i) -> setAutoSize (TRUE); }
Nathan
14
for ($i = 'A'; $i !=  $objPHPExcel->getActiveSheet()->getHighestColumn(); $i++) {
    $objPHPExcel->getActiveSheet()->getColumnDimension($i)->setAutoSize(TRUE);
}
Nathan
fonte
2
boa resposta, mas deveria ser $i <= $objPHPExcel->getActiveSheet()->getHighestColumn()caso contrário, a última coluna não
aumenta
10

Este é um exemplo de como usar todas as colunas da planilha:

$sheet = $PHPExcel->getActiveSheet();
$cellIterator = $sheet->getRowIterator()->current()->getCellIterator();
$cellIterator->setIterateOnlyExistingCells( true );
/** @var PHPExcel_Cell $cell */
foreach( $cellIterator as $cell ) {
        $sheet->getColumnDimension( $cell->getColumn() )->setAutoSize( true );
}
dmi3x
fonte
3
Adicione algum contexto em torno de sua resposta para explicar como ela resolve o problema
Andrew Stubbs
6

Este snippet de código dimensionará automaticamente todas as colunas que contêm dados em todas as planilhas. Não há necessidade de usar getter e setter activeSheet.

// In my case this line didn't make much of a difference
PHPExcel_Shared_Font::setAutoSizeMethod(PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT);
// Iterating all the sheets
/** @var PHPExcel_Worksheet $sheet */
foreach ($objPHPExcel->getAllSheets() as $sheet) {
    // Iterating through all the columns
    // The after Z column problem is solved by using numeric columns; thanks to the columnIndexFromString method
    for ($col = 0; $col <= PHPExcel_Cell::columnIndexFromString($sheet->getHighestDataColumn()); $col++) {
        $sheet->getColumnDimensionByColumn($col)->setAutoSize(true);
    }
}
Ronnie
fonte
6

para planilha phps:

$sheet = $spreadsheet->getActiveSheet(); // $spreadsheet is instance of PhpOffice\PhpSpreadsheet\Spreadsheet

foreach (
    range(
         1, 
         Coordinate::columnIndexFromString($sheet->getHighestColumn(1))
    ) as $column
) {
    $sheet
          ->getColumnDimension(Coordinate::stringFromColumnIndex($column))
          ->setAutoSize(true);
}
beck kuo
fonte
foreach (range('A', $sheet->getHighestDataColumn()) as $column) {$sheet->getColumnDimension($column)->setAutoSize(true);}
Wesley Abbenhuis
1
@WesleyAbbenhuis seu comentário só funcionará quando não houver mais de 26 colunas. Quando a coluna mais alta é, por exemplo: 'AH', a função de intervalo não funcionará corretamente.
Sander Van Keer
3
foreach(range('B','G') as $columnID)
{
    $objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setAutoSize(true);
}
Sadikhasan
fonte
3

No caso de alguém estar procurando por isso.

A resolução abaixo também funciona em PHPSpreadsheetsua nova versão do PHPExcel.

// assuming $spreadsheet is instance of PhpOffice\PhpSpreadsheet\Spreadsheet
// assuming $worksheet = $spreadsheet->getActiveSheet();
foreach(range('A',$worksheet->getHighestColumn()) as $column) {
    $spreadsheet->getColumnDimension($column)->setAutoSize(true);
}

Nota: getHighestColumn()pode ser substituído por getHighestDataColumn()ou a última coluna real.

O que esses métodos fazem:

getHighestColumn($row = null) - Obtenha a coluna mais alta da planilha.

getHighestDataColumn($row = null) - Obtenha a coluna de planilha mais alta que contém dados.

getHighestRow($column = null) - Obtenha a linha de planilha mais alta

getHighestDataRow($column = null) - Obtenha a linha mais alta da planilha que contém dados.

Gabi Dj
fonte
2

Se você tentar iterar com for ($col = 2; $col <= 'AC'; ++ $col){...}, ou com foreach(range('A','AC') as $col) {...}ele funcionará para colunas de A a Z, mas falhará, passe o Z (Ex. Iterar entre 'A' para 'AC').

Para iterar a passagem 'Z', você precisa converter a coluna para inteiro, incrementar, comparar e obtê-la como string novamente:

$MAX_COL = $sheet->getHighestDataColumn();
$MAX_COL_INDEX = PHPExcel_Cell::columnIndexFromString($MAX_COL);
    for($index=0 ; $index <= $MAX_COL_INDEX ; $index++){
    $col = PHPExcel_Cell::stringFromColumnIndex($index);

    // do something, like set the column width...
    $sheet->getColumnDimension($col)->setAutoSize(TRUE);
}

Com isso, você pode iterar facilmente, passar a coluna 'Z' e definir o tamanho automático para cada coluna.

Alejandro Silva
fonte
1

Chegue tarde, mas depois de pesquisar em todos os lugares, criei uma solução que parece ser "a única".

Sabendo que existe um iterador de coluna nas últimas versões da API, mas não sabendo como reajustar o próprio objeto de coluna, basicamente criei um loop para ir da primeira coluna real usada para a última coluna real usada.

Aqui vai:

//Just before saving de Excel document, you do this:

PHPExcel_Shared_Font::setAutoSizeMethod(PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT);

//We get the util used space on worksheet. Change getActiveSheet to setActiveSheetIndex(0) to choose the sheet you want to autosize. Iterate thorugh'em if needed.
//We remove all digits from this string, which cames in a form of "A1:G24".
//Exploding via ":" to get a 2 position array being 0 fisrt used column and 1, the last used column.
$cols = explode(":", trim(preg_replace('/\d+/u', '', $objPHPExcel->getActiveSheet()->calculateWorksheetDimension())));

$col = $cols[0]; //first util column with data
$end = ++$cols[1]; //last util column with data +1, to use it inside the WHILE loop. Else, is not going to use last util range column.
while($col != $end){
    $objPHPExcel->getActiveSheet()->getColumnDimension($col)->setAutoSize(true);

    $col++;
}

//Saving.
$objWriter->save('php://output');
Trabalhador da Luz
fonte
1

você também precisa identificar as colunas para definir as dimensões:

foreach (range('A', $phpExcelObject->getActiveSheet()->getHighestDataColumn()) as $col) {
$phpExcelObject
        ->getActiveSheet()
        ->getColumnDimension($col)
        ->setAutoSize(true);
}
Bhavik Hirani
fonte
1
$col = 'A';
while(true){
    $tempCol = $col++;
    $objPHPExcel->getActiveSheet()->getColumnDimension($tempCol)->setAutoSize(true);
    if($tempCol == $objPHPExcel->getActiveSheet()->getHighestDataColumn()){
        break;
    }
}
Prashant Khanderia
fonte
5
Reformate sua resposta e pense no seguinte: Uma boa resposta sempre terá uma explicação do que foi feito e por que foi feito dessa maneira, não apenas para o OP, mas para futuros visitantes do SO.
B001 ᛦ
1

Para Spreedsheet + PHP 7, você deve escrever em vez de PHPExcel_Cell::columnIndexFromString, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString. E no loop é um erro, aí você <não deve trabalhar <=. Caso contrário, ele leva uma coluna muito para o loop.

GSI One
fonte
1
// Auto-size columns for all worksheets
foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
    foreach ($worksheet->getColumnIterator() as $column) {
        $worksheet
            ->getColumnDimension($column->getColumnIndex())
            ->setAutoSize(true);
    } 
}
Gyrocode.com
fonte