Background:
I'm successfully inserting rows of data into a spreadsheet using the following to add text data:
$sheet->fromArray($user, NULL, 'B' . $counter);
And the following to add an image to the beggining of that row:
$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
$drawing->setName('Avatar');
$drawing->setDescription('Avatar');
$drawing->setPath('image.jpg');
$drawing->setCoordinates('A' . $counter);
$drawing->setWidthAndHeight(50, 50);
$drawing->setWorksheet($spreadsheet->getActiveSheet());
This works fine
Problem:
When I then go to sort that data, the data is sorted successfully, but the images stay in their original place.
Question:
How can I ensure when the spreadsheet is sorted, the images move with the row as well?
Related
I need to create an excel table with help of php. Is that possible? The php code below creates and write to an excel file. I would like to create an excel table with the data, see picture below. I'm using PhpSpreadsheet (sorry I forgot to say that)
Edit: The code below uses library PhpSpreadsheet to ceate a excel file with some content.
I want to create an excel table:
The code works and create the content as the second picture below shows. This is NOT an excel table, just plain text in cells.
But that is not what I want. I want to be able to create the content as the first picture below shows. This is an excel table. When you create an excel table by hand you can choose colrs etc. I do not care about the colors. Excel add the column name and push the content down.
What I have tried is to add: $sheet->setAutoFilter('A1:B5'); to the code, but this does not create an excel table as shown in the third picture below.
So the question is: What do I need to add to the code above to be able to create the content as shown in the first picture below
The fourth picture below shows how to crate an excel table in excel (and this is what I want the php code to do)
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', 'A1');
$sheet->setCellValue('A2', 'A2');
$sheet->setCellValue('A3', 'A3');
$sheet->setCellValue('A4', 'A4');
$sheet->setCellValue('A5', 'A5');
//$sheet->setCellValue('A6', 'A6');
$sheet->setCellValue('B1', 'B1');
$sheet->setCellValue('B2', 'B2');
$sheet->setCellValue('B3', 'B3');
$sheet->setCellValue('B4', 'B4');
$sheet->setCellValue('B5', 'B5');
$writer = new Xlsx($spreadsheet);
$writer->save('CreateExcelTable.xlsx');
The picture below show the tableI would like to create
With the code above this is created:
With the code added:
$sheet->setAutoFilter('A1:B5');
The picture below show what is created.It is not a table
Insert/Table is simply a GUI "shortcut" method for styling and setting autofilters against a block of cells. Both of these can be done as individual tasks using PHPSpreadSheet, but the library does not provide a "shortcut" way of doing this with a single method call.
Take a look at section of the Developer documentation.
I have a similar problem.
My Excel Template had some array formulas that refer to Named Data Tables,
(instead of writing in the array formula A2:A150 i would simply write NameOfMyTable[NameOfColumn])
When i inserted some data in my template using PhpSpreadSheet and downloaded the produced excel file, Each instance of NameOfMyTable[NameOfColumn] was replaced with REF!
Instead of searching how make or preserve Named Data Tables while using PHPSpreasheet. I simply converted all my Named tables back to simple ranges. (you can easily do this conversion through TableTools in excel without having to change every formula in your Excel Template).
I have a code I wrote, use it if you want
look at the code
using
$excelExport = new ExcelExport(['name' => 'dılo'], 'file');
$excelExport->download();
shortest excel creation example with php
basic example
<?php
$file="demo.xls";
$test="<table ><tr><td>Cell 1</td><td>Cell 2</td></tr></table>";
header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=$file");
echo $test;
?>
Trying to import data from CSV files using PHP Codeigniter.
The file has column description in which the data entered has some enter or new line within a cell but it does not create a new row in CSV. On the other hand, while importing using php it generates a new row in the loop which is being inserted as a new record in the database.
How to resolve this issue. Picture attached.
$csv_array = $this->csvreader->parse_file($file_path);
foreach ($csv_array as $row) {
$description =$row['description'];
echo '<pre>';
var_dump(($row));
}
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']);
}
}
i'm trying to use fdpf with php to generate a pdf file with patient automatic reports system
so after getting all patient info from DB .. i'm trying to print report image from directory
$id=$user_id;
$dir="./user_reports/$id";
opendir("$dir");
$fi = new FilesystemIterator($dir, FilesystemIterator::SKIP_DOTS);
$report_img=array();
for($k=1;$k<=iterator_count($fi);$k++) // iterator_count to count files in folder
{
$report_img[$k]="$dir/$id.jpg";
$id++;
}
and this is to print info.
for($x=1;$x<=$i;$x++)
{
$image=$report_img[$x];
$pdf->Cell( 40, 40, $pdf->Image($image,70,190,-300), 0, 0, 'L', false );
}
after all .. it doesn't work :(
any ideas?
You are assuming $pdf->Image($image,70,190,-300) returns a string which you can put in a cell. This is not so. Try this:
for($x=1;$x<=$i;$x++)
{
$image=$report_img[$x];
$pdf->Image($image,70,190,300);
}
I left out the cell, because it doesn't do anything. I used a positive width for the image.
I'm sure this doesn't do what you want. That's unclear at this point, but it shouldn't generate an error 500 anymore, as long as the images exist.
Generating a PDF file like this is nothing like working with HTML. You're probably thinking of HTML table cells.
In the case you want to print something, you can work with just HTML. It is now possible to make pages in HTML and set the true dimensions when printing with styles. See: https://www.w3.org/TR/css3-page/#page-size
That could be a much better solution for you, since you seem to know HTML. It wouldn't work if it is actually the PDF file you want.
actualy this for saving huge data to excel file, but excel have limitation for storing data for each row, i wanna make a few sheet acording to data row, here is the problem, say that i have 1000 data in database, and i wanna make it splited by 500 for each and put in to first sheet, how do we make that happen ?, i have tried with following code
$this->load->library('excel');
$this->excel->setActiveSheetIndex(0);
$this->excel->getActiveSheet()->setCellValue('A1','NAME');
for($i=1; $i<=1000; $i++){
if($i>=500){
#save first 500 data to first sheet and then continue for the rest to 2nd sheet
}
$this->excel->getActiveSheet()
->setCellValue("A$i",$i);
}
i wanna make for each sheet saved 500 data, is it possible to make it happen?
Basically something like this:
$inserted = 0;
for(...) {
$inserted++;
if ($inserted % 500 == 0) {
start new sheet
}
}
keep a counter. whenever the counter reaches a multiple of 500, start a new sheet, and start inserting into that.