Maatwerk Excel Laravel how to set CSV EXPORT delimeter? - php

Hi i'm using Maatwerk Excel laravel package to export data to XLSX and CSV.
In 2 instances a comma is good.
But now i need to make a CSV where the delimeter is not a comma but something different (a tab or pipe symbol).
I cannot find where to set this.
I tried:
Config::set('Excel::csv.delimeter','|');
Excel::create('CSV Products', function($excel) use ($exports_arr) {
$excel->setTitle('Products');
$excel->setCreator('Me')->setCompany('My company');
$excel->setDescription('Products');
$excel->sheet('sheet1', function($sheet) use ($exports_arr) {
$sheet->fromArray($exports_arr, null, 'A1', false, false);
});
})->download('csv');
But if i look in the config/Excel.php file the comments suggest that this delimeter is only for reading.
Is it even possible to change the Delimeter for EXPORTING CSV files?
Thanks in advance.

The comment states that excel.csv.delimiter is used for reading out a csv file, but in Writers/LaravelExcelWriter.php (line 578) the CSV delimiter is taken from the config, and set as , by default:
$this->writer->setDelimiter(config('excel.csv.delimiter', ','));
Are you sure the Config::set statement works properly?
Try to use:
Config::set('excel.csv.delimeter','|');
and check the value with
Config::get('excel.csv.delimeter');
UPDATE:
As mentioned in this answer, the service provider is registered before the request takes place. Updating the config key during the request won't affect the value that is read earlier by Maatwerk/Excel. A solution is given in the answer, by creating a deferred provider.

I know this is a bit outdated but I was having the same problem recently.
In order to set a custom delimiter while exporting multiple CSV files, you can create a new instance of the use Maatwebsite\Excel\Excel class without using the facade.
Try this:
use Maatwebsite\Excel\Excel;
use Maatwebsite\Excel\Writer;
use Maatwebsite\Excel\QueuedWriter;
use Maatwebsite\Excel\Reader;
...
$reader = new Reader(app()->make('filesystem'));
$writer = new Writer;
$queued_writer = new QueuedWriter($writer);
$writer->setDelimiter('|');
$excel = new Excel($writer, $queued_writer, $reader, app()->make('filesystem'));
$excel->create( ... );

An update on this question: If you are using Laravel Excel 3, you can set it in the config/excel.php file:
return [
'exports' => [
'csv' => [
'delimiter' => '|',
]
]
]
Or if you want to set it dynamically:
\Config::set('excel.exports.csv.delimiter', '|');

use Maatwebsite\Excel\Concerns\WithCustomCsvSettings;
use Maatwebsite\Excel\Concerns\WithCustomQuerySize;
class MyExportClass implements FromView, WithCustomQuerySize, WithCustomCsvSettings
{
use Exportable;
public string $filePath;
public string $disk;
public function getCsvSettings(): array
{
return [
'delimiter' => ",",
];
}
....
}
From documentation:
enter link description here

Related

How to update information without duplicating in the database

I'm still new to Laravel and I needed some help.
I have a job from a programming course that I'm stuck on, which is to import a .csv file like in the image: enter image description here
And I need to add it to the database without duplicating the CPF information as in the image:
enter image description here
*The information is merely illustrative.
So if anyone can help me I would appreciate it.
I can use updateOrCreate but it doesn't get the rest of the information.
Import:
public function collection(Collection $collection)
{
foreach ($collection as $row) {
Clientes::updateOrCreate(
[ 'cpf' => $row[1]],
[ 'nome' => $row[2],
'telefone1' => $row[0],
]
);
}
}
Controller:
public function import(Request $request)
{
$import = (new ImportTelefones(2));
Excel::import($import, $request->file);
return redirect()->back();
}
It looks like that you are trying to import an Excel or CSV file.
The easiest option for that is to use Laravel-Excel Package.
See here:
Installation: https://docs.laravel-excel.com/3.1/getting-started/installation.html
Import: https://docs.laravel-excel.com/3.1/imports/
With that you should be able to import your file and have the data in the database.
To prevent duplicates you can use the 'upsert' feature. It will update the entry on import instead of creating it, if the configured unique key exists.
https://docs.laravel-excel.com/3.1/imports/model.html#upserting-models
Best regards
Sergej

Laravel firstOrCreate() not working with event listeners

I have a table "phones" with columns "id" and "number". I need to store only unique phone numbers.
I used to do this:
$phone = Phone::firstOrCreate(['number' => $phone['number']]);
And it worked just fine.
Now I want to save phone numbers without spaces, but show them with spaces for better reading. So I created two event listeners and registered them in Phone model like this:
protected $dispatchesEvents = [
'saving' => \App\Events\Phone\PhoneSavingEvent::class,
'retrieved' => \App\Events\Phone\PhoneRetrievedEvent::class,
];
With listeners defines like this:
public function handle(PhoneSavingEvent $event)
{
$event->phone->number = preg_replace('/\s+/', '', $event->phone->number);
}
public function handle(PhoneRetrievedEvent $event)
{
$event->phone->number = wordwrap($event->phone->number, 3, ' ', true);
}
Listeners works just fine. Phone numbers are saved without spaces and displayed with spaces. But function firstOrCreate() now saves duplicate phone numbers to database.
How can I save unique phone numbers again with these two listeners?
Thank you
EDIT:
If I don't use $dispatchesEvents but use this code instead:
protected static function booted()
{
static::saving(function ($phone) {
$phone->number = preg_replace('/\s+/', '', $phone->number);
});
}
The firstOrCreate() function works well, when trying to save number without spaces (like "111222333"). It will find that in database and won't save duplicate.
But if I try to save number with spaces (like "111 222 333") the firstOrCreate() function save it like "111222333", but that number is already in database.
I probably should treat the number somewhere else than in event listener. But where/how?
Read this link https://laravel.com/docs/9.x/eloquent-mutators
And add $table->string('number')->unique(); to your migration.
You can use these rules to validate your number format and make sure that it is unique
'number' => 'required|numeric|min:8|max:11|unique:your_table_name'
hey you need to set your number column unique attribute in you migration
$table->string('number')->unique();
in your controller before try to manage data check and validate data first the simple way like this below or you can check with regex to
'number' => 'required|numeric|min:8|max:11',
and in your dispatchesEvents variable you can use creating instead of saving

Having constants for all pages in Laravel

I want to have some constants to have IP, platform, browser to be placed in a single file and to be used in all views and controllers like so:
// inside app/config/constants.php
return [
'IP' => 'some ip'
];
// inside controller
echo Config::get('constants.IP');
But instead of 'some ip', I want to use Request::ip() at least or even better, to use parse_user_agent()['platform'] that its code link is here
Simply you may put something like this in your config file:
return [
'ip' => app('request')->ip()
];
I use a little customized one for my sitewise configs, for example, let's say you want to use something like this:
/**
* Get config/constants.php
*
* [
* 'person' => [
* 'name' => 'Me',
* 'age' => 1000
* ]
* ];
*/
$name = constants('person.name');
So, to achieve this you need to write a function like:
// Helpers/Common.php
function constants($key = null)
{
$constants = config('constants');
return is_null($key) ? $constants : array_get($constants, $key);
}
Now, in your composer.json file you may add the following files entry:
"psr-4": {
"App\\": "app/"
},
"files": ["Helpers/Common.php"]
Then you need to add the constants.php in config directory for example:
<?php
return [
"ip" => app('request')->ip(),
"person" => [
"name" => "Sheikh Heera",
"age" => 10000
],
];
Finally, just run composer-dump from terminal and you are done. So, if the ip key is available in the array then you may just try this:
$ip = constants('ip');
From the view (Blade), you may use following to echo out the ip:
{{ constants('ip') }}
Let's sum up the whole process:
Create a directory in your project root (or inside app if you wish) as Helpers.
Create the Common.php file in that directory and put the array (return it)
Put the constants function (given above) in the Common.php file
Add the files (given above) key in your composer.json file
Run composer-dump to update autoload files
That's it. Use the file name and helper function name that describes your domian, so instead of constants you may use for example: site or your domain name as well.
You can create (or use an existing) a service provider and in the register method use the following code:
view()->share('constants', config('constants', []));
Using share on the view helper function will share the variable over all views.
You can now access this variable in any view, for instance with blade:
{{ array_get($constants, 'ip') }}

Import utf-8 headings Maatwebsite Laravel

I'm using Maatwebsite in Laravel and it's very good option for excel works but I have one problem .. I have excel sheet with arabic heading, so when I import it , it converted to understand-less english character to fit array key .. So What is the solution for my problem?
I know it's too late, but for someone else that may have the same problem, you should change the value of "heading" key to "original" in "import" array of config/excel.php file..
'import' => [
...
'heading' => 'original',
],
http://www.maatwebsite.nl/laravel-excel/docs/import
Look up the header about import encoding.
From thoose pages:
// When utilising a closure, you can pass the input encoding as third parameter.
Excel::load('filename.csv', function($reader) {
}, 'UTF-8');
// or without a closure, you can use it as second parameter.
Excel::load('filename.csv', 'UTF-8');
Does that solve the issue?
You can implements the Interface of WithCustomCsvSettings, in your class import
Example:
<?php
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithCustomCsvSettings;
class ArticlesImport implements ToCollection, WithCustomCsvSettings
{
public function collection(Collection $rows)
{
// do something
}
public function getCsvSettings(): array
{
# Define your custom import settings for only this class
return [
'input_encoding' => 'UTF-8',
'delimiter' => ";"
];
}
}
I'm too late but this workerd for me, instead of a modifying import.php, in your controller add this
config(['excel.import.heading' => 'original' ]);

Yii2 translating data stored in database

I'm working with Yii2 Framework, and already configured i18n component using this guide:
http://thecodeninja.net/2014/12/i18n-with-yii-2-advanced-template/
So, I can now translate strings within my php files using Yii::t() function. Translatable strings are extracted using $ ./yii message/extract console command, which generates proper translation files.
I now need to display translations for strings stored in the database.
I could use Yii:t() with a variable instead of a string as an argument like this
echo Yii:t('app', $some_string_from_db );
and make a new php file with some code like this
<?php
function dbStringsToTranslate() {
$o = Yii::t('app','db english string 1');
$o.= Yii::t('app','db english string 2');
$o.= Yii::t('app','db english string 3');
return $o;
}
This way $ ./yii message/extract command will find the needed translations.
This is working Ok, but of course $ ./yii message/extract is throwing some warnings anywhere I use Yii:t() with variables.
Skipping line 39. Make sure both category and message are static strings.
I think this is not a big deal, but well, here is my question:
Is this a right way to translate strings stored in a database?
Is there a better way to accomplish this?
You can check out this extension. https://github.com/creocoder/yii2-translateable it allows for attaching behaviors to models to support multiple languages.
I am using it now in a projects and it is easy to use.
I was having the same problem, and I found the solution with this module. In the module configuration you have the 'tables' array, in which you can specify which field(s) of which table(s) should be translated.
Then, the module has its own 'scan' action (equivalent to message/extract) with which it adds all the translatable strings to database (using DbMessageSource): all Yii::t, the specified database fields, and many more (even javascript, check the docs). It also has a nice user interface to do the translations, it's awesome!
For example, with the following configuration the field name from table nationality will be scanned and added for its translation (i.e country names):
'modules' => [
'translatemanager' => [
'class' => 'lajax\translatemanager\Module',
...
'tables' => [ // Properties of individual tables
[
'connection' => 'db', // connection identifier
'table' => 'nationality', // table name
'columns' => ['name'], // names of multilingual fields
'category' => 'database-table-name',// the category is the database table name
'categoryPrefix' => 'lx-' //
]
]
],
],
You can generate php file with some fake Yii:t() calls.
For example:
$filename = Yii::getAlias('#frontend/runtime/fake-category-translations.php');
$str = '<?php' . PHP_EOL;
foreach (Category::find()->all() as $category) {
$str .= "Yii::t('category', '{$category->name}');" . PHP_EOL;
}
file_put_contents($filename, $str);
In output this file will be something like this:
<?php
Yii::t('category', 'Art & Design');
Yii::t('category', 'Creativity');
Yii::t('category', 'Educational');
Yii::t('category', 'Education');
Yii::t('category', 'Lifestyle');
Yii::t('category', 'Casual');
So, now you can just call console method for searching untranslated strings:
php yii message/extract #frontend/messages/config.php
I know this is old but I faced same thing with rest API, and here is how I went about resolving it. Note that When saving I used
$post->comment = Yii::t('app', 'My Nice Comment here');
$post->save();
class Post extends ActiveRecord
{
public function fields()
{
$fields = parent::fields();
$fields['comment'] = function ($model) {
return Yii::t('app', $model->comment);
};
return $fields;
}
}

Categories