when i am trying to export it says that the Export::create is not found class:
use DB;
use Excel;
class ExportExcelController extends Controller
{
function index()
{
$customer_data=DB::table('book_details')->get();
return view('export_excel')->with('customer_data',$customer_data);
}
function excel()
{
$customer_data=DB::table('book_details')->get()->toArray();
$customer_array[]=array('ID','Book Name','Author Name','Publisher
Name','Supplier Name','Department of book','Book status','Book Stock',
'Image');
foreach($customer_data as $customer)
{
$customer_array[] = array('ID'=> $customer->id,
'Book Name'=> $customer->book_name,
'Author Name'=> $customer->book_author,
'Publisher Name'=> $customer->book_publisher,
'Supplier Name'=> $customer->book_supplier,
'Department of book'=> $customer->book_dept,
'Book status'=> $customer->book_status,
'Book Stock'=> $customer->book_stock,
'Image'=> $customer->book_image
);
}
Excel::create('Book Data', function($excel) use($customer_array)
{
$excel->setTitle('Book Data');
$excel->sheet('Book Data',function($sheet)
use($customer_array)
{
$sheet->fromArray(
$customer_array,null,'A1',false,false);
});
})->download('xlsx');
}
Related
When calling an edit function the prop mealService is passing null values and will not populate form fields with values. It looks like the controller isn't loading the model to query the single record. The Create and Store functions work fine.
First time posting. And very new to coding. Please let me know if more info is needed for the question.
edit.vue
export default {
components: {
Head,
Link,
LoadingButton,
SelectInput,
TrashedMessage,
},
layout: Layout,
props: {
mealService: Object,
sites: Array,
},
remember: 'form',
data() {
return {
form: this.$inertia.form({
site_id: this.mealService.site_id,
meal_type: this.mealService.meal_type,
adults: this.mealService.adults,
tally: this.mealService.tally,
}),
}
},
MealServiceController
public function edit(MealService $meal_service)
{
return Inertia::render('MealServices/Edit', [
'mealService' => [
'id' => $meal_service->id,
'site_id' => $meal_service->site_id,
'meal_type' => $meal_service->meal_type,
'adults' => $meal_service->adults,
'tally' => $meal_service->tally,
],
'sites' => Auth::user()->sfa
->sites()
->orderBy('name')
->get()
->map
->only('id', 'name'),
]);
}
MealService Model
class MealService extends Model
{
use HasFactory;
use SoftDeletes;
public function resolveRouteBinding($value, $field = null)
{
return $this->where($field ?? 'id', $value)->withTrashed()->firstOrFail();
}
public function site()
{
return $this->belongsTo(Site::class);
}
public function scopeFilter($query, array $filters)
{
$query->when($filters['search'] ?? null, function ($query, $search) {
$query->WhereHas('site', function ($query) use ($search) {
$query->where('name', 'like', '%'.$search.'%');
});
})->when($filters['trashed'] ?? null, function ($query, $trashed) {
if ($trashed === 'with') {
$query->withTrashed();
} elseif ($trashed === 'only') {
$query->onlyTrashed();
}
});
}
}
Route
Route::get('mealServices/{mealService}/edit', [MealServicesController::class, 'edit'])
->name('mealServices.edit')
->middleware('auth');
In your edit function you are using meal_service while in your route you use mealService
Try naming the one in the edit function mealService too
Using Laravel-5.8 and Maatwebsite-3.1, I have a table called employees (Employee).
class FirstEmployeeSheetImport implements ToModel, WithBatchInserts, WithHeadingRow, SkipsOnError, WithValidation, SkipsOnFailure
{
use Importable, SkipsErrors, SkipsFailures;
public function model(array $row)
{
$this->department = $row['department'];
$employee_data = [
'employee_code' => $row['employee_code'],
'company_id' => Auth::user()->company_id,
'email' => $row['official_email'],
'department_id' => $this->getDepartment(),
];
$employee = Employee::create($employee_data);
}
public function getDepartment(){
if(!empty($this->department) || !$this->department){
return HrDepartment::where('dept_name',$this->department)->where('company_id',Auth::user()->company_id)->pluck('id')->first();
} else {
return 0;
}
}
}
I want to use the excel upload to update these two (2) fields: email and department_id for each of the employees where:
company_id = Auth::user()->company_id AND employee_code = $row['employee_code'].
Also, it should only perform the update for those that meet the condition. I should only perform update and don't crete.
How do I achieve this?
Thanks
You can use ToCollection to get your data into $rows then update your data accordingly.
class FirstEmployeeSheetImport implements ToCollection
{
public function collection(Collection $rows)
{
foreach ($rows as $row)
{
Employee::where('company_id', auth()->user()->company_id)
->where('employee_code', $row['employee_code'])
->update([
'email' => $row['email'],
...
]);
}
}
}
I trying to export a Excel file, from a collection using laravel. The code bellow, returns me this. I need to add a 2 new rows above the start of columsn, is that possible? What Should I do?
<?php
namespace App\Traits;
namespace App\Exports;
// use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Collection;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithColumnWidths;
use Maatwebsite\Excel\Concerns\WithStyles;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
class exportSafety implements FromCollection, WithHeadings, WithMapping, WithColumnWidths, WithStyles, WithColumnFormatting, WithCustomStartCell
{
protected $services;
protected $request;
public function __construct(Collection $services)
{
$this->services = $services;
}
public function startCell(): string
{
return 'A3';
}
public function columnWidths(): array
{
return [
'A' => 30,
'B' => 20,
'C' => 20,
'D' => 15,
];
}
public function columnFormats(): array
{
return [
'B' => NumberFormat::FORMAT_DATE_DDMMYYYY,
];
}
public function styles(Worksheet $sheet)
{
return [
// Style the first row as bold text.
3 => ['font' => ['bold' => true]],
];
}
public function collection()
{
$this->services->each(function ($service) {
$this->map($service);
});
return $this->services;
}
public function headings(): array
{
$columns = [
'Name' => 'Name',
'Data de Nascimento' => 'Data de Nascimento',
'CPF' => 'CPF',
'Valor do Seguro' => "Valor do Seguro"
];
return $columns;
}
public function startRow(): int
{
return 2;
}
public function map($service): array
{
$columns = [
'Name' => $service->name,
'Data de Nascimento' => $service->birthdate,
'CPF' => $service->cpf,
'Valor do Seguro' => $service->client->donation_safety
];
return $columns;
}
}
But I need something like this:
I need to put two custom row above the start of the columns, is that possible? How I to that? I am using https://docs.laravel-excel.com/3.1/imports/multiple-sheets.html
you need to use WithHeadings trait to format heading rows.
$rangeHeadings = [
'chiqaruvchi',
'chiqarilgan',
'sotilgan',
"sana",
];
public function headings(): array
{
return [
[
$this->product?->name . " product " . $this->params['from_date'] . ' - ' . $this->params['to_date'] . " report",
],
$rangeHeadings,
];
}
I have component: ckeditor. I am trying to get data from it and save it to the database. Every time I save the data using the store function I get an empty record in the database:
public function store(Request $request)
{
$business = Business::create($request->all());
if($request->has('photos')) {
foreach ($request->photos as $photo) {
$filename = $photo->store('public/photos');
Photo::create([
'business_id' => $business->id,
'filename' => $filename
]);
}
}
return redirect()->action('BusinessController#clist');
}
Here is my code of component:
<template>
<vue-ckeditor type="classic" v-model="editorData" :editors="editors" id="description" name="description"></vue-ckeditor>
</template>
<script>
import VueCkeditor from 'vue-ckeditor5'
export default {
components: {
'vue-ckeditor': VueCkeditor.component
},
data(){
return {
editors: {
classic: ClassicEditor
},
editorData: '<p>Content of the editor.</p>',
}
},
}
</script>
The code in create.blade.php:
<vue-ck name="description" id="description"></vue-ck>
I will just add that the store function works fine for textarea input. Thanks for help guys.
Model:
class Business extends Model
{
protected $fillable = [
'title',
'description',
'order',
'visible',
'lang'
];
public function photos()
{
return $this->hasMany(Photo::class);
}
}
I have additional columns there, title, lang etc. But the important column is a description. I do not know why I do not want to download data from this component.
I have two models in Yii2 (masterTransaction and splitTransaction), where each masterTransactions can have multiple splitTransactions. Each splitTransaction has an attribute 'amount'. My problem is I need to validate if the sum over all 'amount' attributes is 0.
My first solution was to make another model called Transaction, in which I had an attribute where I saved an instance of the masterTransaction model and another attribute with an array of splitTransaction instances. I did the validation with a custom inline validatior, which work perfectly.
Transaction model
class Transaction extends Model
{
public $masterTransaction;
public $splitTransactions;
public function init()
{
$this->masterTransaction = new MasterTransaction();
$this->splitTransactions[] = new SplitTransaction();
}
public function rules()
{
return [
['splitTransactions', 'validateSplitTransactions'],
];
}
public function validateSplitTransactions($attribute, $params)
{
$sum = 0;
foreach ($this->$attribute as $transaction) {
$sum = bcadd($sum, $transaction->amount, 3);
}
if ($sum != 0) {
$this->addError($attribute, 'The sum of the entries has to be 0');
}
}
public function save()
{
$this->masterTransaction->save();
foreach ($this->splitTransactions as $splitTransaction) {
$splitTransaction->master_transaction_id = $this->masterTransaction->id;
$splitTransaction->save();
}
}
}
Controller function to create the model
public function actionCreate()
{
$transaction = new Transaction();
$count = count(Yii::$app->request->post('SplitTransaction', []));
for ($i = 1; $i < $count; $i++) {
$transaction->splitTransactions[] = new SplitTransaction();
}
if ($transaction->masterTransaction->load(Yii::$app->request->post()) && Model::loadMultiple($transaction->splitTransactions, Yii::$app->request->post())) {
$transaction->masterTransaction->user_id = Yii::$app->user->id;
foreach ($transaction->splitTransactions as $splitTransaction) {
$splitTransaction->user_id = Yii::$app->user->id;
}
if ($transaction->validate()) {
$transaction->save();
}
}
return $this->render('create', [
'transaction' => $transaction,
]);
}
But when I tried building a form to input the data, I ran into a problem with the Ajax validation. The validation would work, but Yii didn't know where to put the error message, so it just deleted it.
I suspect that this is just not the preferred way in Yii2 model my data, but I don't really have another idea. Maybe someone has some ideas for me.
Option 1.
It depends on your view file codes. Does your form contains "splitTransactions" variable? If not, you can put it like this
<?= $form->field($model, 'splitTransactions')->hiddenInput(['maxlength' => true])->label(false); ?>
The variable will be hidden, but still show errors. In some case validation will not be fired because of empty value of "splitTransactions" variable.
"splitTransactions" should contain some value to fire validation. You can put some value to if before pasting the form like this
$model->splitTransactions=1;
Option 2.
You can add error to other variable (which form contains) like this
public function validateSplitTransactions($attribute, $params)
{
$sum = 0;
foreach ($this->$attribute as $transaction) {
$sum = bcadd($sum, $transaction->amount, 3);
}
if ($sum != 0) {
$this->addError('transaction_number', 'The sum of the entries has to be 0');
}
}
Look, form should contain "transaction_number" variable. Error will be added to "transaction_number" input.
Option 3. In my experience.
It is better to separate ajax validation from form action url a.g. create another controller action for ajax validation and use it.
Example
Create model FeedbackForm
class FeedbackForm extends Model
{
public $name;
public $email;
public $text;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['name', 'email', 'text'], 'required'],
[['name', 'email'], 'string', 'max' => 128],
[['email'], 'email'],
[['text'], 'string', 'max' => 512],
];
}
public function attributeLabels()
{
return [
'name' => \Yii::t('front', 'Name'),
'email' => \Yii::t('front', 'Email'),
'text' => \Yii::t('front', 'Message text'),
];
}
}
put actions to SiteSontroller
public function actionFeedback()
{
$model= new \frontend\models\FeedbackForm;
$model->load(Yii::$app->request->post());
if($model->validate()) {
$newFeed=new \frontend\models\Feedback;
$newFeed->create_time=new \yii\db\Expression('NOW()');
$newFeed->name=$model->name;
$newFeed->email=$model->email;
$newFeed->is_new=1;
$newFeed->text=$model->text;
if($newFeed->save()) {
\Yii::$app->session->setFlash('success', \Yii::t('front', 'Your message has accepted'));
} else {
\Yii::$app->session->setFlash('error', \Yii::t('front', 'Error on save'));
}
} else {
\Yii::$app->session->setFlash('error', \Yii::t('front', 'Data error'));
}
return $this->redirect(['/site/index']);
}
public function actionFeedbackvalidate()
{
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$model= new \frontend\models\FeedbackForm;
$model->load(Yii::$app->request->post());
return ActiveForm::validate($model);
}
And create form inside view
<?php $model=new \frontend\models\FeedbackForm; ?>
<?php $form = ActiveForm::begin([
'enableClientValidation' => true,
'enableAjaxValidation' => true,
'validationUrl'=>['/site/feedbackvalidate'],
'validateOnSubmit' => true,
'id' => 'form-feedback',
'action'=>['/site/feedback'],
'options'=>['class'=>'some class', 'autocomplete'=>'off']
]); ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => true, 'placeholder'=>$model->getAttributeLabel('name'), 'autocomplete'=>'off'])->label(false); ?>
<?= $form->field($model, 'email')->textInput(['maxlength' => true, 'placeholder'=>$model->getAttributeLabel('email'), 'autocomplete'=>'off'])->label(false); ?>
<?= $form->field($model, 'text')->textarea(['maxlength' => true, 'placeholder'=>$model->getAttributeLabel('text'), 'autocomplete'=>'off'])->label(false); ?>
<div class="form-group">
<input type="submit" class="btn btn-default" value="<?php echo Yii::t('front', 'Send') ?>">
</div>
<?php ActiveForm::end(); ?>
That is it