PHPExcel szerokość kolumny automatycznego rozmiaru

101

Próbuję automatycznie zmienić rozmiar kolumn w moim arkuszu. Piszę plik i na koniec próbuję zmienić rozmiar wszystkich moich kolumn.

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

Powyższy kod nie działa. Nie zmienia rozmiaru kolumny w celu dopasowania do tekstu

AKTUALIZACJA Pisarz, którego używam$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');

Alkis Kalogeris
źródło

Odpowiedzi:

195

Jeśli kolumna jest ustawiona na AutoSize, PHPExcel próbuje obliczyć szerokość kolumny na podstawie obliczonej wartości kolumny (a więc na podstawie wyników dowolnych formuł) oraz wszelkich dodatkowych znaków dodanych przez maski formatu, takie jak separatory tysięcy.

Domyślnie jest to estimatedszerokość: dostępna jest dokładniejsza metoda obliczania, oparta na użyciu GD, który może również obsługiwać cechy stylu czcionki, takie jak pogrubienie i kursywa; ale jest to znacznie większe obciążenie, więc jest domyślnie wyłączone. Możesz włączyć dokładniejsze obliczenia za pomocą

PHPExcel_Shared_Font::setAutoSizeMethod(PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT);

Jednak autosize nie dotyczy wszystkich formatów Writer ... na przykład CSV. Nie wspominasz, jakiego pisarza używasz.

Ale musisz też zidentyfikować kolumny, aby ustawić wymiary:

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

$objPHPExcel->getActiveSheet()->getColumnDimension() oczekuje identyfikatora kolumny.

$objPHPExcel->getActiveSheet()->getColumnDimensions()zwróci tablicę wszystkich zdefiniowanych rekordów wymiarów kolumny; ale jeśli rekord wymiaru kolumny nie został jawnie utworzony (na przykład przez załadowanie szablonu lub ręczne wywołanie getColumnDimension()), to nie będzie istniał (oszczędzanie pamięci).

Mark Baker
źródło
Dziękuję bardzo. To działa. Nie oblicza dodatkowych odstępów utworzonych z pogrubionej czcionki, chociaż jest to oczekiwane (gdzieś to czytałem). Czy możesz zaktualizować swoją odpowiedź, aby to również uwzględnić?
Alkis Kalogeris
1
Jeśli potrzebujesz tego stopnia precyzji w stylu kroju, takim jak pogrubienie lub kursywa, musisz użyć PHPExcel_Shared_Font :: AUTOSIZE_METHOD_EXACT, ale jest o wiele wolniejszy
Mark Baker
W porządku, nie obchodzi mnie to. Chociaż nie wiem, jak to zrobić. Używam 01simple-download-xls.php z folderu Test. Gdzie dodać tę linię? Przepraszam za mój całkowity brak. Właśnie zacząłem się tym bawić.
Alkis Kalogeris
2
Ponadto, jeśli nie chcesz iterować za pomocą liter kolumn, ale zamiast tego indeksów, możesz użyć statycznej metody PHPExcel_Cell :: stringFromColumnIndex ($ columnIndex), aby uzyskać literę kolumny
MeatPopsicle
@MarkBaker Czy jest jakaś metoda, którą można zrobić z pojedynczym poleceniem, abyśmy mogli ustawić szerokość kolumn podanych na liście. Obecnie używam $ activeSheetObj-> getColumnDimension ('G') -> setWidth (35); kolumny na liście mogą mieć dowolną kolejność.
Rosa Mystica,
55

Jeśli musisz to zrobić na wielu arkuszach i wielu kolumnach w każdym arkuszu, oto jak możesz iterować je wszystkie:

// 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
źródło
7
Jest to lepsze rozwiązanie, ponieważ nie wymaga specjalnego uwzględnienia dla kolumn za Z.
Anthony
2
Mogę potwierdzić, że ta odpowiedź działa bezbłędnie również w PhpSpreadSheet. Wielkie dzięki!
Hissvard
Użyj, $worksheet->getColumnIterator()aby uprościć tutaj. Zobacz moją odpowiedź
BARNZ
23

Tutaj bardziej elastyczny wariant oparty na poście @Mark Baker:

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

Mam nadzieję że to pomoże ;)

Todor Todorov
źródło
14
Działa to tylko do Z, ponieważ range('A', 'AB')zwróci tylko jeden element o nazwie „A”. Więc używanie range()w tym przypadku NIE jest dobrym pomysłem!
Michael
7
Działa to jednak: for ($ i = 'A'; $ i! = $ PhpExcelObject-> getActiveSheet () -> getHighestColumn (); $ i ++) {$ workheet-> getColumnDimension ($ i) -> setAutoSize (TRUE); }
Nathan
Nie używaj tego. Proszę zobaczyć moją odpowiedź, która używa$sheet->getColumnIterator()
BARNZ
15
for ($i = 'A'; $i !=  $objPHPExcel->getActiveSheet()->getHighestColumn(); $i++) {
    $objPHPExcel->getActiveSheet()->getColumnDimension($i)->setAutoSize(TRUE);
}
Nathan
źródło
3
dobra odpowiedź, ale w $i <= $objPHPExcel->getActiveSheet()->getHighestColumn()przeciwnym razie ostatnia kolumna nie ma rozmiaru
billynoah
10

Oto przykład użycia wszystkich kolumn z arkusza:

$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
źródło
3
Dodaj kontekst do swojej odpowiedzi, aby wyjaśnić, w jaki sposób rozwiązuje problem
Andrew Stubbs,
6

Ten fragment kodu automatycznie dopasuje rozmiar wszystkich kolumn zawierających dane we wszystkich arkuszach. Nie ma potrzeby używania metody pobierającej i ustawiającej 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
źródło
6

dla arkusza 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
źródło
foreach (range('A', $sheet->getHighestDataColumn()) as $column) {$sheet->getColumnDimension($column)->setAutoSize(true);}
Wesley Abbenhuis
1
@WesleyAbbenhuis Twój komentarz będzie działał tylko wtedy, gdy nie będzie więcej niż 26 kolumn. Gdy najwyższa kolumna to na przykład „AH”, funkcja zakresu nie będzie działać poprawnie.
Sander Van Keer
3

Na wypadek, gdyby ktoś tego szukał.

Poniższa rozdzielczość działa również na PHPSpreadsheetich nowej wersji 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);
}

Uwaga: getHighestColumn()można zastąpić getHighestDataColumn()ostatnią rzeczywistą kolumną.

Co robią te metody:

getHighestColumn($row = null) - Uzyskaj najwyższą kolumnę arkusza.

getHighestDataColumn($row = null) - Uzyskaj najwyższą kolumnę arkusza zawierającą dane.

getHighestRow($column = null) - Uzyskaj najwyższy wiersz arkusza

getHighestDataRow($column = null) - Uzyskaj najwyższy wiersz arkusza, który zawiera dane.

Gabi Dj
źródło
2
foreach(range('B','G') as $columnID)
{
    $objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setAutoSize(true);
}
Sadikhasan
źródło
2

Jeśli spróbujesz wykonać iterację z for ($col = 2; $col <= 'AC'; ++ $col){...}lub z foreach(range('A','AC') as $col) {...}nią, będzie działać dla kolumn od A do Z, ale nie powiedzie się, aby przejść do Z (np. Iteracja między „A” a „AC”).

Aby iterować przebieg `` Z '', musisz przekonwertować kolumnę na liczbę całkowitą, zwiększyć, porównać i ponownie uzyskać jako ciąg:

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

Dzięki temu możesz łatwo przejść przez kolumnę „Z” i ustawić autosize dla każdej kolumny.

Alejandro Silva
źródło
1

Przyjdź późno, ale po przeszukaniu wszędzie stworzyłem rozwiązanie, które wydaje się być „tym jedynym”.

Wiedząc, że w ostatnich wersjach API istnieje iterator kolumn, ale nie wiedząc, jak dostosować sam obiekt kolumny, w zasadzie stworzyłem pętlę, aby przejść od prawdziwej pierwszej używanej kolumny do rzeczywistej, ostatnio używanej.

Oto jest:

//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');
Lightworker
źródło
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
źródło
0

musisz również zidentyfikować kolumny, aby ustawić wymiary:

foreach (range('A', $phpExcelObject->getActiveSheet()->getHighestDataColumn()) as $col) {
$phpExcelObject
        ->getActiveSheet()
        ->getColumnDimension($col)
        ->setAutoSize(true);
}
Bhavik Hirani
źródło
0
$col = 'A';
while(true){
    $tempCol = $col++;
    $objPHPExcel->getActiveSheet()->getColumnDimension($tempCol)->setAutoSize(true);
    if($tempCol == $objPHPExcel->getActiveSheet()->getHighestDataColumn()){
        break;
    }
}
Prashant Khanderia
źródło
5
Sformatuj ponownie swoją odpowiedź i zastanów się nad tym: Dobra odpowiedź zawsze będzie zawierała wyjaśnienie, co zostało zrobione i dlaczego zostało zrobione w taki sposób, nie tylko dla PO, ale dla przyszłych gości SO.
B001 ᛦ
0

Dla Spreedsheet + PHP 7, musisz napisać zamiast PHPExcel_Cell::columnIndexFromString, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString. A na pętli jest błąd, nie możesz <z nim pracować <=. W przeciwnym razie zbyt mocno weźmie kolumnę do pętli.

GSI One
źródło
0

Wszystkie te odpowiedzi są do dupy ... nie używaj zakresu (), to nie zadziała poza kolumną Z.

Po prostu użyj:

$sheet = $spreadsheet->getActiveSheet();
foreach ($sheet->getColumnIterator() as $column) {
    $sheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true);
}

Zrób to po zapisaniu danych, aby iterator kolumn wiedział, ile kolumn ma wykonać iteracja.

BARNZ
źródło