Export Cgridview Keeping Chosen Record Sort Order

I need to export records from a cgridview to a pdf in the same order that the user chooses, and respecting the applyed filtering. It all works fine at the filter part but I can’t get the export to respect the order from the cgridview. Can someone pls help?

Here’s my relevant code:

controler:




public function actionIndex()

	{

		$model=new activitylog('search');

		$model->unsetAttributes();  // clear any default values

		if(isset($_GET['activitylog']))

			$model->attributes=$_GET['activitylog'];

                        Yii::app()->user->setState('logModel',$model); 

		$this->render('admin',array(

			'model'=>$model,

		));

	}


public function actionPrint()

	{

                        

    if(Yii::app()->user->getState('logModel')):

      $model=Yii::app()->user->getState('logModel');

    else:

      $model=new activitylog('search');

      $model->unsetAttributes();       

    endif;  

    $dataProvider = $model->search();                                      

    $dataProvider->pagination=false; // for retrieve all models

    

    $larguras=array('10','35','20','20','30','50');

    Yii:utils::makeTablePdf($dataProvider, 

                            ' ', //titulo

                            'ficheiro',

                            'Atividade no Sistema', //subtitulo

                            $larguras

                            );

             

}




Everything is ok with filtering. PDF only prints filtered records. But the sort order from the grid (the one resulting from clicking column headers) is not respected. My model search function goes as follows:





	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);

		$criteria->compare('inserted_date',$this->inserted_date,true);

		$criteria->compare('username',$this->username,true);

		$criteria->compare('func',$this->func,true);

		$criteria->compare('ip_user',$this->ip_user,true);

		$criteria->compare('description',$this->description,true);


		return new CActiveDataProvider($this, array(

		  'sort'=>array('defaultOrder'=>'inserted_date DESC'),

			'pagination'=>array('pageSize'=>50),

			'criteria'=>$criteria,

		));






Any ideas to help the newbie?

I think it may can help you. Not sure if it the most suitable option… But… Let’s give it a try.

Controller




public function actionIndex() {

	$model=new activitylog('search');

	$model->unsetAttributes();

	

	/**** ADDED CODE ****/

	if (isset($_GET['sort'])) {

		Yii::app()->user->setState('activitylog_sort', $_GET['sort']);

	} else if (Yii::app()->user->hasState('activitylog_sort'))

		$_GET['sort']=Yii::app()->user->getState('activitylog_sort');

	/**** END ADDED CODE ****/

				

	if(isset($_GET['activitylog']))

		$model->attributes=$_GET['activitylog'];

		

	Yii::app()->user->setState('logModel',$model); 

		$this->render('admin',array(

			'model'=>$model,

		));

	}



Model




public function search()

{

	$criteria=new CDbCriteria;


	$criteria->compare('id',$this->id);

	$criteria->compare('inserted_date',$this->inserted_date,true);

	$criteria->compare('username',$this->username,true);

	$criteria->compare('func',$this->func,true);

	$criteria->compare('ip_user',$this->ip_user,true);

	$criteria->compare('description',$this->description,true);

	

	/**** ADDED CODE ****/

	$sorter = new CSort;

	$sorter->defaultOrder = 'inserted_date DESC';

	$sorter->attributes = array(

		'id'=>'id',

		'inserted_date'=>'inserted_date',

		'username'=>'username',

		'func'=>'func',

		'ip_user'=>'ip_user',

		'description'=>'description',

	);

	/**** END ADDED CODE ****/

	

	/**** ENTIRE BLOCK HAS CHANGED CODE ****/

	return new CActiveDataProvider($this, array(

		'criteria'=>$criteria,

		'sort'=>$sorter,

		'pagination'=>array(

			'pageSize'=>array('pageSize'=>50),

		),

	));

	/**** END CHANGED CODE ****/

}



Now when the user change the sorter that will be saved to user session and stick upon navigation.

Thiago:

One thousand thank you’s… It works like a charm…

I needed some minor changes though. I’will post them here for others that might need them. Here’s the complete solution:

Controller:





public function actionIndex()

	{

    $model=new activitylog('search');

    $model->unsetAttributes();  // clear any default values

          

    if (isset($_GET['sort'])):              

       Yii::app()->user->setState('activitylog_sort', $_GET['sort']);       

    endif;

     

    if(isset($_GET['activitylog']))

	$model->attributes=$_GET['activitylog'];


    Yii::app()->user->setState('logModel',$model); 

		$this->render('admin',array(

			'model'=>$model,

		));

	}



when printing to pdf:





public function actionPrint()

	{

                        

    if(Yii::app()->user->getState('logModel')):

      $model=Yii::app()->user->getState('logModel');


      // this is the new line ( the one that does the trick...)

      $_GET['sort']=Yii::app()->user->getState('activitylog_sort');

      // end new line


    else:

      $model=new activitylog('search');

      $model->unsetAttributes();       

    endif;  

    $dataProvider = $model->search();                                      

    $dataProvider->pagination=false; // for retrieve all models

    

    $larguras=array('10','35','20','20','30','50');

    Yii:utils::makeTablePdf($dataProvider, 

                            ' ', //titulo

                            'ficheiro',

                            'Atividade no Sistema', //subtitulo

                            $larguras

                            );

             

	}






The search function is just like you wrote it.

Muito Obrigado

Jorge

You are welcome. Glad that helped you out.

Thank you for your considerations. I have additional problem.

I have view allinfo.php with Cgridview and button with action allinfo. I can sort and filter this table in different manners. It works perfectly in the table. But Pdf contains correct sorted and filtered data EXCEPT ONE COLUMN.

My codes:

Controller




public function actionAllinfo() {

		$model=new Info('search');

		//$model->unsetAttributes();  // clear any default values

                 


                if (isset($_GET['sort'])) {

                        Yii::app()->user->setState('activitylog_sort', $_GET['sort']);

                } else if (Yii::app()->user->hasState('activitylog_sort'))

                        $_GET['sort']=Yii::app()->user->getState('activitylog_sort');

				if(isset($_GET['Info'])){

					$model->attributes=$_GET['Info'];

					$model->helpis=$_GET['Info']['helpis'];

				}


		$this->render('allinfo',array(

			'model'=>$model,

		));



Model




public function search()

	{


	// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;

		

		$criteria->with=array('user1', 'user2');


		$criteria->compare('id',$this->id,true);

		$criteria->compare('user1_id',$this->user1_id,true);

		$criteria->compare('user1.userName',$this->user1Name,true);

		$criteria->compare('user2_id',$this->user2_id,true);

		$criteria->compare('user2.userName',$this->user2Name,true);

		$criteria->compare('time',$this->time,true);

		

		if(is_numeric($this->helpis) && $this->helpis == 0){


			$criteria2 = new CDbcriteria;

			$criteria2->compare('user1.helpIs',0,true);

			$criteria2->compare('user2.helpIs',0,true);

			$criteria2->with=array('user1', 'user2');

			$criteria->mergeWith($criteria2, true);

		}else if($this->helpis == 1){

			$criteria2 = new CDbcriteria;

			$criteria2->compare('user1.helpIs',1,true,'OR');

			$criteria2->compare('user2.helpIs',1,true,'OR');

			$criteria2->with=array('user1', 'user2');

			$criteria->mergeWith($criteria2, true);

		}


	

		$sorter = new CSort();

		$sorter->defaultOrder = 'time ASC';

		$sorter->attributes = array(

			'time'=>array(

			  'asc'=>'time',

			  'desc'=>'time desc',

			),

			'user1Name'=>array(

			  'asc'=>'user1.userName',

			  'desc'=>'user1.userName desc',

			),

			'user2Name'=>array(

			  'asc'=>'user2.userName',

			  'desc'=>'user2.userName desc',

			),

			'helpis'=>array(

			  'asc'=>'user1.helpIs, user2.helpIs',

			  'desc'=>'user1.helpIs desc, user2.helpIs desc',

			),




		);

	


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

			'sort'=>$sorter,

			'pagination'=>array(

				'pageSize'=>20,

			),

		));

		

		

	}



Why pdf does not show filtered helpis column? When I sort helpis column, then pdf displays correct order. But after filtering pdf still shows all data (instead of 1s only, for example).

Could you help me in this problem?

Anyone got an idea? Why pdf doesn’t want to accept filter rule?

Kate, I think the problem is this EXTRA SORT COLUMN that you want to apply. I think you need to use another approach.

Can you tell me, or show, the SQL generated or explain better what extra sort attribute do you want to apply?

Another thing is that a complex filter can work with pdf very fine. You just need to correct the code.

Dear Thiago, in fact, my explanation can be to small. I try to expand it. Take a look.

I have table Info with few columns: user1, user2, time, helpis.

user1 is from Users table

user2 is from Users table

time is from Info table

helpis is specific

helpis column have data that come from Users table but not directly. Lets take an example of Users table:

id | userName | helpIs


0 | cat | 0

1 | dog | 1

2 | cow | 0

In Info table I use some rule for data generating:

in Info table helpis will display 0 if both users have 0 in helpIs column

in Info table helpis will display 1 if at least one user have 1 in helpIs column

for example:

id | user1Name | user2Name | helpis


0 | cat | dog | 1 (because cat is 0 and dog is 1)

1 | dog | cow | 1 (because dog is 1 and cow is 0)

2 | cow | cat | 0 (because both have 0)

etc.

It means that helpis come not directly from some table (i.e. helpis has not been rewritten directly from some table), but it has been created in based above rule.

I use this rule in above search() function inside $criteria.

My view allinfo.php:




<?php echo CHtml::button('Print PDF', ... ?>


<?php $this->widget('zii.widgets.grid.CGridView', array(

    'id'=>'info-grid',

    //'dataProvider'=>$dataProvider,

    'dataProvider'=>$model->search(),

    'filter'=>$model,

    'columns'=>array(

        array(

            'name'=>'time',

            'type'=>'raw',

            'value'=>'date("Y-m-d", strtotime($data->time)).\' \'.date("H:i", strtotime($data->time))',

            'visible'=>true,

        ),

        array(

            'name'=>'user1Name',

            'type'=>'raw',

            'value'=>'$data->user1->userName',

            'visible'=>true,

        ),

        array(

            'name'=>'user2Name',

            'type'=>'raw',

            'value'=>'$data->user2->userName',

            'visible'=>true,

        ),

        array(

            'name'=>'helpis',

            'type'=>'raw',

            'filter'=>array(0=>Yii::t('main', 'No'), 1=>Yii::t('main', 'Yes')),

            'value'=>'($data->helpis ? Yii::t(\'main\', \'Yes\') : Yii::t(\'main\', \'No\'))',

            'visible'=>true,

        ),

        array(

            'class'=>'CButtonColumn',

            'template'=>'{view} {update} {delete}',

            'buttons'=>array(

                'view'=>array(

                    'imageUrl' => Yii::app()->request->baseUrl.'/images/view.png',

                    'url'=>'Yii::app()->createUrl("/info/view", array("id" => $data->id))',

                ),

                'update'=>array(

                    'imageUrl' => Yii::app()->request->baseUrl.'/images/update.png',

                    'url'=>'Yii::app()->createUrl("/info/update", array("id" => $data->id))',

                ),

                'delete'=>array(

                    'imageUrl' => Yii::app()->request->baseUrl.'/images/delete.png',

                    'url'=>'Yii::app()->createUrl("/info/delete", array("id" => $data->id))',

                ),

            ),

        ),

    ),

));


if (isset($_GET[...]) - it is not important

{

ob_clean();

$this->widget('ext.pdf.EPDFGrid', array(

    'id'        => 'informe-pdf',

    'fileName'  => 'Information report',

    'dataProvider'  => $model->search(),

    //'filter'=>$model,

    'columns'   => array(

       array(

            'name'=>'time',

            'type'=>'raw',

            'value'=>'date("Y-m-d", strtotime($data->time)).\' \'.date("H:i", strtotime($data->time))',

            'visible'=>true,

        ),

        array(

            'name'=>'user1Name',

            'type'=>'raw',

            'value'=>'$data->user1->userName',

            'visible'=>true,

        ),

        array(

            'name'=>'user2Name',

            'type'=>'raw',

            'value'=>'$data->user2->userName',

            'visible'=>true,

        ),

        array(

            'name'=>'helpis',

            'type'=>'raw',

            'filter'=>array(0=>Yii::t('main', 'No'), 1=>Yii::t('main', 'Yes')),

            'value'=>'($data->helpis ? Yii::t(\'main\', \'Yes\') : Yii::t(\'main\', \'No\'))',

            'visible'=>true,

        ),

    ),

    'config'    => array(

        'title'     => 'Report',

        'colWidths' => array(40, 60, 60, 40),

    ),

));

}



It is now more clear? You think about similar complex filer? I do know if my filter rule is complex. Please look that in widget EPDFGrid I use ‘filter’ too, and maybe it is some inconvenience?? Words Yes/No are displayed correct in pdf. But if I choose for example ‘No’ from the list in top helpis column in Cgridview, then Cgridview displays only record with 0 (No), but pdf displays all record with ‘No’ and ‘Yes’ :(