Answers.Body: <p>For a plugin-based solution, it's possible to create Reports based on arbitrary queries using <a href="http://sprout.barrelstrengthdesign.com/craft-plugins/reports" rel="nofollow">Sprout Reports</a>. Reports created in Sprout Reports can all be viewed in the same area of the Control Panel. A user can run reports from a simple user interface and export the results as a CSV. </p>
  
  <p>You can create reports that are just a specific query or customizable reports that give the user any number of options to customize the results.</p>
  
  <p>A report based on a Custom SQL query can be created in the interface, or you can create a more customized report via the <a href="http://sprout.barrelstrengthdesign.com/craft-plugins/reports/docs/custom-reports/data-sources" rel="nofollow">Custom Reports Data Source API</a>.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-10-17T16:06:18.987Z
Answers.LastActivityDate: 2016-10-17T16:06:18.987Z
Answers.UserDisplayName: Ben Parizek
Answers.Body: <p>Craft's <a href="https://github.com/pixelandtonic/Craft-Release/blob/master/app/services/HttpRequestService.php">HttpRequestService</a> has a <a href="https://github.com/pixelandtonic/Craft-Release/blob/master/app/services/HttpRequestService.php#L660">sendFile</a> method (available via <code>craft()-&gt;request-&gt;sendFile()</code>).</p>
  
  <p>The 3rd parameter is an optional <code>$options</code> array that accepts key => value pairs.  One of those is <code>'forceDownload' =&gt; true</code> and when that is passed in, Craft will set the proper HTTP headers to force the given file to be sent to the browser as a download.</p>
  
  <p>You could do this from inside an action in one of your plugin's <a href="http://buildwithcraft.com/docs/plugins/controllers">controllers</a>.  Something like:</p>
  
  <pre><code>public function actionDownloadFile()
  {
      // Grab your file content from wherever you have it stored. Here, it's just hard coded into a string.
      $contents = 'row1column1,row2column2'.PHP_EOL.'row2column1,row2column2'.PHP_EOL;    
  
      // Call sendFile, giving it the name of the file to send, the contents and tell it to force a download to the browser.
      craft()-&gt;request-&gt;sendFile('filename.csv', $contents, array('forceDownload' =&gt; true));
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-08-26T16:14:02.337Z
Answers.Text: That sounds exactly like what I need Brad, but I have to be honest I'd have no idea how to implement it. I spent 3 days trying to learn how to write Craft Plugins and got nowhere (my brain's fault, not the documentation's). The plugin I've written is literally one template that outputs entries the same way as a front end template would. How would I implement your answer in simple terms?
Answers.UserDisplayName: darylknight
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-08-26T17:07:13.077Z
Answers.Text: Updated the answer with some more details.
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-26T10:19:45.670Z
Answers.Text: I've implemented the above on one of our sites. However it appears to split fields on commas in the title of the entry and not escape them for csv files. I can code for the data to be escaped before it is used in the sendFile function but wanted to check that I wasn't missing something that would automatically escape it or change the delimiter as a param?
Answers.UserDisplayName: Lettie
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-07-05T14:30:55.233Z
Answers.Text: Brad this is great, but an extension on how to pull all contents from a table and export to CSV would be AWESOME!
Answers.UserDisplayName: H2ONOCK
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-08-26T16:06:07.550Z
Answers.LastActivityDate: 2014-08-26T17:04:33.633Z
Answers.LastEditDate: 2014-08-26T17:04:33.633Z
Answers.UserDisplayName: Brad Bell
Body: <p>The website I'm building enables users to book places on events. This is simply a form which creates an entry in a channel containing 2 fields: "related user" and "related event". In the control panel I've written a simple plugin which displays all the entries in that channel exactly the same as the control panel normally would do, but now I can display any fields I want instead of just title and post date.</p>
  
  <p>My client wants to be able to export the entry data from the control panel into Excel (xls or csv). What's the simplest way to do this? I read somewhere about changing http headers to force a download of a file, so can I just force a browser download of a dynamically generated page containing a table of all that entry data?</p>
  
  <p>When I say "force a download" I mean I probably just need a button that says "Export", but it should download the file instead of opening it in the browser.</p>
  
Tags: <entries>
Title: How can I force a download of entry data to an excel file?
ThreadText: # How can I force a download of entry data to an excel file?
  
  (Asked by: username_0 on 2014-08-26)
  
  The website I'm building enables users to book places on events. This is simply a form which creates an entry in a channel containing 2 fields: "related user" and "related event". In the control panel I've written a simple plugin which displays all the entries in that channel exactly the same as the control panel normally would do, but now I can display any fields I want instead of just title and post date.
  
  My client wants to be able to export the entry data from the control panel into Excel (xls or csv). What's the simplest way to do this? I read somewhere about changing http headers to force a download of a file, so can I just force a browser download of a dynamically generated page containing a table of all that entry data?
  
  When I say "force a download" I mean I probably just need a button that says "Export", but it should download the file instead of opening it in the browser.
  
  **Tags:** entries
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_2 on 2014-08-26. Score: 8 | Accepted answer
  
  Craft's [HttpRequestService](https://github.com/pixelandtonic/Craft-Release/blob/master/app/services/HttpRequestService.php) has a [sendFile](https://github.com/pixelandtonic/Craft-Release/blob/master/app/services/HttpRequestService.php#L660) method (available via `craft()->request->sendFile()`).
  
  The 3rd parameter is an optional `$options` array that accepts key => value pairs. One of those is `'forceDownload' => true` and when that is passed in, Craft will set the proper HTTP headers to force the given file to be sent to the browser as a download.
  
  You could do this from inside an action in one of your plugin's [controllers](http://buildwithcraft.com/docs/plugins/controllers). Something like:
  
  ```
  public function actionDownloadFile()
  {
      // Grab your file content from wherever you have it stored. Here, it's just hard coded into a string.
      $contents = 'row1column1,row2column2'.PHP_EOL.'row2column1,row2column2'.PHP_EOL;    
  
      // Call sendFile, giving it the name of the file to send, the contents and tell it to force a download to the browser.
      craft()->request->sendFile('filename.csv', $contents, array('forceDownload' => true));
  }
  
  ```
  
  > **Comments:**
  > **username_0**: That sounds exactly like what I need username_2, but I have to be honest I'd have no idea how to implement it. I spent 3 days trying to learn how to write Craft Plugins and got nowhere (my brain's fault, not the documentation's). The plugin I've written is literally one template that outputs entries the same way as a front end template would. How would I implement your answer in simple terms?  
  > **username_2**: Updated the answer with some more details.  
  > **username_3**: I've implemented the above on one of our sites. However it appears to split fields on commas in the title of the entry and not escape them for csv files. I can code for the data to be escaped before it is used in the sendFile function but wanted to check that I wasn't missing something that would automatically escape it or change the delimiter as a param?  
  > **username_4**: username_2 this is great, but an extension on how to pull all contents from a table and export to CSV would be AWESOME!  
  
  ---
  
  ### Answer by username_1 on 2016-10-17. Score: 2
  
  For a plugin-based solution, it's possible to create Reports based on arbitrary queries using [Sprout Reports](http://sprout.barrelstrengthdesign.com/craft-plugins/reports). Reports created in Sprout Reports can all be viewed in the same area of the Control Panel. A user can run reports from a simple user interface and export the results as a CSV.
  
  You can create reports that are just a specific query or customizable reports that give the user any number of options to customize the results.
  
  A report based on a Custom SQL query can be created in the interface, or you can create a more customized report via the [Custom Reports Data Source API](http://sprout.barrelstrengthdesign.com/craft-plugins/reports/docs/custom-reports/data-sources).
  
  
  ---
  
  