New Rewritten version! Class renamed as well. Download had incorrect folder name and file name, though the class itself is named correctly. Don't code late at night.
CSVExport will allow you to create a csv file with optional row callbacks. By default it will return a string of comma delimited items, but can also write a file if you need one.
By passing an Array, CDbCommand, CSqlDataProvider, or CActiveDataProvider instance this extension will create a csv string or file, taking into account also any paging settings.
For extremely large csv files, you should just use mysql's select into file instead, as it will be really fast (you just need correct permissions).
Yii 1.1 PHP 5.2+
Delimiter and Enclosure defaults to php defaults of , and ". You can change this with set functions, or at the call toCSV(). Many set* functions provide a fluent interface as well.
Yii::import('ext.ECSVExport'); // for use with array of arrays $data = array( array('key1'=>'value1', 'key2'=>'value2') .... ) $csv = new ECSVExport($data); $output = $csv->toCSV(); // returns string by default echo $output; // gives you something like key1,key2 value1,value2 // OR $csv = new ECSVExport($provider); $content = $csv->toCSV(); Yii::app()->getRequest()->sendFile($filename, $content, "text/csv", false); exit();
Writing To File
Yii::import('ext.ECSVExport'); // for use with array of arrays $data = array( array('key1'=>'value1', 'key2'=>'value2') .... ) $filename = 'somewriteablefile.csv'; $csv = new ECSVExport($data); $csv->toCSV($filename); // returns string by default echo file_get_contents($filename); // gives you something like key1,key2 value1,value2
Human Readable headers
$headers = array('header_to_change'=>'new value'); $csv->setHeaders($headers); // or $csv->setHeader($currentHeaderValue, $newHeaderValue);
Per Row Callback
// callback must be is_callable by php or exception is thrown $csv->setCallback(function($row){ $new = array(); foreach($row as $k=>$v) { $new[$k] = $v * $v; } return $new; });
Exclude Columns
$exclude = array('getlost','dontshow'...); $csv->setExclude($exclude); // or $csv->setExclude($nameofcolumn);
Various Provider types
// CDbCommand $cmd = Yii::app()->db->createCommand("SELECT * FROM track_test LIMIT 10"); $csv = new ECSVExport($cmd); $csv->setOutputFile($outputFile); $csv->toCSV(); // CSqlDataProvider // Defaults to looping through all pages, use $csv->exportCurrentPageOnly(); to turn that off $count=Yii::app()->db->createCommand('SELECT COUNT(*) FROM track_test WHERE campaign_id=1')->queryScalar(); $sql='SELECT * FROM track_test WHERE campaign_id=1'; $dataProvider=new CSqlDataProvider($sql, array( 'totalItemCount'=>$count, 'pagination'=>array( 'pageSize'=>10, ), )); $csv = new ECSVExport($dataProvider); $csv->exportCurrentPageOnly(); // if not set will loop through all pages! $csv->setOutputFile($this->outputFile); $csv->toCSV(); // CActiveDataProvider $dataProvider = new CActiveDataProvider('Track', array( 'criteria'=>array( 'condition'=>'campaign_id=1 and type=1' ) )); $csv = new ECSVExport($dataProvider); $csv->setOutputFile($this->outputFile); $csv->toCSV(); // Active Records $csv = new ECSVExport(Track::model()->findAllByAttributes(array('campaign_id'=>1,'type'=>Track::TYPE_INT_SUCCESS))); $csv->setOutputFile($this->outputFile); $csv->toCSV();
When working with CActiveDataProviders, you can often run out of memory when working with large resultsets. $convertActiveDataProvider defaults to true, which creates a command out of provider. While this seems to fix memory problems, you are no longer able to use the with() function and will will to resort to joins. Sorry! Use dontConvertProvider() to turn that off.
Total 20 comments
Hi,
thanks for the extension.
My csv files won't import corectly so I changed:
Maybe add this at line 58 and a public array $includeAttributes to support magic component properties. e.g. to call
just noticed a bug with implementing the code mentioned below, download new version and then this should work.
Hey guys, I really like this extension but how do I get related columns into my $csv variable from a CActiveDataProvider?
I am trying to apply code to the search function that saves the filtered CActiveDataProvider in SESSION then use that SESSION variable as the datasource for the CSV.
I see you say you cant use with() unless you call dontConvertProvider(), however that seems to turn off my select and still not use my with().
Any help would be greatly appreciated.
what a careless error on my part, fixed in the download
Hi, thanks for the great work.
It took me a few minutes to work out why the extension didn't want to load. You switched the 'C' and 'S' in the filenames of the latest releases...easy to overlook.
added fix, thanks for bug report
Great plugin, thank you! I have noticed/fixed a couple of bugs:
Hope that helps.
I have a fix coming, but until I can upload it (on my phone right now) I just changed the description. Should be up today once I test and verify it.
Why exactly is PHP 5.3 required? Keeping the requirements as low as possible or similar to current Yii version seems pretty important to me. For example, our production environment (and probably many others) still runs on 5.2.
I fixed that bug, and added the file output documentation here on this page, it was in the header on the actual file, but I had removed it by accident when I updated this page, thanks for pointing that out.
As for extending from CComponent, other than being able to set public properties, I don't see what advantages there would be. If you can think of something let me know. The other problem I have with just extending from CComponent is that you can't really restrict what those public properties are set to, ie; the setCallback function, which makes sure that you are only setting a callable function. You could check later when it is called, but I find it easier to debug if it fails right when you try to set it.
And please include something like this in your documentation:
Bug In 0.5, Exlude is not implemented properly. It correctly excludes the headers, but not the rows. Replace the incorrect code in _writeRow with this:
Additional idea You could extend from CComponent so we can do $csv->headers = array(), $csv->exclude = array(), etc.
old class is still available to download, but I suggest upgrading to the new one, its alot faster, uses less memory, has some more options.
Thumbs up for the rewrite!
Large recordsets are now being handled by passing in a CDbCommand rather than a CSqlDataProvider [i.e. a QueryAll()].
there is a new version in devel for anyone who is interested: http://thebusypixel.com/ECSVExport.zip
I will post as official after I finish more tests, as this new version supports passing CDbcommands and activerecord resultsets.
ok im working on a rewrite right now that will help you with large record sets, I just have to finish up the testing today and should have it this week. do you have some sample data sets I can use to test against?
I'm using:
are you pulling back active records or just from csql?
First, thanks for the great extension!
I've got a problem where the results from a queryall is too large to deal with in one go (38k+ records). Would it be difficult to rejig the extension to do some kind of paging and perhaps write the file in stages?
Leave a comment
Please login to leave your comment.