So I'm using PHPExcel to generate spreadsheets with data from a database. I have specific columns set to specific widths. When ever I try to use a default font for the entire spreadsheet though, these widths seem to be ignored and the sheet widens. Am i using this wrong? Where is #Mark Baker?
$objPHPExcel = new PHPExcel();
$phpColor = new PHPExcel_Style_Color();
$phpColor->setRGB('051C48');
$objPHPExcel->getDefaultStyle()->getFont()->setColor($phpColor);
$objPHPExcel->getDefaultStyle()->getFont()->setName('Gotham Book');
$objPHPExcel->getDefaultStyle()->getFont()->setSize(10);
$activeSheet = $objPHPExcel->getActiveSheet();
$activeSheet->setShowGridlines(false);
foreach(range('A','F') as $columnID){
$objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setAutoSize(false);
}
///////////////////////////////// FIRST PHASE /////////////////////////////////////////////////////////
$activeSheet->getColumnDimension('A')->setWidth(22.71);
$activeSheet->getColumnDimension('B')->setWidth(31.71);
$activeSheet->getColumnDimension('C')->setWidth(9.71);
$activeSheet->getColumnDimension('D')->setWidth(9.71);
$activeSheet->getColumnDimension('E')->setWidth(11.85);
$activeSheet->getColumnDimension('F')->setWidth(17.57);
NO DEFAULT FONT SET:
DEFAULT FONT SET:
If you would like any additional information, just let me know. I realize those screenshots may not be the best method for showing whats happening. I can however just set a range for the cells, I was just hoping for cleaner code by setting a default value. Also if I'm being to specific and needy, just ignore me
$activeSheet->getStyle('A1:F1')->applyFromArray($firstRowStyle);
$activeSheet->getStyle('B2:B50')->applyFromArray($gothamBook10);
$activeSheet->getStyle('C2:C50')->applyFromArray($gothamBook10);
$activeSheet->getStyle('D2:D50')->applyFromArray($gothamBook10);
$activeSheet->getStyle('E2:E50')->applyFromArray($gothamBook10);
$activeSheet->getStyle('F2:F50')->applyFromArray($gothamBook10);
Related
I am trying to export some data gathered by webforms, and match it up with one or more files included for each webform. My chosen format is .xls not .xlsx for backwards compatibility.
I've learned here, and on the internet in general, that multiple links IS possible if we use shapes or images/thumbnails to add hyperlinks to, but I can't seem to make it work with PHPSpreadsheet and xls files.
So far I've managed to set hyperlink to individual cells, but I can't seem to make it work on drawings.
Working code for cells:
$coordinates = $sheet->getCellByColumnAndRow($column,$row)->getCoordinate(); // get coordinate like "A1", "B5" etc.
$sheet->setCellValueByColumnAndRow($column,$row,$cellValue); // set link text
$sheet->getStyle($coordinates)->getFont()->setUnderline('single'); // set underline like links have
$sheet->getStyle($coordinates)->getFont()->getColor()->setRGB('#0000FF'); // set default link color
$sheet->getCellByColumnAndRow($column,$row)->getHyperlink()->setUrl('http://www.test.com'); // setting url or local link
This works great, but in my spreadsheet I would like to have multiple links in one cell if there are more than one file sent in by a single user.
Attempt at making it work for drawings:
// create a new drawing object
$drawing = new Drawing();
// set properties
$drawing->setName('Testname');
$drawing->setDescription('Test description');
$drawing->setPath($url); // put your path and image here
$drawing->setCoordinates($coordinates);
$drawing->setOffsetX($width);
$drawing->setHeight($height);
//$drawing->getHyperlink()->setUrl('http://www.test.com'); // error: Call to a member function setUrl() on null
//$drawing->getHyperlink()->setTooltip('tooltip works?'); // error: Call to a member function setTooltip() on null
// Connect drawn image to the spreadsheet
$drawing->setWorksheet($sheet);
The images works great, and I can place multiple images in one cell, but when I try to add hyperlink to each image, PHPSpreadsheet fails me. Are there any other way, perhaps with shapes or other things that I haven't thought about that might do the trick?
And if adding hyperlinks to multiple shapes / images with hyperlinks inside one cell is impossible with standard PHPSpreadsheet, is there a way to force one or more excel functions into one cell, achieving the same thing somehow?
I found a workaround. I answered my own question for future reference and hopefully to help others. :)
The solution was to add a new row for each extra link I needed, and merge all other cells vertically in the columns that was not the link column. This made it possible to seemingly make 2 or more cells inside one cell, not affecting the other columns. E.g. one result that needed 3 links for the file cell, would be taking up 3 rows in the spreadsheet, but all the other columns corresponding to that result would be merged individually vertically, making it look like one row with a file cell containing 3 cells.
Because of the limitation on one link per cell, this is what needed to be done:
require_once '/vendor/autoload.php';
// set folder to unzip the corresponding files
$filesFolder = 'Files';
// Create new Spreadsheet object
$spreadsheet = new Spreadsheet();
// set active sheet
$sheet = $spreadsheet->getActiveSheet();
// get form results data prepped for my .xls file
list($header, $allRows) = getResults(); // privat function setting 2x arrays with info gathered
// set headers
$sheet->fromArray([$header], NULL, 'A1');
$fileFieldIndex = 3; // the column index of the files
$counter = 2; // Start below the headers
foreach($allRows as $row => $innerArray){
// Add some data
$sheet->fromArray([$innerArray], NULL, 'A'.$counter);
// fetching fileinfo
$aFileInfo = getFileInfo(); // privat function setting 2x array with fileinfo corresponding to this specific result
// loop through and add rows for each extra file link
foreach($aFileInfo as $innerRow => $fileInfo) {
if($innerRow>=1){
// on second or more occurrence of files, add extra row
$counter++; // update counter
// Add one row starting at column 'A'
$sheet->fromArray([$innerArray], NULL, 'A'.$counter);
// set link text
$sheet->setCellValueByColumnAndRow($fileFieldIndex,$counter,$fileInfo['filename']);
// get coordinates (using only numbers to get the letter/number combination)
$coordinates = $sheet->getCellByColumnAndRow($fileFieldIndex,$counter)->getCoordinate();
// separate letter-column and number-row
preg_match_all('/(\d)|(\w)/', $coordinates, $matches);
$letterColumnFiles = implode($matches[2]);
// loop through columns
// Get the highest column letter referenced in the worksheet
$highestColumn = $sheet->getHighestColumn();
$prevRow = ($counter-1);
// stop when you reach the highest column
for ($col = 'A'; $col != $highestColumn; ++$col) {
if($col != $letterColumnFiles){
// merge cell with cell above if not the column with the files
$topCell = $col.$prevRow;
$sheet->getStyle($topCell)->getAlignment()->setVertical('top');
$sheet->mergeCells("$topCell:$col$counter");
}
}
// merge highest column too, we wouldn't want to forget this one
$sheet->getStyle($highestColumn.$prevRow)->getAlignment()->setVertical('top');
$sheet->mergeCells("$highestColumn$prevRow:$highestColumn$counter");
}
// get coordinate like "A1", "B5" etc. needed for getStyle
$coordinates = $sheet->getCellByColumnAndRow($fileFieldIndex,$counter)->getCoordinate();
// set underline like links have
$sheet->getStyle($coordinates)->getFont()->setUnderline('single');
// set default link color
$sheet->getStyle($coordinates)->getFont()->getColor()->setRGB('#0000FF');
// setting local link to specified local folder
$sheet->getCellByColumnAndRow($fileFieldIndex,$counter)->getHyperlink()->setUrl($filesFolder.'\\'.$fileInfo['filename']);
}
}
It's possible to auto size the columns but is there a way set the row size automaticaly?
I've searched for it in the oficial docs and didn't found anything for the 3.1 version.
I've also tried the issue on the project's GitHub page, but they instruct you to search help on StackOverflow.
Maybe it's too late to give an answer. But if you or maybe someone else still needs it, I have a solution using PhpOffice~
First, call the Spreadsheet from PhpOffice
use PhpOffice\PhpSpreadsheet\Spreadsheet;
then
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$rowDimension = 2; // <- Row Number
$rowHeight = 40; // <- row height
$sheet->getRowDimension($rowDimension)
->setRowHeight($rowHeight);
You can learn more about basic alignment in their github repository
Problem with PHPSpreadsheet. When I read my own template file and opened the saved one, the template style was applied only to the first row or column, and the rest of the cells became the default style. I want the template style to be applied to all cells.
The executed code is as follows.
$spreadsheet = IOFactory::load('sample.xlsx');
$sheet = $spreadsheet->getActiveSheet();
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save('write.xlsx');
exit();
Maybe not a code issue, but a spreadsheet issue. If you have a similar problem, I'd like to give some advice so I can do it a little.
Thank you.
The styles will not automatically taken from the template. You can set them manually.
Take a look to Documentation.
Not all kind of styles are implemented. Pivot-Tables for example aren't supported. If you use format as table you use an pivot-table and yes this is not supported as well.
After looking over the documentation for Box/Spout I do not see a way to format cells for currency.
NOTE: PhpExcel and PhpSpreadsheet are not an option.
Is there a way to format a cell?
While styling, is there a way to set the width of the cells?
This is my code so far.
It works, but is lacking currency formatting and width:
$writer = WriterFactory::create(Type::XLSX); // for XLSX files
$writer->openToFile($tmpfile); // write data to a file or to a PHP stream
$writer_sheet = $writer->getCurrentSheet();
$writer_sheet->setName($invoiceSheetName);
$headerStyle = (new StyleBuilder())
->setFontBold()
->setFontUnderline()
->build();
// add header with style
$writer->addRowWithStyle($header, $headerStyle);
$writer->addRows($resultsArray); // add multiple rows at a time
$writer->close();
$excelOutput = file_get_contents($tmpfile);
Documentation:
Spout Documentation
Help is greatly appreciated.
Decided to implement my own implementation with unzipping the xlsx file and modifying the correct xml file.
So I am exporting an Excel file I created with PHPExcel to PDF. My only problem is when the content runs over the width of the page (not the length) that content disappears. Only a blank page is created where that content should be. I've tried inserting a column break with a line like this example from the documentation, but only row breaks seem to work with PDF:
$objPHPExcel->getActiveSheet()->setBreak( 'D10' , \PHPExcel_Worksheet::BREAK_COLUMN );
It's worth mentioning I'm working from within a Symfony2 controller, hence the slash in front of the PHPExcel enum.
My ideal solution is to have any extra content run over to a second page that can be placed alongside the first page to show the entire table as it appears in a real Excel document.
This is a limitation of the external library used by PHPExcel to render html output as PDF (namely tcPDF).
While I'm aware of a number of other libraries that can generate PDF from HTML (such as domPdf and mPdf) and future versions of PHPExcel will allow you to select which of these libraries you wish to use, none of them seem capable of generating multiple pages to show data from the full width of a worksheet.
Unless anybody can suggest alternatives, I'm afraid that this will remain a limitation for the foreseeable future.
I was having a similar problem vertically,
the solution i found was to use this
$highestRow = $objPHPExcel->setActiveSheetIndex(0)
->getHighestRow();
$objPHPExcel->setActiveSheetIndex(0)
->getPageSetup()
->setPrintArea("A1:I" . $highestRow )
->setFitToHeight(255);
i would suggest trying something similar with width.
for example :
$highestColumn= $objPHPExcel->setActiveSheetIndex(0)
->getHighestColumn();
$objPHPExcel->setActiveSheetIndex(0)
->getPageSetup()
->setPrintArea("A1:" . $highestColumn . "10" )
->setFitToWidth(255);