Can we make heading not editable in laravel-excel export - laravel

I'm using Maatwebsite\Excel to download excel file. When the file downloaded I want to make header row which specify the column heading, read only. After downloading no one can make any change in headers. Is it Possible to do make column name un-editable ? I looked for lock function , or protect function but couldn't find answer. please help.
i have registerEvents() function where i'm specifying all the editing parts like ,
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
$event->sheet->getDelegate()->getStyle('A1:C1')->getFont()->setSize(16);
},
];
}
is there any function i can write here or anywhere!?

This solution worked for me for making header uneditable
$sheet->protectCells('A1:G1', 'PASSWORD');
$sheet->getStyle('A2:G10')->getProtection()->setLocked(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_UNPROTECTED);
//A2:G10 is the range which can be editable
$sheet->getDelegate()->getProtection()->setSheet(true);

Related

Laravel attach a non-physically saved file

I'm trying to find a way to attach a non-physical file to an email that's being made on the spot.
I'm using the following lines in my controller:
$columns = ['line1', 'line2'];
$rows = [
['line1' => 'first', 'line2' => 'second'],
['line1' => 'first', 'line2' => 'second'],
['line1' => 'first', 'line2' => 'second'],
];
Mail::to('email#email.com')->send(new ExportMail($columns, $rows));
And the following build function in the ExportMail class:
public function build()
{
$file = fopen('php://output', 'w'); // Tried w+ too
fputcsv($file, $this->columns);
foreach ($this->rows as $row) {
fputcsv($file, $row);
}
// I tried a couple of things:
return $this->view('emails.myTestMail')
->attach($file);
return $this->view('emails.myTestMail')
->attach(fopen($file, 'r'));
return $this->view('emails.myTestMail')
->attach(fopen('php://output', 'r'));
return $this->view('emails.myTestMail')
->attach(file_get_contents($file));
return $this->view('emails.myTestMail')
->attach(file_get_contents(fopen($file, 'r')));
return $this->view('emails.myTestMail')
->attach(file_get_contents(fopen('php://output', 'r')));
}
But none if it works so I'm beginning to question if there is a way to send an email with a file that is never physically saved.
You can attach file data directly with the attachData method documented here:
https://laravel.com/docs/9.x/mail#raw-data-attachments
I use this regularly to attach dynamically generated PDF files, for example.
You should be able to do something like this:
return $this->view('emails.myTestMail')
->attachData($yourCsvData, "attachment.csv");
Also, I think you want to look at how you are generating your CSV data. Right now using php://output the CSV data will be sent out to the browser immediately, not stored in a variable.
There are a couple ways you can solve this, output buffering being one, or using php://temp instead, or using one of many CSV libraries (like https://csv.thephpleague.com/). I put together a fully working example for you here using php://temp:
https://laravelplayground.com/#/snippets/aa5b6594-4493-4ca4-9d12-837c102b7cc5
Expand the rawAttachments attribute on that Message on the right, and you'll see the attached CSV file.

Setting up Laravel-excel and PhpSpreadsheet macro

I am using Maatwebsite Laravel-excel version 3.1. And I want to set the default styling of the sheet. I have read the documentation about including a macro in your laravel app by setting this in my AppServiceProvider boot() method. :
Sheet::macro('getDefaultStyle',function(Sheet $sheet){
$sheet->getDefaultStyle();
});
But when everytime i reload the page it crashes the page and the laravel server in my cmd stops and re run. Here is my Export.php looks like:
public function registerEvents():array
{
return[
AfterSheet::class=>function(AfterSheet $event){
$header_style_array = [
'font'=>['bold'=>true]
];
$style_array = [
'font'=>['bold'=>true]
];
$event->sheet->getStyle('A1:B1')->getAlignment()->setHorizontal('center');
$event->sheet->getStyle('A1:B1')->applyFromArray($header_style_array);
$event->sheet->getDefaultStyle()->getFont()->setSize(5);
}];
}
I already included use Maatwebsite\Excel\Concerns\WithEvents; use Maatwebsite\Excel\Events\AfterSheet; above my Export.php file.
Is there something that I missed? I find this so hard to set up. And there's little article about setting this up.
Any help would be much appreciated
Refs: https://phpspreadsheet.readthedocs.io/en/latest/topics/recipes/#styles
https://docs.laravel-excel.com/3.1/exports/extending.html
If you examine the documentation for PhpSpreadsheet, I think you will find that the getDefaultStyle() method is not accessible from the active sheet.
To Laravel Excel, $event->sheet is equivalent to $spreadsheet->getActiveSheet(). This is why your current configuration will not work.
// this doesn't work
// $spreadsheet->getActiveSheet()->getDefaultStyle()->getFont()->setSize(5);
// this does
$spreadsheet->getDefaultStyle()->getFont()->setSize(5);
You should set default styles through the writer in BeforeWriting.
public function registerEvents():array
{
return [
BeforeWriting::class=>function(BeforeWriting $event){
$event->writer->getDefaultStyle()->getFont()->setSize(5);
},
];
}
If you want to turn this into a macro, you should use a Writer macro rather than a Sheet macro.
https://docs.laravel-excel.com/3.1/exports/extending.html#writer
public function registerEvents():array
{
Writer::macro('setDefaultStyle', function (Writer $writer) {
$writer->getDefaultStyle()->getFont()->setSize(5);
});
return [
BeforeWriting::class=>function(BeforeWriting $event){
$event->writer->setDefaultStyle();
},
];
}

Laravel Validation Passing Variable to Rule::in() method

I am importing a Excel file in Laravel, It is working fine. I need some validation like whether team ids are available in database or not. I make a query each time file uploaded and create an array and then implode it to pass in rule condition. Can you please help. Is it possible to pass and variable to rule method as am trying to do in my code?
Thanks in advance.
public function rules(): array
{
.......
//Some Codes here
.....
$team_id = implode("', '", $team_id_array);
return [
'*.ext_or_int' => Rule::in(['Internal','External']),
'*.team_id' => Rule::in(['$team_id']),
];
}

Laravel maatwebsite/excel (PhpSpreadsheet) and TCPDF wrong sheet orientation

I have a Laravel application using the maatwebsite/excel package to generate and excel file. I also allow the user to download that excel file as a PDF.
The problem is that when the pdf is generated, the pagination is vertical and the content gets cut.
I have the excel file set to landscape but the pagination is still vertical. I can not find in the docs a way to set the pdf direction
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
// Landscope orientation
$event->sheet->getDelegate()->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE);
}
];
}
I'm exporting the PDF file using the TCPDF library. I've seen a parameter in the docs to set as landscape but I can not figure out the way to pass the parameter to the TCPDF constructor with the maatwebsite/excel api. This is the syntax:
return (new GanttExport)->download('gantt_' . time() . '.pdf', Excel::TCPDF);
Have you tried using BeforeSheet event? It does work in my code. And dont forget to implement Maatwebsite\Excel\Concerns\WithEvents interface within the class.
public function registerEvents(): array
{
return [
BeforeSheet::class => function (BeforeSheet $event) {
$event->sheet
->getPageSetup()
->setOrientation(PageSetup::ORIENTATION_LANDSCAPE);
}
];
}

File Upload in Laravel - Display Error to user if they are trying to upload big file

Within Laravel, I am successfully able to have a user upload a file on a page, but I want to know if there is a way for there to be an error displayed to that user before they submit the page that the file is too big. Something like "The file you selected to upload is 25MB. Get it below 20MB."
Is there some kind of package that can handle this?
Validating the file size on client side. (Mentioning this because you have mentioned that you would like to alert the error before form submit.)
Check the example code below which uses jQuery :
$(document).ready(function() {
$('input[type="file"]').change(function(event) {
var fileSize = this.files[0].size;
var maxAllowedSize = //add your value here;
// check the file size if its greater than your requirement
if(size > maxAllowedSize){
alert('Please upload a smaller file');
this.val('');
}
});
});
Validation on server side(you can change mime types as per the file type you want to allow) :
<?php
public function store(Request $request){
$request->validate([
'file_input_name' => 'file|max:25000|mimes:jpeg,bmp,png',
// add validations for other fields here
]);
}
For more check documentation
You don't need a package to do this, you can create either a Request class or use a validator:
1. Create a Request class:
Run the command php artisan make:request FileRequest
Then, on the File generated under App\Http\Requests\FileRequest do the following:
Change the authorize method to return true instead of false.
Under the rules method you return your validation rules:
return [
"file_input" => "max:20480", //If your input type's file name is "file_input"
];
According to documentation, max rule verifies that the input size from the user will not exceed the specified number in kilobytes for files.
2. You can also create a validator in your controller method:
use Validator;
public function store(Request $request)
{
$validator = Validator::make($request->only('file_input'), [
'file_input' => 'max:20480',
]);
if ($validator->fails()) {
return redirect()
->route('your.route.name')
->withErrors($validator)
->withInput();
}
// other code here
}

Resources