Jump to content
Sign in to follow this  
Zazhir

Destroy or clean TSaveDialog after save

Recommended Posts

I have a form that has some buttons to export a qry result to differents files formats. 

I'am using a TSaveDialog, that is located in the main Form [frmMainSIG]. The component works just fine, but when I click in more than one button that export to file, gives a access violation message. Tried to "clear" the component create at my main form [frmMainSIG]. I've tried the `Free` method and the `FreeAndNil`, but they don't destroy my component. 

 

The code of export to pdf ⬇

var
  Excel: variant;
  caminho, caminhoFicha, pastaFicha, edtCaminhoRelatorio: string;
  linha: integer;
begin
  try
    if not frmMainSIG.frmSIG.dlgFileSave.Execute then exit;
    caminho := ExtractFilePath(frmMainSIG.frmSIG.dlgFileSave.Name) + ExtractFileName(frmMainSIG.frmSIG.dlgFileSave.FileName);
    edtCaminhoRelatorio := caminho;

    ShowMessage('Ficaremos inativos até a geração completas dos dados!');

    pastaFicha := 'Imovel';

    frmSig.jvAlertaProgress.MessageText := 'Iniciado!';
    frmSig.jvAlertaProgress.Execute;
    frmExportarImovel.progressBarQry.Max := frmImovel.qryPesq.RecordCount;

    frmImovel.qryPesq.First;

    linha := 4;
    Excel := CreateOleObject('Excel.Application');
    Excel.Visible := false;
    Excel.Workbooks.open(frmMainSIG.frmSIG.caminhoFicha + pastaFicha + '\modeloImovelSelecao.xlsx');

    while not (frmImovel.qryPesq.Eof) do
    begin
      atualizaTela;

      Excel.WorkBooks[1].Sheets[1].Range['B'+inttostr(Linha+1),'J'+inttostr(Linha+1)].RowHeight := 35;
      Excel.ActiveSheet.Range['B'+inttostr(Linha+1)+':J'+inttostr(linha+1)].Borders.LineStyle := 1;
      Excel.WorkBooks[1].Sheets[1].Range['B'+inttostr(Linha+1),'J'+inttostr(Linha+1)].NumberFormat := '@';

      Excel.ActiveSheet.Cells[Linha+1,2] := frmImovel.qryPesq.FieldByName('IMOV_ID_CODPREF').asString;
      Excel.ActiveSheet.Cells[Linha+1,3] := frmImovel.qryPesq.FieldByName('IMOV_TX_PROPRIETARIO').asString;
      Excel.ActiveSheet.Cells[Linha+1,4] := frmImovel.qryPesq.FieldByName('IMOV_TX_LOGRADOURO').asString;
      Excel.ActiveSheet.Cells[Linha+1,5] := frmImovel.qryPesq.FieldByName('IMOV_NR_NUMERO_PREDIAL').asString;
      Excel.ActiveSheet.Cells[Linha+1,6] := frmImovel.qryPesq.FieldByName('IMOV_TX_TIPO_IMOVEL').asString;
      Excel.ActiveSheet.Cells[Linha+1,7] := frmImovel.qryPesq.FieldByName('IMOV_NR_QUADRA').asString;
      Excel.ActiveSheet.Cells[Linha+1,8] := frmImovel.qryPesq.FieldByName('IMOV_NR_PISCINA').asString;
      Excel.ActiveSheet.Cells[Linha+1,9] := frmImovel.qryPesq.FieldByName('IMOV_NR_AREA_CONSTRUIDA_PREF').asString;
      Excel.ActiveSheet.Cells[Linha+1,10] := frmImovel.qryPesq.FieldByName('IMOV_NR_AREA_GERAL_COM_DESC_BEIRAL').asString;

      frmImovel.qryPesq.Next;
      linha := linha + 1;
      sleep(100);
    end;

    sleep(100);
    Excel.ActiveWorkbook.saveas(edtCaminhoRelatorio + ' RELATORIO_SIGATI' + '.xlsx');

    sleep(1000);
    Excel.ActiveWorkbook.Worksheets[1].ExportAsFixedFormat(0, edtCaminhoRelatorio + ' RELATORIO.pdf',0,-1,0);

    Excel.Workbooks[1].Close;
    Excel.Quit;
    Excel := Unassigned;

    ShowMessage('Relatório gerado com Sucesso! 😊');
    frmSig.jvAlertaProgress.MessageText := 'O Relatório foi Gerado com Sucesso!';
    frmSig.jvAlertaProgress.Execute;

    progressBarQry.Position := 0;
    lblProgresso.Caption := '0 de 0';
    lblProgresso.Refresh;

    if Application.MessageBox('Deseja abrir o arquivo?', 'Opção', MB_YESNO+MB_ICONINFORMATION) = mrYes then
    begin
      ShellExecute(0, 'open', PCHAR(frmMainSIG.frmSIG.dlgFileSave.FileName + ' RELATORIO.pdf'), nil, nil, SW_SHOWNORMAL);
      FreeAndNil(frmMainSIG.frmSIG.dlgFileSave);
    end;
    FreeAndNil(frmMainSIG.frmSIG.dlgFileSave);

  except
    on E: Exception do
    begin
      ShowMessage(E.Message);
     end;
    end;
end;

 

and the code to export to csv (excel file)

var
  Excel: Variant;
  Linha, i : Integer;
  mostrar : boolean;
  caminho, edtCaminhoRelatorio, nome, extensao, saveDir: string;
  saveCSV: TSaveDialog;
  f: TextFile;

begin
  if not frmImovel.qryPesq.IsEmpty then
    begin
    if Application.MessageBox('Deseja acompanhar o Excel carregando as informações?', 'Opção',MB_YESNO+MB_ICONINFORMATION) = mrYes then
      begin
        mostrar := true;
        showMessage('Não clique no Excel até que o procedimento termine, isso interrompe o carregamento.');
      end
      else
      begin
        mostrar := false;
        showMessage('O Excel está oculto gerando as informações. Clique em "OK" para continuar. O sistema ficará desabilitado até que termine.');
      end;

      frmSig.jvAlertaProgress.MessageText := 'Iniciado!';
      frmSig.jvAlertaProgress.Execute;
      frmExportarImovel.progressBarQry.Max := frmImovel.qryPesq.RecordCount;

      frmImovel.qryPesq.First;
      Excel := CreateOleObject('Excel.Application');
      Excel.Workbooks.Add;
      Excel.Visible := mostrar;
      Linha := 1;

      for i := 0 to frmImovel.qryPesq.FieldCount - 1 do
        Excel.WorkBooks[1].Sheets[1].Cells[Linha,i+1] := frmImovel.qryPesq.Fields[i].DisplayName;
        Linha := 2;

      while not frmImovel.qryPesq.Eof do
      begin
        for i := 0 to frmImovel.qryPesq.FieldCount - 1 do
          Excel.WorkBooks[1].Sheets[1].Cells[Linha,i+1] := frmImovel.qryPesq.Fields[i].Text;

          frmImovel.qryPesq.Next;
          Linha:=Linha+1;
          atualizaTela;
      end;

      Excel.Visible := false;
      sleep(100);

      // Salvar como CSV
      saveCSV:= TSaveDialog.Create(Self);
      saveCSV.Title:= 'Salvar como CSV';
      saveCSV.Filter:= 'Arquivo CSV|*.csv';
      saveCSV.DefaultExt:= 'csv';
      saveCSV.FilterIndex:= 1;

      if saveCSV.Execute then
      begin
        AssignFile(f, saveCSV.FileName);
      end;

      Excel.ActiveWorkbook.saveas(saveCSV.FileName);
      Excel.Workbooks[1].Close;
      Excel.Quit;
      Excel := Unassigned;

      showMessage('Arquivo CSV salvo com sucesso!');

      frmSig.jvAlertaProgress.MessageText := 'O Relatório foi Gerado com Sucesso!';
      frmSig.jvAlertaProgress.Execute;

      progressBarQry.Position := 0;
      lblProgresso.Caption := '0 de 0';
      lblProgresso.Refresh;

      if Application.MessageBox('Deseja abrir o arquivo?', 'Opção', MB_YESNO+MB_ICONINFORMATION) = mrYes then
      begin
        ShellExecute(Handle, 'open', PChar(saveCSV.FileName), nil, nil, SW_SHOWNORMAL);
        FreeAndNil(frmMainSIG.frmSIG.dlgFileSave);
      end;
      FreeAndNil(frmMainSIG.frmSIG.dlgFileSave);

      end
      else
        showMessage('Tabela não possui dados para serem exportados!');
end;

After a click in this buttons, what I need to do is to destroy the frmMainSIG.frmSIG.dlgFileSave, to when I click in another button, the component are clean and ready to use!

The line that "breaks" my code, only after a already generate the first file, is the if not frmImovel.qryPesq.IsEmpty then (first line).

How can I do that, because the FreeAndNil method is not working for this case 😞

Edited by Zazhir

Share this post


Link to post
12 minutes ago, Zazhir said:

After a click in this buttons, what I need to do is to destroy the frmMainSIG.frmSIG.dlgFileSave, to when I click in another button, the component are clean and ready to use!

The line that "breaks" my code, only after a already generate the first file, is the if not frmImovel.qryPesq.IsEmpty then (first line).

How can I do that, because the FreeAndNil method is not working for this case 😞

Please define "the component are clean and ready to use". You can reuse the dialog component without freeing it. In this case your freeing it and set the reference to nil (freeandnil) then try to access a nil object reference.

 

You cannot do that. Just remove FreeAndNil. In case you would like to use a fresh dialog object just use a local variable instead of a global one then you can free it at the end of the procedure/method wherever this code snippet was copied from.

 

 

  • Like 1

Share this post


Link to post

confused code!

try create your "Excel" just one time... out any procedure! for example, before any use in your unit. Then, when all end, just free it! 

Quote

// your unit using Excel obj

...

implementation

var

   Excel :variant;

...

// your code to use it

// when needs open other file, just close old-file and open a new-file.  if needs new actions, just clear your Excel object... etc...

 

OnCreate from "Form" // or initialization section

     Excel := CreateOleObject('Excel.Application'); // avoid create it many times if not really necessary do it!!! 

 

OnDestroy from "Form" // or finalization section

      Excel.Quit;

      Excel := Unassigned; // or any other way to free it

 

  • Confused 1

Share this post


Link to post
6 hours ago, Zazhir said:

if Application.MessageBox('Deseja abrir o arquivo?', 'Opção', MB_YESNO+MB_ICONINFORMATION) = mrYes then

begin

   ShellExecute(Handle, 'open', PChar(saveCSV.FileName), nil, nil, SW_SHOWNORMAL);  // try execute external command after conclude your code-actions... any error here, your FreeAndNil() can dont be executed at all.

   FreeAndNil(frmMainSIG.frmSIG.dlgFileSave);

end;

try some like this:

Quote

try

//...

LOpenMyCSVFile := Application.MessageBox('Deseja abrir o arquivo?', 'Opção', MB_YESNO+MB_ICONINFORMATION) = mrYes;

...

finally

   FreeAndNil(frmMainSIG.frmSIG.dlgFileSave);

end;

/

if LOpenMyCSVFile then

    ShellExecute(Handle, 'open', PChar(saveCSV.FileName), nil, nil, SW_SHOWNORMAL); 

 

 

  • Like 1

Share this post


Link to post
1 hour ago, programmerdelphi2k said:

FreeAndNil(frmMainSIG.frmSIG.dlgFileSave);

What a great suggestion to free a component from a form. That's a huge NO. If it's in a try ... finally it must be a local reference not a global one. programmerdelphi2k as others wrote please make sure that your reply brings something to the topic here the goal is to help and not to reply to every post.

 

If a reference is freed in a code it should be local:

 

var
  dlgFileSave: TSaveDialog;

begin
  dlgFileSave:=TSaveDialog.create(nil);
  try
    ...
  finally
    dlgFileSave.Free;
  end;   
end;

The code to save csv is almost how it should be, the problem there is that the wrong reference is freed. Instead of frmMainSIG.frmSIG.dlgFileSave the saveCSV should be freed. 

 

var
  Excel: Variant;
  Linha, i : Integer;
  mostrar : boolean;
  caminho, edtCaminhoRelatorio, nome, extensao, saveDir: string;
  saveCSV: TSaveDialog;
  f: TextFile;

begin
  if not frmImovel.qryPesq.IsEmpty then
    begin
    if Application.MessageBox('Deseja acompanhar o Excel carregando as informações?', 'Opção',MB_YESNO+MB_ICONINFORMATION) = mrYes then
      begin
        mostrar := true;
        showMessage('Não clique no Excel até que o procedimento termine, isso interrompe o carregamento.');
      end
      else
      begin
        mostrar := false;
        showMessage('O Excel está oculto gerando as informações. Clique em "OK" para continuar. O sistema ficará desabilitado até que termine.');
      end;

      frmSig.jvAlertaProgress.MessageText := 'Iniciado!';
      frmSig.jvAlertaProgress.Execute;
      frmExportarImovel.progressBarQry.Max := frmImovel.qryPesq.RecordCount;

      frmImovel.qryPesq.First;
      Excel := CreateOleObject('Excel.Application');
      Excel.Workbooks.Add;
      Excel.Visible := mostrar;
      Linha := 1;

      for i := 0 to frmImovel.qryPesq.FieldCount - 1 do
        Excel.WorkBooks[1].Sheets[1].Cells[Linha,i+1] := frmImovel.qryPesq.Fields[i].DisplayName;
        Linha := 2;

      while not frmImovel.qryPesq.Eof do
      begin
        for i := 0 to frmImovel.qryPesq.FieldCount - 1 do
          Excel.WorkBooks[1].Sheets[1].Cells[Linha,i+1] := frmImovel.qryPesq.Fields[i].Text;

          frmImovel.qryPesq.Next;
          Linha:=Linha+1;
          atualizaTela;
      end;

      Excel.Visible := false;
      sleep(100);

      // Salvar como CSV
      saveCSV:= TSaveDialog.Create(nil);
      try
        saveCSV.Title:= 'Salvar como CSV';
        saveCSV.Filter:= 'Arquivo CSV|*.csv';
        saveCSV.DefaultExt:= 'csv';
        saveCSV.FilterIndex:= 1;

        if saveCSV.Execute then
        begin
          AssignFile(f, saveCSV.FileName);
        end;

        Excel.ActiveWorkbook.saveas(saveCSV.FileName);
        Excel.Workbooks[1].Close;
        Excel.Quit;
        Excel := Unassigned;

        showMessage('Arquivo CSV salvo com sucesso!');

        frmSig.jvAlertaProgress.MessageText := 'O Relatório foi Gerado com Sucesso!';
        frmSig.jvAlertaProgress.Execute;

        progressBarQry.Position := 0;
        lblProgresso.Caption := '0 de 0';
        lblProgresso.Refresh;

        if Application.MessageBox('Deseja abrir o arquivo?', 'Opção', MB_YESNO+MB_ICONINFORMATION) = mrYes then
          ShellExecute(Handle, 'open', PChar(saveCSV.FileName), nil, nil, SW_SHOWNORMAL);
       finaly
         saveCSV.Free;
       end;  
      end
      else
        showMessage('Tabela não possui dados para serem exportados!');
end;

 

 

  • Like 2
  • Haha 1

Share this post


Link to post

Thanks for the help everyone!! 😄

quick update here: I've solved the problem!!

 

What I has to do is just create a new component in every button (belive that's not the more efficent way, but it is the more simple that I found).

just like that: 

procedure TfrmExportarImovel.btnPdfClick(Sender: TObject);
var
  Excel: variant;
  caminho, caminhoFicha, pastaFicha, edtCaminhoRelatorio: string;
  linha: integer;
  savePdf: TSaveDialog; //new component created
begin
  try
    savePdf:= TSaveDialog.Create(Self); //using a fresh and new component 
    if savePdf.Execute then
    
    
    //....
    
  except
    on E: Exception do
    begin
      ShowMessage(E.Message);
     end;
    end;
end;   

Have done this for all the buttons that i use to export. 😉

Share this post


Link to post
8 hours ago, Lajos Juhász said:

FreeAndNil(frmMainSIG.frmSIG.dlgFileSave);

this code it's not mine! I just say "where" put it...   on "try-finally"

 

as I said on first post, "CODE CONFUSED"!!!

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×