Getting data validation to work with PhpSpreadsheet - laravel

I'm using laravel and I need to convert my array into a string so that I can add it to the phpSpreadsheet validation. So that when I download an excel spreadsheet
I can select a list of products. The problem I'm having is that I can't get it to be the format that is needed.
Here is the documentation PhpSpreadsheet
The correct format is
$validation->setFormula1('"Item A,Item B,Item C"');
Here is my code
public function generate()
{
$this->spreadsheet = new Spreadsheet;
$validation = $this->spreadsheet->getActiveSheet()->getCell('B5')->getDataValidation();
$validation->setType( DataValidation::TYPE_LIST );
$validation->setErrorStyle( DataValidation::STYLE_INFORMATION );
$validation->setAllowBlank(false);
$validation->setShowInputMessage(true);
$validation->setShowErrorMessage(true);
$validation->setShowDropDown(true);
$validation->setErrorTitle('Input error');
$validation->setError('Value is not in list.');
$validation->setPromptTitle('Pick from list');
$validation->setPrompt('Please pick a value from the drop-down list.');
$products = Product::all();
$product_list = [];
foreach($products as $product)
{
$product_name = $product->name;
array_push($product_list, $product_name);
}
$validation->setFormula1($product_list);
}
I tried a json_encode(), but it seems that excel doesn't like that.

Based on the documentation $product_list should be a comma delimited string not an array.
$products = Product::all();
$product_list = '';
foreach($products as $product) {
$product_name = $product->name;
$product_list .= '"' . $product_name . '",';
}
$validation->setFormula1(rtrim($product_list,','));

$validation4->setFormula1(implode(','), $product_list);
must be string right or formula range cell like =$A;
some value can find when you try make data validation list type on excel, you use that on your program.

Related

Creating a Dynamic PDF and Saving it in a folder using Loop with MYSQL and Codeigniter

This is the public function with looping (Edited)
public function generate_salary_slip(){
$this->load->helper('file');
$this->load->library('m_pdf');
$data = [];
$slip = $this->Admin_Login_Model->generate_salary_slip();
//$html = array();
$html='';
if(!empty($slip)){
foreach($slip as $slip_list){
$id = $slip_list->emp_id;
$data['attendance'] = $this->Admin_Login_Model->get_slip_attendance($id);
$data['emp_profile'] = $this->Admin_Login_Model->get_emp_details($id);
$data['late_day'] = $this->Admin_Login_Model->get_late_days($id);
$data['half_days'] = $this->Admin_Login_Model->get_half_days($id);
$data['salary'] = $this->Admin_Login_Model->get_salary_slip($id);
$data['second_half'] = $this->Admin_Login_Model->get_half_Second_days($id);
//$html=$this->load->view('admin/payslip',$data);
$pdfFilePath = date("F_Y")."salary_slip.pdf";
$html .= $this->load->view('admin/payslip', $data, true);
}
$htmlval = $html;
//echo $html;exit;
$this->m_pdf->pdf->WriteHTML($htmlval);
$this->m_pdf->pdf->Output('salary_slips/'.$pdfFilePath, "F");
$this->session->set_flashdata('success','Salary slips saved in directory!');
redirect('admin_attendance_list');
}else{
$this->session->set_flashdata('message','Salary slips not available for this month!');
redirect('admin_attendance_list');
}
}
File is getting saved in the folder, but Only with the First Record. Also, Repeated loop is getting generated, but with same record.
How to create a HTML by loop.
PS: Using MPDF to generate PDF File
Any hep will be highly appreciated.
You need to take the render, writeHtml and Output calls outside the forech loop, there is you problem.
You could save all the data in a var and then render the HTML as you are doing now and then generate the PDF.
EDIT: Your code should look something like this (please read comments below):
$htmlData = array();
if(!empty($slip)){
foreach ($slip as $slip_list) {
//
$htmlData[] = $data;
}
$pdfFilePath = date("F_Y")."salary_slip.pdf";
$html = $this->load->view('admin/payslip', $htmlData, true);
$this->m_pdf->pdf->WriteHTML($html);
$this->m_pdf->pdf->Output('salary_slips/'.$pdfFilePath, "F");

Laravel change pagination data

My Laravel pagination output is like laravel pagination used to be, but I need to change the data array for each object.
My output is:
As you can see, the data object has 2 items, which I need to change.
My code is:
$items = $this->items()
->where('position', '=', null)
->paginate(15);
Which returns the user items with pivot table, but I don't like the way the pivot table is shown in the JSON, so I decided to change the items and organize each item with the pivot before the item.
For this purpose, I tried to use foreach
foreach ($items->data as $item)
{
}
which giving my an error, for a reason I don't know:
Undefined property: Illuminate\Pagination\LengthAwarePaginator::$data"
status_code: 500
Any help?
The paginator's items is a collection. You can grab it and transform the data like so:
$paginator = $this->items()->where('position', '=', null)->paginate(15);
$paginator->getCollection()->transform(function ($value) {
// Your code here
return $value;
});
If you are familiar with tap helper here is the snippet that does exact same.
$paginator = tap($this->items()->where('position', '=', null)->paginate(15),function($paginatedInstance){
return $paginatedInstance->getCollection()->transform(function ($value) {
return $value;
});
});
We can't chain method getCollection to paginator instance because AbstractPaginator will return paginator's underlying collection. so the paginator instance will be transformed to Collection. So fix that we can use tap helper.
If you'd like to keep items paginated:
$itemsPaginated = $this->items()
->paginate(15);
$itemsTransformed = $itemsPaginated
->getCollection()
->map(function($item) {
return [
'id' => $item->id,
];
})->toArray();
$itemsTransformedAndPaginated = new \Illuminate\Pagination\LengthAwarePaginator(
$itemsTransformed,
$itemsPaginated->total(),
$itemsPaginated->perPage(),
$itemsPaginated->currentPage(), [
'path' => \Request::url(),
'query' => [
'page' => $itemsPaginated->currentPage()
]
]
);
There is a setCollection method for such purpose.
$items = Model::paginate(10);
$updatedItems = $items->getCollection();
// data manipulation
// ...
$items->setCollection($updateItems);
From the source code of /Illuminate/Pagination/AbstractPaginator.php
/**
* Set the paginator's underlying collection.
*
* #param \Illuminate\Support\Collection $collection
* #return $this
*/
public function setCollection(Collection $collection)
{
$this->items = $collection;
return $this;
}
Source
I could make shorter way. This returns edited $array instead of simple $paginated. This example modify file names.
This doc was useful for me.
$paginated=$query->paginate(12);
$array=$paginated->toArray();
foreach ($array['data'] as $r=>$record) {
$array['data'][$r]->gif=$array['data'][$r]->gif.".gif";
}
return $array;
Sample Example :
$franchiseData=[ 'id'=>1 ,'name'=>'PAnkaj'];
$models = $bookingsQuery->paginate(10);
$models->setCollection(collect($franchiseData));
return $models;
Note that $models->setCollection(collect($franchiseData)); you have to use collect() else you will get error.
getCollection
is one way to get the items. Another way is to use this
For ex- Assuming, user doesn't have name param and only have first_name and last_name
$userPaginatedData = User::paginate(15);
$users = $userPaginatedData->items();
foreach($users as $user) {
$user->name = $user->first_name . ' ' . $user->last_name;
}
return $userPaginatedData;
Now in the data key, you would see that each user has name param with it.
Laravel 8.9.0 has added the through method to AbstractPaginator.
It transforms each item in the slice of items using a callback, and keeps the items paginated.
$paginator = $this->items()->where('position', '=', null)->paginate(15);
$paginator->through(function ($value) {
// Your code here
return $value;
});
The source code:
/**
* Transform each item in the slice of items using a callback.
*
* #param callable $callback
* #return $this
*/
public function through(callable $callback)
{
$this->items->transform($callback);
return $this;
}
-Laravel 5.4
// example update column "photo"
// from "/path/to/photo.png"
// to "abc.com/path/to/photo.png"
foreach ($items as $item)
{
$path = $item->photo;
// Remove
$item->offsetUnset("photo");
// Set
$item->offsetSet("photo", url($path));
}
Laravel AbstractPaginator has methods setCollection() and getCollection()
<?php
$itemsPaginated = $this->items()->paginate(15);
$itemsPaginated->setCollection(
$itemsPaginated->getCollection()->transform(function ($item) {
// Your code here
return $item;
})
)
This is your paginated items...
$items = $this->items()
->where('position', '=', null)
->paginate(15);
I am using Laravel 8, can simply use each
$items->each(function ($item) {
// your code here
$item->custom_data = calcSomeData(); // sample
});
It does the same as this...
$items->getCollection()->transform(function ($item) {
// your code here
$item->custom_data = calcSomeData(); // sample
});
<?php
$itemsPaginated = $this->items()->paginate(15);
$itemsPaginated = json_encode($itemsPaginated);
foreach ($itemsPaginated->data as $key => $item) {
$results->data[$key]; //Modify
}
$itemsPaginated = json_encode($results);
you have to use below code in your blade
{!! $items->render() !!}
Ignore the pagination in laravel and hit the normal data
foreach ($items as $item)
{
}

Kohana 3.2 + PHPExcel creates empty document when there are more than 31 rows written.

I'm trying to create a simple excel document that contains a 3-column list. (First Name, Last Name, Email Address)
When I output more than 31 rows, a blank excel file is created. Does anyone know how to fix it?
My code below:
$guests = ORM::factory('guest')
->order_by('last_name', 'ASC')
->find_all()
->as_array();
$columns = array('first_name', 'last_name', 'email');
$objPHPExcel = new PHPExcel();
$objPHPExcel->getProperties()
->setCreator('Me')
->setLastModifiedBy('Me)
->setTitle('Guest List')
->setSubject('Guest List')
->setDescription('Title of Report, run on ' . date('m/d/Y H:i:s'));
$objPHPExcel->createSheet(0);
$objPHPExcel->setActiveSheetIndex(0);
foreach($guests as $row => $guest) {
$source = array();
$column = 0;
$next_row = $objPHPExcel->getActiveSheet()->getHighestRow();
foreach($guest->as_array() as $column_name => $data) {
if(in_array($column_name, $columns)) {
$objPHPExcel->getActiveSheet()
->setCellValueByColumnAndRow($column, $next_row+1, $data);
$column++;
// unset($data);
}
}
}
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$this->response->body($objWriter->save('php://output'));
$this->response->send_file(TRUE, 'GuestList.xls');
Kohana has a hard time handling the rendered file using the send_file() method, so write the file to disk using the built-in method from PHPExcel. Then use Kohana to deliver the saved file as a download.
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
$objWriter->save($filename, 'EXCEL2007');
$this->response->send_file( DOCROOT.$filename );

How to validate duplicate entries before inserting to database - Codeigniter

I have developed simple application, i have generated checkbox in grid dynamically from database, but my problem is when user select the checkbox and other required field from grid and press submit button, it adds duplicate value, so i want to know how can i check the checkbox value & other field value with database value while submitting data to database.
following code i use to generate all selected items and then save too db
foreach ($this->addattendee->results as $key=>$value)
{
//print_r($value);
$id = $this->Attendee_model->save($value);
}
i am using codeigniter....can any one give the idea with sample code plz
{
$person = $this->Person_model->get_by_id($id)->row();
$this->form_data->id = $person->tab_classid;
$this->form_data->classtitle = $person->tab_classtitle;
$this->form_data->classdate = $person->tab_classtime;
$this->form_data->createddate = $person->tab_crtdate;
$this->form_data->peremail = $person->tab_pemail;
$this->form_data->duration = $person->tab_classduration;
//Show User Grid - Attendee>>>>>>>>>>>>>>>>>>>>>>>>
$uri_segment = 0;
$offset = $this->uri->segment($uri_segment);
$users = $this->User_model->get_paged_list($this->limit, $offset)->result();
// generate pagination
$this->load->library('pagination');
$config['base_url'] = site_url('person/index/');
$config['total_rows'] = $this->User_model->count_all();
$config['per_page'] = $this->limit;
$config['uri_segment'] = $uri_segment;
$this->pagination->initialize($config);
$data['pagination'] = $this->pagination->create_links();
// generate table data
$this->load->library('table');
$this->table->set_empty(" ");
$this->table->set_heading('Check', 'User Id','User Name', 'Email', 'Language');
$i = 0 + $offset;
foreach ($users as $user)
{
$checkarray=array('name'=>'chkclsid[]','id'=>'chkclsid','value'=>$user->user_id);
$this->table->add_row(form_checkbox($checkarray), $user->user_id, $user->user_name, $user->user_email,$user->user_language
/*,anchor('person/view/'.$user->user_id,'view',array('class'=>'view')).' '.
anchor('person/update/'.$user->user_id,'update',array('class'=>'update')).' '.
anchor('person/showattendee/'.$user->user_id,'Attendee',array('class'=>'attendee')).' '.
anchor('person/delete/'.$user->user_id,'delete',array('class'=>'delete','onclick'=>"return confirm('Are you sure want to delete this person?')"))*/ );
}
$data['table'] = $this->table->generate();
//end grid code
// load view
// set common properties
$data['title'] = 'Assign Attendees';
$msg = '';
$data['message'] = $msg;
$data['action'] = site_url('person/CreateAttendees');
//$data['value'] = "sssssssssssssssssss";
$session_data = $this->session->userdata('logged_in');
$data['username'] = "<p>Welcome:"." ".$session_data['username']. " | " . anchor('home/logout', 'Logout')." | ". "Userid :"." ".$session_data['id']; "</p>";
$data['link_back'] = anchor('person/index/','Back to list of Classes',array('class'=>'back'));
$this->load->view('common/header',$data);
$this->load->view('adminmenu');
$this->load->view('addattendee_v', $data);
}
The code is quite messy but I have solved a similar issue in my application I think, I am not sure if its the best way, but it works.
function save_vote($vote,$show_id, $stats){
// Check if new vote
$this->db->from('show_ratings')
->where('user_id', $user_id)
->where('show_id', $show_id);
$rs = $this->db->get();
$user_vote = $rs->row_array();
// Here we are check if that entry exists
if ($rs->num_rows() == '0' ){
// Its a new vote so insert data
$this->db->insert('show_ratings', $rate);
}else{
// Its a not new vote, so we update the DB. I also added a UNIQUE KEY to my database for the user_id and show_id fields in the show_ratings table. So There is that extra protection.
$this->db->query('INSERT INTO `show_ratings` (`user_id`,`show_id`,`score`) VALUES (?,?,?) ON DUPLICATE KEY UPDATE `score`=?;', array($user_id, $show_id, $vote, $vote));
return $update;
}
}
I hope this code snippet gives you some idea of what to do.
maybe i have same trouble with you.
and this is what i did.
<?php
public function set_news(){
$this->load->helper('url');
$slug = url_title($this->input->post('title'), 'dash', TRUE);
$query = $this->db->query("select slug from news where slug like '%$slug%'");
if($query->num_rows()>=1){
$jum = $query->num_rows() + 1;
$slug = $slug.'-'.$jum;
}
$data = array(
'title' => $this->input->post('title'),
'slug' => $slug,
'text' => $this->input->post('text')
);
return $this->db->insert('news', $data);
}
?>
then it works.

Codeigniter pagination with my own query

first be gentle im a begginer.
I have a problem with codeogniter pagination and im totally clules.
I watched a lot of tuts on the net and never got any aswer.
My problem is, im building a real-estate site, it has 2 types of estate, for sale and for rent.
My query looks like this
function for_sale()
{
$query = $this->db->query(" SELECT city, rand_id, price, image FROM estate WHERE type = 'for_sale' ");
if ($query->num_rows() > 0)
{
foreach ($query->result() as $f)
{
$for_sale[] = $f;
}
return $for_sale;
}
}
my controller
function index()
{
$this->load->view("header");
$this->load->model('estate_model');
$for_sale['result'] = $this->estate_model->for_sale();
$this->load->library('pagination');
$config['base_url'] = 'http://localhost/kpi/for_sale/index';
$config['total_rows'] = 22;
$config['per_page'] = 9;
$config['num_links'] = 19;
$this->pagination->initialize($config);
// $data['records'] = $this->db->get('ingatlan', $config['per_page'], $this->uri->segment(3));
$this->load->view("for_sale_view", $for_sale);
$this->load->view("footer");
}
and my view
foreach($results as $r) {
echo '<div class="grid_4">';
echo '<p class="title">Estate for sale</p>';
echo '<div class="thumbnail">
<div class="info">
<p class="bar">'.$r->city.'</p>
<p></p>
</div>
'.$r->image.'</div>';
echo '<div class="more">View details</div>';
echo '</div>';
}
So my problem is i cant figure this out how to use it with my query, i watched lots of tuts, that i need to load in the table library, and pass a data array like this
$data['records'] = $this->db->get('estate', $config['per_page'], $this->uri->segment(3));
anf give the per page this result `$this->db->get('estate')->num_rows(); but i would like this with my query, and not with a table.
So can someone hive me a hint?
Thank you
... i need to load in the table library, and pass a data array ...
how you display your data is totally up to you. the html-table class can help you with that, but it is not necessary to use it. your view should work just fine except for the fact that you want to iterate over $results which will be empty because you put your data into $for_sale['result'] (results != result).
in order for the pagination library to work with your query, you have to pass your query 2 parameters:
how many rows/records should be loaded from your db (= $config['per_page'])
how many rows/records should be skipped at the beginning (also known as 'offset', this value will be provided by the pagination library = $this->uri->segment(3))
So instead of:
$for_sale['result'] = $this->estate_model->for_sale();
Model:
function for_sale()
{
$query = $this->db->query(" SELECT city, rand_id, price, image FROM estate WHERE type = 'for_sale' ");
...
}
you should try:
$for_sale['result'] = $this->estate_model->for_sale($config['per_page'],$this->uri->segment(3));
Model:
function for_sale($per_page, $offset) {
$query = $this->db->query(" SELECT city, rand_id, price, image FROM estate WHERE type = 'for_sale' LIMIT $offset, $per_page");
...
return $query->result();
}
One last thing: the pagination library has to be initialized BEFORE you query the database.
And another last thing: $config['total_rows'] = 22; you will probably want to replace that with something like $this->estate_model->get_for_sale_total_rows()
Hope this helps.

Resources