FastReport interno no banco de dados


Útilizo os arquivos no banco de dados para não precisar atualizar em todas as maquinas um determinado arquivo, adiciono no banco de dados e no momento de visulizar o documento e sistema exporta apenas o arquivo que vai ser visualizado e o exclui logo em seguida!
Para começar vamos fazer o modo de importar para o banco de dados e exportar em caso de precisar o arquivo;

Vamos precisar dos componentes

pnlBotoes: TPanel;
btnNovo: TBitBtn;
btnExcluir: TBitBtn;
btnCancelar: TBitBtn;
BtnLimpar: TBitBtn;
btnConfirmar: TBitBtn;
btnAlterar: TBitBtn;
dbgrPrincipal: TDBGrid;
flbArquivos: TFileListBox;
dsRelatorios: TDataSource;

Vão ficar disposto desta forma (Não a necessidade de ficar idêntico apenas exemplo);


Para o armazenamento vamos precisar dos campos:


Eu utilizarei um clientDataSet sem armazenamento em banco de dados.(apenas para ficar genérico para vocês)
Criaremos uma pasta chamada "Atualizações" dentro da pasta do Sistema onde colocaremos os arquivos FastReport importar, no componente TFileListBox vamos colocar a properties Mask como "*.fr3"


No evento de OnCriate colocaremos o código para verificar se contem a pasta  "Atualizações" e criação se a mesma não existir e o carregamento do nome dos aquivos para o TFileListBox

procedure TFRelatorio.DoCreate;
begin
  cdsRelatorios.CreateDataSet;
  if ForceDirectories(ExtractFilePath(Application.ExeName) + 'Atualizações') then
    flbArquivos.Directory := ExtractFilePath(Application.ExeName) + 'Atualizações';
  flbArquivos.Directory := ExtractFilePath(Application.ExeName) + 'Atualizações';
end;  

No botão "Adicionar" vamos colocar o código que ira carregar o conteúdo dos arquivos que foram carregados para o TFileListBox;

procedure TFRelatorio.btnAdicionarClick(Sender: TObject);
var i: integer;
   fr3: string;
begin
  for I := 0 to flbArquivos.Items.Count - 1 do begin
    fr3 := ExtractFilePath(Application.ExeName) + 'Atualizações' + '\' + flbArquivos.Items[I];
    if cdsRelatorios.Locate('DESCRICAO', VarArrayOf([flbArquivos.Items[I]]),[]) then begin
      cdsRelatorios.edit;
    end else begin
      cdsRelatorios.Append;
      cdsRelatoriosDESCRICAO.Value := flbArquivos.Items[I];
    end;
    cdsRelatoriosDATA.Value := Date;
    cdsRelatoriosRELATORIO.LoadFromFile(fr3);
    cdsRelatorios.Post;
    DeleteFile(ExtractFilePath(Application.ExeName) + 'Atualizações' + '\' + flbArquivos.Items[I]);
  end;
  flbArquivos.Clear;
end;  

O botão "Excluir" e "Limpar" não muda muito do padrão: 

procedure TFRelatorio.btnExcluirClick(Sender: TObject);
begin
  cdsRelatorios.Delete;
end;

procedure TFRelatorio.BtnLimparClick(Sender: TObject);
begin
  while cdsRelatoriosDESCRICAO.Value <> EmptyWideStr do
    cdsRelatorios.Delete;
end;  

No exportar vamos apenas pegar o conteúdo e o nome dele e criar o arquivo novamente

procedure TFRelatorio.btnExportarClick(Sender: TObject);
var fr3: string;
begin
  ForceDirectories(ExtractFilePath(Application.ExeName) + 'Relatórios');
  cdsRelatorios.First;
  while not cdsRelatorios.Eof do begin
    fr3 := ExtractFilePath(Application.ExeName) + 'Relatórios' + '\' + cdsRelatoriosDESCRICAO.Value;
    cdsRelatoriosRELATORIO.SaveToFile(fr3);
    cdsRelatorios.Next;
  end;
end;  

Assim já conseguimos armazenar e exportar os arquivos no banco de dados:

Para fazer a leitura do documento vamos precisar de: 

pnlBotao: TPanel;
BtnVisualizar: TBitBtn;
frxReport: TfrxReport;

Os componentes vão ficar mais ou menos assim no meu exemplo (Obs: Eu vou fazer tudo na mesma tela no exemplo, se precisar de um exemplo mais complexo eu faço outro post)


Esta é uma função para localizar o Arquivo na tabela que contem os arquivos, ela ira nos retornar True se conter o documento e apos isso salvar o arquivo na pasta do Sistema com o nome de Relatório.fr3

function TFRelatorio.Ler_Arquivo_do_Banco(const AArquivo: String): Boolean;
var
  lArquivofr3 : String;
begin
  Result := cdsRelatorios.Locate('DESCRICAO', AArquivo, []);
  if Result then begin
    lArquivofr3 := ExtractFilePath(Application.ExeName) + 'Relatório.fr3';
    TMemoField(cdsRelatorios.FieldByName('RELATORIO')).SaveToFile(lArquivofr3);
    Self.frxReport.LoadFromFile(lArquivofr3);
  end;
end;

No botão de "Visualizar" vai o código que vai utilizar o Ler_Arquivo_do_Banco e localizando irá fazer a visualização do documento e apos isto excluir o documento da pasta.

procedure TFRelatorio.BtnVisualizarClick(Sender: TObject);
begin
  if Ler_Arquivo_do_Banco('Relatorio_Teste.fr3') then begin
    frxReport.PrepareReport;
    frxReport.ShowReport;
    DeleteFile(ExtractFilePath(Application.ExeName) + 'Relatório.fr3');
  end;
end;


Exemplo: Download do exemplo

5 comentários:

  1. Isto é bom pra quem tem banco de dados porreta. Eu tenho no sistema que emprego duas possibilidades uma referenciando um diretório e outro armazenando no DB.

    Vejo se entendi. Voce salva na tabela, depois dá download para o disco, abre o fastreport e depois que fecha deleta o arquivo? O fastreport não tem um recurso para carregar direto do stream?

    Bom artigo. Se for isto é mais uma alternativa.

    ResponderExcluir
    Respostas
    1. Isso mesmo com os relatórios no banco de dados e extraindo apenas na hora de impressão, se o cliente tem mais de uma maquina na empresa não iria precisar passar todas atualizando uma pasta de relatório seria apenas colocar no banco que todas as maquinas estariam com os documentos atualizados! Sobre ter o recurso do stream até acho que tem, só não tinha pensado nisso mas se tiver e uma boa opção vou até testar isso.

      Excluir
  2. Segui tua dica e não estou salvando em disco, recuperando direto como stream do banco de dados : frxReport.LoadFromStream(cdsRelatorios.CreateBlobStream(cdsRelatoriosRELATORIO,bmRead))

    ResponderExcluir
  3. Estou com uma duvida, tenho no banco de dados firebird uma coluna do tipo blob texto, eu consigo salvar e recuperar de um campo tipo RichEdit1 com toda formatação, mais como eu poderia imprimir do bando de dados no fastreport em uma band masterdata, com as formatações do texto salvo no banco teria alguma dica de como posso fazer pois os testes que eu fiz não carrega só fica ???????????????? ????????? ?

    ResponderExcluir