PHPExcel ancho de columna de tamaño automático

100

Estoy intentando ajustar automáticamente el tamaño de las columnas de mi hoja. Estoy escribiendo el archivo y al final trato de cambiar el tamaño de todas mis columnas.

// 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();

El código anterior no funciona. No cambia el tamaño de la columna para que se ajuste al texto.

ACTUALIZAR El escritor que estoy usando$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');

Alkis Kalogeris
fuente

Respuestas:

195

Si una columna se establece en AutoSize, PHPExcel intenta calcular el ancho de la columna basándose en el valor calculado de la columna (por lo tanto, en el resultado de cualquier fórmula) y cualquier carácter adicional agregado por máscaras de formato, como miles de separadores.

Por defecto, este es un estimatedancho: hay disponible un método de cálculo más preciso, basado en el uso de GD, que también puede manejar características de estilo de fuente como negrita y cursiva; pero esta es una sobrecarga mucho mayor, por lo que está desactivada de forma predeterminada. Puede habilitar el cálculo más preciso usando

PHPExcel_Shared_Font::setAutoSizeMethod(PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT);

Sin embargo, el tamaño automático no se aplica a todos los formatos de Writer ... por ejemplo, CSV. No mencionas qué escritor estás usando.

Pero también necesita identificar las columnas para establecer dimensiones:

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

$objPHPExcel->getActiveSheet()->getColumnDimension() espera una ID de columna.

$objPHPExcel->getActiveSheet()->getColumnDimensions()devolverá una matriz de todos los registros de dimensión de columna definidos; pero a menos que se haya creado explícitamente un registro de dimensión de columna (tal vez cargando una plantilla o llamando manualmente getColumnDimension()), no existirá (ahorro de memoria).

Mark Baker
fuente
Muchas gracias. Funciona. No calcula el espacio adicional creado a partir de la fuente en negrita, aunque eso es lo esperado (lo he leído en alguna parte). ¿Podrías actualizar tu respuesta para incluir eso también?
Alkis Kalogeris
1
Si necesita ese grado de precisión con un estilo de letra como negrita o cursiva, entonces necesita usar PHPExcel_Shared_Font :: AUTOSIZE_METHOD_EXACT, pero es mucho más lento
Mark Baker
Está bien, no me importa. Aunque no sé cómo hacerlo. Estoy usando 01simple-download-xls.php de la carpeta Prueba. ¿Dónde agrego esa línea? Perdón por mi completa noobness. Acabo de empezar a jugar con eso.
Alkis Kalogeris
2
Además, si no desea iterar a través de letras de columna sino índices, puede usar el método estático PHPExcel_Cell :: stringFromColumnIndex ($ columnIndex) para obtener la letra de columna
MeatPopsicle
@MarkBaker ¿Existe algún método disponible para hacer con una sola declaración para que podamos establecer el ancho de las columnas dadas en una lista? Actualmente estoy usando $ activeSheetObj-> getColumnDimension ('G') -> setWidth (35); las columnas de la lista pueden ser de cualquier orden.
Rosa Mystica
55

Si necesita hacer eso en varias hojas y varias columnas en cada hoja, así es como puede iterar a través de todas ellas:

// 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
fuente
7
Esta es la mejor solución, ya que no requiere una consideración especial para las columnas después de Z.
Anthony
2
Puedo confirmar que esta respuesta también funciona perfectamente en PhpSpreadSheet. ¡Gracias una tonelada!
Hissvard
23

Aquí una variante más flexible basada en la publicación de @Mark Baker:

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

Espero que esto ayude ;)

Todor Todorov
fuente
14
Esto solo funciona hasta Z, porque range('A', 'AB')solo devolverá un artículo llamado 'A'. ¡Entonces usarlo range()en este caso NO es una buena idea!
Michael
7
Sin embargo, esto funciona: para ($ 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
fuente
2
buena respuesta, pero debería ser de lo $i <= $objPHPExcel->getActiveSheet()->getHighestColumn()contrario la última columna no se dimensiona
billynoah
10

Este es un ejemplo de cómo usar todas las columnas de la hoja de trabajo:

$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
fuente
3
Agregue algo de contexto alrededor de su respuesta para explicar cómo resuelve el problema
Andrew Stubbs
6

Este fragmento de código ajustará automáticamente el tamaño de todas las columnas que contienen datos en todas las hojas. No es necesario utilizar el getter y 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
fuente
6

para phpspreadsheet:

$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
fuente
foreach (range('A', $sheet->getHighestDataColumn()) as $column) {$sheet->getColumnDimension($column)->setAutoSize(true);}
Wesley Abbenhuis
1
@WesleyAbbenhuis su comentario solo funcionará cuando no haya más de 26 columnas. Cuando la columna más alta es, por ejemplo: 'AH', la función de rango no funcionará correctamente.
Sander Van Keer
3
foreach(range('B','G') as $columnID)
{
    $objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setAutoSize(true);
}
Sadikhasan
fuente
3

En caso de que alguien estuviera buscando esto.

La resolución a continuación también funciona en PHPSpreadsheetsu nueva versión de 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()se puede reemplazar con getHighestDataColumn()o con la última columna real.

Qué hacen estos métodos:

getHighestColumn($row = null) - Obtener la columna más alta de la hoja de trabajo.

getHighestDataColumn($row = null) - Obtenga la columna de la hoja de trabajo más alta que contiene datos.

getHighestRow($column = null) - Obtener la fila más alta de la hoja de trabajo

getHighestDataRow($column = null) - Obtenga la fila más alta de la hoja de trabajo que contiene datos.

Dj Gabi
fuente
2

Si intenta iterar con for ($col = 2; $col <= 'AC'; ++ $col){...}, o conforeach(range('A','AC') as $col) {...} , funcionará para las columnas de la A a la Z, pero no pasa la Z (por ejemplo, iterar entre 'A' y 'AC').

Para iterar el pase 'Z', debe convertir la columna a un número entero, incrementar, comparar y obtener como cadena nuevamente:

$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);
}

Con esto, puede iterar fácilmente pasar la columna 'Z' y configurar el tamaño automático para cada columna.

Alejandro Silva
fuente
1

Llego tarde, pero después de buscar por todas partes, he creado una solución que parece ser "la indicada".

Sabiendo que hay un iterador de columna en las últimas versiones de la API, pero sin saber cómo ajustar el objeto de la columna en sí, básicamente he creado un bucle para pasar de la primera columna utilizada real a la última utilizada real.

Aquí va:

//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');
Trabajador de la luz
fuente
1

también necesita identificar las columnas para establecer dimensiones:

foreach (range('A', $phpExcelObject->getActiveSheet()->getHighestDataColumn()) as $col) {
$phpExcelObject
        ->getActiveSheet()
        ->getColumnDimension($col)
        ->setAutoSize(true);
}
Bhavik Hirani
fuente
1
$col = 'A';
while(true){
    $tempCol = $col++;
    $objPHPExcel->getActiveSheet()->getColumnDimension($tempCol)->setAutoSize(true);
    if($tempCol == $objPHPExcel->getActiveSheet()->getHighestDataColumn()){
        break;
    }
}
Prashant Khanderia
fuente
5
Vuelva a formatear su respuesta y piense en esto: una buena respuesta siempre tendrá una explicación de lo que se hizo y por qué se hizo de esa manera, no solo para el OP sino para los futuros visitantes del SO.
B001 ᛦ
1

Para spreedsheet + PHP 7, se debe escribir en lugar de PHPExcel_Cell::columnIndexFromString, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString. Y en el bucle hay un error, no debe <trabajar con él <=. De lo contrario, se mete demasiado en una columna.

GSI One
fuente
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
fuente