Search code examples
delphitopendialog

Why does the compiler say my form's variable is undeclared in my procedure?


I would like to read a CSV file to Delphi (DBGrid) as suggested in the sample project here. I have a simple form where I defined TOpenDialog and elements from the TCsvTransform. The project does not compile when I am trying to create a procedure that would pass the file path from the TOpenDialog to the procedure responsible for reading the CSV file.

procedure ReadCSVFile;
var
  SS: TStringStream;
  OS: TFileStream;
begin
  OS := TFileStream.Create(MainOpenDialog.FileName, fmCreate);
  SS := TStringStream.Create;
  try
    ClientDataSet1.SaveToStream(SS, dfXML);
    with TCsvTransform.Create do
    try
      Transform(DPToCsv, SS, TStream(OS));
    finally
      Free;
    end;

  finally
    SS.Free;
    OS.Free;
  end;
end;

The compiler says that MainOpenDialog is undeclared. The full code, where I think that I declared the Open Dialog elements is below.

unit geoimp;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.Buttons, Vcl.StdCtrls,
  Vcl.Grids, Vcl.DBGrids, Data.DB, Datasnap.DBClient, ShlObj;


 const
  shfolder = 'ShFolder.dll';

type
  TMainForm = class(TForm)
    MainPageControl: TPageControl;
    ImportTab: TTabSheet;
    MapPreviewTab: TTabSheet;
    GeoMatchingTab: TTabSheet;
    ImportDBGrid: TDBGrid;
    ImportLbl: TLabel;
    SlctImportDta: TSpeedButton;
    MainClientData: TClientDataSet;
    MainDataSource: TDataSource;
    MainOpenDialog: TOpenDialog;
    procedure SlctImportDtaClick(Sender: TObject);
    procedure ReadCSVFile;

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure ReadCSVFile;
var
  SS: TStringStream;
  OS: TFileStream;
begin
  OS := TFileStream.Create(MainOpenDialog.FileName, fmCreate);
  SS := TStringStream.Create;
  try
    ClientDataSet1.SaveToStream(SS, dfXML);
    with TCsvTransform.Create do
    try
      Transform(DPToCsv, SS, TStream(OS));
    finally
      Free;
    end;

  finally
    SS.Free;
    OS.Free;
  end;
end;

procedure TMainForm.SlctImportDtaClick(Sender: TObject);
begin
  // Create the open dialog object - assign to our open dialog variable
  MainOpenDialog := TOpenDialog.Create(self);

  // Set up the starting directory to be the current one
  MainOpenDialog.InitialDir := GetCurrentDir;

  // Only allow existing files to be selected
  MainOpenDialog.Options := [ofFileMustExist];

  // Allow only .dpr and .pas files to be selected
  MainOpenDialog.Filter :=
    'CSV Files|*.csv';

  // Select pascal files as the starting filter type
  MainOpenDialog.FilterIndex := 2;

  // Display the open file dialog
  if MainOpenDialog.Execute
  then ShowMessage('File : '+MainOpenDialog.FileName)
  else ShowMessage('Open file was cancelled');

  // Free up the dialog
  MainOpenDialog.Free;
end;

end. 

Solution

  • That's because in your implementation section, your procedure ReadCSVFile is stand-alone, not a method of TForm1 (like your SlctImportDtaClick already is). Change it to read

    procedure TForm1.ReadCSVFile;
    var
      SS: TStringStream;
      OS: TFileStream;
    begin
      OS := TFileStream.Create(MainOpenDialog.FileName, fmCreate);
      [etc]
    

    The reason the compiler is complaining is that while ReadCSVFile is declared as a stand-alone procedure, it can't "make the connection" between MainOpenDialog in it and the one that's declared as part of TForm1.