Gerar PDF de sua aplicação Flex é super simples, existem hoje no mercado algumas soluções open-source para se gerar PDF à partir de sua aplicação Flex, a biblioteca que vou usar neste exemplo é a APDF uma biblioteca gratuita e que serve apenas para desenvolvedores que usam o php como linguagem de server-side.
Claro que você pode por outra vez usar outra linguagem de server-side para gerar o documento em PDF para asp por exemplo ou até para Java, mais ai já é por sua conta e risco.
Limitações do aPDF:
- Não suporta PNG
- Não suporta rawData
- Não suporta embed de fontes
- Não suporta manipulação final do encoder do Acrobat Reader
Ingredientes usados:

Baixe a versão que usa o as3corelib, para fazer o encoder de imagem.
Primeiro passo que vou fazer é adicionar conteúdo ao meu aplicativo, para isso copie o código abaixo e coloque em seu aplicativo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| < ?xml version="1.0" encoding="utf-8"?>
<mx :Application backgroundColor="#f4f4f4" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
</mx><mx :XML id="lista" xmlns="">
<root>
<pedidos>
<pedido>
<produto>
<nome>Escova dentária</nome>
<valor>400</valor>
</produto>
<produto>
<nome>Creme Dental</nome>
<valor>100</valor>
</produto>
<produto>
<nome>Fio Dental</nome>
<valor>50</valor>
</produto>
<produto>
<nome>Sabonete</nome>
<valor>10</valor>
</produto>
</pedido>
</pedidos>
</root>
</mx>
<mx :VDividedBox height="100%" width="100%">
</mx><mx :VBox width="100%" height="50%">
</mx><mx :ColumnChart dataProvider="{lista.pedidos.pedido.produto}" id="graficocoluna" width="100%" height="100%">
</mx><mx :horizontalAxis>
<mx :CategoryAxis dataProvider="{lista.pedidos.pedido.produto}" categoryField="nome"/>
</mx><mx :series>
</mx><mx :ColumnSeries displayName="Pedidos" yField="valor">
</mx><mx :fill>
<mx :SolidColor color="0x7BCE2A"/>
<mx :Legend dataProvider="{graficocoluna}"/>
</mx><mx :VBox width="100%" height="50%">
</mx><mx :DataGrid dataProvider="{graficocoluna.dataProvider}" width="100%" height="100%">
</mx><mx :columns>
<mx :DataGridColumn headerText="Produto" dataField="nome"/>
<mx :DataGridColumn headerText="Preço" dataField="valor"/>
</mx>
<mx :HBox width="100%" horizontalAlign="center" height="45" verticalAlign="middle">
<mx :Button label="Gerar PDF"/>
</mx> |
Com o esqueleto pronto, é hora de programar o o aPDF para adicionar a imagem do gráfico e os resultados do datagrid para o documento pdf.
Primeiro passo é você baixar tanto a biblioteca aPDF e a as3corelib e coloca-las dentro da pasta src, lembre-se que ambas compartilham o mesmo diretório “com”, como diretório principal para o pacote de classes, então só jogar o as3corelib dentro do “com” e o apdf tbm, veja aqui como ficou o meu.

Caso você queira, só baixar aqui um arquevo zip que fiz para ambos, basta só arrastar o conteúdo desse zip para seu diretório src do projeto. Clique aqui para baixar o zip.
Outra coisa que fiz é colocar o diretório php que vem junto com o aPDF dentro do meu servidor XAMPP, na pasta htdocs.
Adicionando objetos ao meu arquevo PDF.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| <mx :Script>
< ![CDATA[
import com.candymandesign.pdf.objects.APDFormat;
import com.candymandesign.pdf.APDF;
private var _pdfObject:APDF;
public function gerarPDF():void{
_pdfObject = new APDF();
_pdfObject.addPage();
_pdfObject.setPageSize(APDFormat.PAGE_SIZE_A4);
_pdfObject.currentPage.addImage(graficocoluna,60,50,50);
_pdfObject.export("http://localhost/apdf/apdf.php");
}
]]>
</mx> |
Gerar a página em pdf é simples, veja que do código acima eu criei um objeto _pdfObject que deriva da instância da classe APDF, depois adiciono ai uma página com o método addPage().
Depois que executo o método addPage(), vou setar o formato desta minha página usando o método setPageSize(), no caso acima uso uma classe auxiliar que é a APDFFormat para gerar em A4; Logo eu pego a página atual ou seja currentPage e adiciono uma imagem usando o método addImage(), este método vem com parametros onde seto o primeiro que é o alvo ou seja uma imagem que venha da classe DisplayObject e depois seto a qualidade desta imagem que vai de zero até 100, o padrão dela é 60, e depois os valores de x, y para posicionar na página e larguar e altura da imagem.
No final de todo o processo de montar a página, etc, eu executo o método export, que aponta para meu arquevo apdf.php que recebe os valores e gera o pdf final.
O resultado do código final é o seguinte.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
| < ?xml version="1.0" encoding="utf-8"?>
<mx :Application backgroundColor="#f4f4f4" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
</mx><mx :Script>
< ![CDATA[
import com.candymandesign.pdf.objects.APDFormat;
import com.candymandesign.pdf.APDF;
private var _pdfObject:APDF;
public function gerarPDF():void{
_pdfObject = new APDF();
_pdfObject.addPage();
_pdfObject.setPageSize(APDFormat.PAGE_SIZE_A4);
_pdfObject.currentPage.addImage(graficocoluna,60,50,50);
_pdfObject.export("http://localhost/apdf/apdf.php");
}
]]>
</mx>
<mx :XML id="lista" xmlns="">
<root>
<pedidos>
<pedido>
<produto>
<nome>Escova dentária</nome>
<valor>400</valor>
</produto>
<produto>
<nome>Creme Dental</nome>
<valor>100</valor>
</produto>
<produto>
<nome>Fio Dental</nome>
<valor>50</valor>
</produto>
<produto>
<nome>Sabonete</nome>
<valor>10</valor>
</produto>
</pedido>
</pedidos>
</root>
</mx>
<mx :VDividedBox height="100%" width="100%">
</mx><mx :VBox width="100%" height="50%">
</mx><mx :ColumnChart dataProvider="{lista.pedidos.pedido.produto}" id="graficocoluna" width="100%" height="100%">
</mx><mx :horizontalAxis>
<mx :CategoryAxis dataProvider="{lista.pedidos.pedido.produto}" categoryField="nome"/>
</mx>
<mx :series>
</mx><mx :ColumnSeries displayName="Pedidos" yField="valor">
</mx><mx :fill>
<mx :SolidColor color="0x7BCE2A"/>
</mx>
<mx :Legend dataProvider="{graficocoluna}"/>
<mx :VBox width="100%" height="50%">
</mx><mx :DataGrid dataProvider="{graficocoluna.dataProvider}" width="100%" height="100%">
</mx><mx :columns>
<mx :DataGridColumn headerText="Produto" dataField="nome"/>
<mx :DataGridColumn headerText="Preço" dataField="valor"/>
</mx>
<mx :HBox width="100%" horizontalAlign="center" height="45" verticalAlign="middle">
<mx :Button label="Gerar PDF" click="gerarPDF()"/>
</mx> |
Ok, até ai tudo bem, geramos nosso primeiro PDF, só que é simples demais, vamos tentar adicionar uma série de opções ao meu pdf.
Outro exemplo é a adição de textos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| < ?xml version="1.0" encoding="utf-8"?>
<mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
</mx><mx :Script>
< ![CDATA[
import com.candymandesign.pdf.objects.APDFDocumentInfo;
import com.candymandesign.pdf.objects.APDFormat;
import com.igorcosta.ArquevoPDFUtil;
import com.candymandesign.pdf.APDF;
public function gerarPDF():void{
var cms:APDF = new APDF();
cms.addPage();
cms.currentPage.addText(texto.text,10,10);
cms.setOrientation(APDFormat.PORTRAIT);
cms.export("http://localhost/apdf/apdf.php");
}
]]>
</mx>
<mx :Button x="500" y="370" label="Gerar PDF" click="gerarPDF()"/>
<mx :RichTextEditor id="texto" x="239" y="31" title="Editor" width="570" height="331">
</mx> |
Criando um gerenciador de controle de impressão
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
| < ?xml version="1.0" encoding="utf-8"?>
<mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
</mx><mx :Script>
< ![CDATA[
import com.candymandesign.pdf.objects.APDFormat;
import com.candymandesign.pdf.APDF;
private var _arquevo:APDF;
public function gerarPDF():void{
_arquevo = new APDF();
for (var i:int=1;i<=pgNumers.value;i++){
_arquevo.addPage(String(i));
}
for (var j:int=0;j <_arquevo.getNumberOfPages();j++){
_arquevo.getPageByID(j).addText("Algum texto criado",10,10,20);
}
switch (formatoPage.selectedIndex){
case 0:
_arquevo.setPageSize(APDFormat.PAGE_SIZE_LETTER);
break;
case 1:
_arquevo.setPageSize(APDFormat.PAGE_SIZE_A3);
break;
case 2:
_arquevo.setPageSize(APDFormat.PAGE_SIZE_A4);
break;
case 3:
_arquevo.setPageSize(APDFormat.PAGE_SIZE_A5);
break;
case 4: _arquevo.setPageSize(APDFormat.PAGE_SIZE_LEGAL);
break;
default:
_arquevo.setPageSize(APDFormat.PAGE_SIZE_A4);
break;
}
switch (orientacaoPage.selectedIndex){
case 0:
_arquevo.setOrientation(APDFormat.LANDSCAPE);
break;
case 1:
_arquevo.setOrientation(APDFormat.PORTRAIT);
break;
default:
_arquevo.setOrientation(APDFormat.PORTRAIT);
break;
}
_arquevo.export("http://localhost/apdf/apdf.php");
}
]]>
</mx>
<mx :Panel width="374" height="218" layout="absolute" title="Gerenciador APDF" x="10" top="27">
</mx><mx :Form x="21" y="25">
</mx><mx :FormItem label="Número de paginas">
<mx :NumericStepper id="pgNumers" value="1" minimum="1" maximum="100" stepSize="1"/>
</mx>
<mx :FormItem label="Formato da pagina">
</mx><mx :ComboBox id="formatoPage">
</mx><mx :Array>
</mx><mx :String> Carta </mx>
<mx :String> A3 </mx>
<mx :String> A4 </mx>
<mx :String> A5 </mx>
<mx :String> Legal </mx>
<mx :FormItem label="Orientação">
</mx><mx :ComboBox id="orientacaoPage">
</mx><mx :Array>
</mx><mx :String>Paisagem</mx>
<mx :String>Vertical</mx>
<mx :Button x="259" y="143" label="Gerar PDF" click="gerarPDF()"/> |
Embora eu tenha usado o aPDF, ainda tem assunto para o próximo post, que neste caso usarei uma biblioteca mais robusta que o aPDF que é o alivePDF.
[Update] Alguns códigos exibidos neste post podem não aparecer corretamente, devido a um problema antigo em um plug-in para exibir código fonte. Pedimos desculpas.
Comentários feitos