Export dat do CSV, XML, TXT apod
- lumen
- Člen | 32
Ahoj, nevím, zda se tento dotaz týká přímo Nette, ale i tak se zeptám: Mám stránku, na ní AppForm se dvěma inputy a tlačítko Export. Jak mám udělat, aby se po kliku na Export poslal uživateli daný soubor s exportem dat z formuláře? Nejde mi o to jak dostat data z formu, ale jak takový soubor vytvořit a poslat uživateli.
Díky
- Ondřej Mirtes
- Člen | 1536
V továrničce na formulář:
$form->addSubmit('export', 'Export')->onClick[] = array($this, 'exportClicked');
A pak metoda:
public function exportClicked($button) {
$this->terminate(new DownloadResponse('cestaKSouboru.csv'));
}
Cesta k souboru by měla být absolutní, tj. včetně APP_DIR, WWW_DIR či kde ten soubor máš.
Editoval Ondřej Mirtes (29. 1. 2010 16:09)
- Vyki
- Člen | 388
Pro jednoduchý export je to pěkně ukázáno v distribuci
v examples. Vtip je v tom, že se v šabloně nenačte
layout
pomocí {extends none}
. Šablona se pak
klasicky nakrmí daty třeba formátu XML, TXT. Pro tyto formáty kdy to chceš
zobrazit a né stáhnout je to ideální. \\Edit: ještě dodávám, že
v šabloně pro nastavení správné hlavičky lze použít makro
{contentType text/xml}
(příklad pro export do XML).
Editoval Vyki (29. 1. 2010 16:35)
- lumen
- Člen | 32
Supr, díky za rady… Ještě mám drobný dotaz tady k tomu:
Ondřej Mirtes napsal(a):
A pak metoda:
public function exportClicked($button) { $this->terminate(new DownloadResponse('cestaKSouboru.csv')); }
Cesta k souboru by měla být absolutní, tj. včetně APP_DIR, WWW_DIR či kde ten soubor máš.
co když nechci vubec pracovat se souborem na úrovni souborového systému
na serveru. Jen si chci třeba vygenerovat nějaký string
a ten
pak v podobě třeba TXT souboru uživateli poslat. Jak na to?
PS: Co přesně provádí funkce terminate()
?
- Ondřej Mirtes
- Člen | 1536
Tak v takovém případě na to budeš muset jít asi starou skoro-PHP cestou…
(převzato z php.net – při jiném typu souboru bude třeba změnit některé hlavičky)
$filename = 'nazev-souboru.txt';
$file = 'stringKeStazeni';
$response = Environment::getHttpResponse();
$response->setHeader('Content-Description', 'File Transfer');
$response->setContentType('text/plain', 'UTF-8');
$response->setHeader('Content-Disposition', 'attachment; filename=' . $filename);
$response->setHeader('Content-Transfer-Encoding', 'binary');
$response->setHeader('Expires', 0);
$response->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
$response->setHeader('Pragma', 'public');
$response->setHeader('Content-Length', strlen($file));
ob_clean();
flush();
echo $file;
$this->terminate();
Metoda Presenter::terminate() – „Correctly terminates Presenter.“ Zkrátka místo nějakého exit() v Nette použiješ $this->terminate(), což zajistí korektní ukončení celého životního cyklu aplikace. Můžeš ji jako parametr předat objekt implementující IPresenterResponse a tím říct, co se má před ukončením vlastně stát/poslat na výstup.
Editoval Ondřej Mirtes (4. 2. 2010 10:08)
- Lopo
- Člen | 277
aktualne pouzivam tento sposob:
na stranke je link na action exportXML, v prezenteri obsluha
<?php
public function handleExportXML()
{
$model=new Obchod_XTab;
$data=$model->getXTab();
$cols=$model->getCols();
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="crosstab.xml"');
header('Cache-Control: max-age=0');
$this->setLayout('empty');
$this->setView('exportXML');
$this->template->cols=$cols;
$this->template->data=$data;
}
?>
kde $cols je zoznam stlpcov, $data su proste data :)
sablona:
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
<ss:Styles>
<ss:Style ss:ID="0">
<ss:Font ss:Bold="1"/>
<ss:Alignment ss:Horizontal="Center" ss:WrapText="0"/>
<ss:Interior ss:Color="#B8CCE4" ss:Pattern="Solid"/>
</ss:Style>
<ss:Style ss:ID="1">
<ss:Alignment ss:WrapText="0"/>
<ss:NumberFormat ss:Format="0"/>
</ss:Style>
<ss:Style ss:ID="2">
<ss:Alignment ss:WrapText="0"/>
<ss:NumberFormat ss:Format="Fixed"/>
</ss:Style>
<ss:Style ss:ID="3">
<ss:Alignment ss:WrapText="0"/>
</ss:Style>
</ss:Styles>
<ss:Worksheet ss:Name="Sheet1">
<ss:Table>
<ss:Row>
{foreach $cols as $col}
<ss:Cell ss:StyleID="0"><ss:Data ss:Type="String">{!$col['name']}</ss:Data></ss:Cell>
{/foreach}
</ss:Row>
{foreach $data as $row}
<ss:Row>
{foreach $cols as $col}
<ss:Cell ss:StyleID="{if $col['name']=='cipa' || $col['name']=='voj'}1{elseif $iterator->getCounter()<17}3{else}2{/if}"><ss:Data ss:Type="{if $col['name']=='cipa' || $col['name']=='voj' || $iterator->getCounter()>=17}Number{else}String{/if}">{$row[$col['name']]}</ss:Data></ss:Cell>
{/foreach}
</ss:Row>
{/foreach}
</ss:Table>
</ss:Worksheet>
</ss:Workbook>
layout empty je proste prazdny subor @empty.phtml – ale podla predchadzajucich prispevkov to asi presunem do sablony ako extends, podobne aj contenttype hlavicku
v sablone potom je cez if-y prepinanie datovych typov buniek
mam aj trosku upraveny sposob, tam nejdem cez $cols ale len cez data a popisky stlpcov su natvrdo v sablone
tento sposob je bez problemov pouzitelny aj na CSV, tam sa potom pouzije
contenttype text/csv, excel je vsak co sa tyka importu csv strasne blby kvoli
jeho automatickym urcovaniam datoveho typu buniek a preto som robil XML
tuna ukazany je XML bez problemov otvoritelne v exceli 2k7 a podla informacii
od pouzivatelov by malo byt aj v exceli 2k3
- PetrP
- Člen | 587
lumen napsal(a):
co když nechci vubec pracovat se souborem na úrovni souborového systému na serveru. Jen si chci třeba vygenerovat nějaký
string
a ten pak v podobě třeba TXT souboru uživateli poslat. Jak na to?
Můžeš poslat jiný response, třeba RenderResponse. (lze poslat i šablonu)