Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I display a list of certain filenames in a combo box? 2

Status
Not open for further replies.

Jayz

ISP
Feb 17, 2002
59
Hello Experts of the realm,

I need to display in a combobox, a list of filenames (including extension) of a certain type, eg spreadsheets with the extension '.xls' that is in a set directory.

I hope this is clear.

So, as a simple example:
I have a form with only a combobox displayed, that shows a list of only spreadsheets. Where the directory is set in the code.

Much appreciated,
Jayz



 
This isn't quite what you want, but it is a very useful component for displaying files (especially when combined with TDirectoryListBox and TDriveComboBox):
Code:
var
  FileListBox: TFileListBox;
begin
  FileListBox := TFileListBox.Create(Panel1);
  FileListBox.Parent := Panel1;
  FileListBox.Directory := 'c:\temp';
  FileListBox.Mask := '*.xls';
  FileListBox.ShowGlyphs := True;
end;
Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
As a little expansion to what Clive wrote...

Right now, I don't have access to Delphi, but I *think* the FileListBox has an "items", "names", "files" or some such property that is of the TStrings type.

Here's what you do :

procedure Form.Create();
var
FileListBox: TFileListBox;
index : Integer;
begin
FileListBox := TFileListBox.Create(Panel1);
FileListBox.Parent := Panel1;
FileListBox.Directory := 'c:\temp';
FileListBox.Mask := '*.xls';
FileListBox.ShowGlyphs := True;
{ so far I was lazy and copied Clive's code ;) }
FileListBox.Visible:=False;
For index := 0 to FileListBox.Count-1 do
ComboBox1.Items.add(FileListBox.Items(index);
end;
 
We'll get there between us Kistal!
Here is the full code - there were a couple of small mistakes in Kistal's (you need square brackets in the ComboBox1 line) and as we're hiding the filelistbox we don't need to show glyphs.
Code:
var
  FileListBox: TFileListBox;
  index: Integer;
begin
  FileListBox := TFileListBox.Create(Panel1);
  FileListBox.Parent := Panel1;
  FileListBox.Directory := 'c:\temp';
  FileListBox.Mask := '*.xls';
  FileListBox.Visible := False;
  For index := 0 to FileListBox.Count - 1 do
    ComboBox1.Items.Add(FileListBox.Items[index]);
end;
Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
Just a final adjustment: move the
Code:
 FileListBox.Visible := False;
to the line after
Code:
FileListBox := TFileListBox.Create(Panel1);

Basically the way it was, meant that a flicker occurred, because you could see the FileListBox being added to Panel1 and then being made invisible very soon after. By placing the "visible" line above the "parent" line it stops this flicker. Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
Clive thanks very much for that. Just one more thing, how do I make the ItemIndex display the first file instead of a blank. I'm unable to change this in the object inspector.

I am using the style csDropdownList.

Regards,
Jayz
 
Strangely enough I did do that, but have just realised that it should be placed as the last line of code.

var
FileListBox: TFileListBox;
index: Integer;
begin
FileListBox := TFileListBox.Create(Panel1);
FileListBox.Parent := Panel1;
FileListBox.Directory := 'c:\temp';
FileListBox.Mask := '*.xls';
FileListBox.Visible := False;
For index := 0 to FileListBox.Count - 1 do
ComboBox1.Items.Add(FileListBox.Items[index]);
end;

Speaking of strange:
This code requires 3 components, FileListBox, ComboBox and Panel.

After compiling and running the program I removed the FileListBox and found that the program was still able to run without this component. But it did require it initially.

Clive what affect (if any) will this have by me now removing the FileListBox?.


 
Sorry...yes I forgot to mention ItemIndex should be the last line.

What do you mean by "I removed the FileListBox"? Do you mean you removed it from the code? I don't see how you could do that unless you didn't rebuild the project and it was still running from the old code. Select "Build" from the "Project" menu and see what happens. By removing the FileListBox - you will be removing the ability to grab the files of the specified directory.

Let me explain what each component is doing:
FileListBox:
- this component is responsible for locating and grabbing the names of all the files found in a specified directory, that match a specified filter (i.e. *.xls)
ComboBox:
- this component is there purely because it was in your initial request, it simply grabs the filenames that the FileListBox has generated. In this case, it is there for display rather than actual functionality. If you removed this component and changed the FileListBox's visible property to true, you would still see the filenames outputted but they would be in a listbox style not a drop-down combo style.
Panel:
- this component is just used as a parent container. You could have used the form itself or a groupbox or something. Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
I take it you have actually pasted a FileListBox on your form...

There is a difference between "form components" and function variables.

Stuff you put on the form is, essentially, a variable of a form, created together with it, and you can edit it at design time.

Function variables, on the other hand, are declared and created at runtime only - you can neither see nor edit them during design time, and they are only valid in that one single function.

The function me and Clive cooked up for you uses a variable, because you really only need it in this one function (as you have noticed).

So I suppose you both copied the code and inserted a FileListBox on your form, and gave it the same name. In this special case, they overlap and the FileListBox1 from the function temporarily "hides" the FileListBox1 of the form. Essentially, it pushes it aside in just that single moment that it would actually be used.

As for your question what impact removing the component on the form will have - none at all, it never should have been there to begin with.

You could also remove the panel component and just set the FileListBox like this :

FileListBox := TFileListBox.Create(theNameOfYourFormHere);
FileListBox.Parent := theNameOfYourFormHere;

With "theNameOfYourFormHere" obviously being whatever you called your form.
 
The reason why I create the FileListBox component at run-time and not design-time is because I couldn't find where the FileListBox component was in the toolbox (I've now found it under the "Win 3.1" tab)!!!

If you want to use this component in several functions then you may as well drop the component on your form and set its design-time properties from the "Properties Explorer" i.e. Visible and Mask.

You will still need to set the Directory property in code and the loop which adds all the files in the FileListBox to the ComboBox. Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
Kistal, you are correct I pasted a FileList box onto the form. But I had no other choice. I kept getting the error Undeclared identifier: 'TFileListBox'.
FileListBox: TFileListBox; would be highlighlted.

So now I'm confused. What am I missing?. Here is the complete code that won't compile. I used Form1 in replace of Panel1. I've pasted only a combobox(ComboBox1) onto my form as a simple example.
I'm using Delphi 6 Enterrise.


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
ComboBox1: TComboBox;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
FileListBox: TFileListBox; //The error is highlighted here
index: Integer;


implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

begin
FileListBox := TFileListBox.Create(Form1);
FileListBox.Visible := False;
FileListBox.Parent := Form1;
FileListBox.Directory := 'c:\temp';
FileListBox.Mask := '*.xls';
For index := 0 to FileListBox.Count - 1 do
ComboBox1.Items.Add(FileListBox.Items[index]);
ComboBox1.ItemIndex := 0;

end;

end.

 
Ok I found the problem.
Because we are using FileListBox there needed to be a control in 'uses' clause.
So what was happening when I pasted the FileListBox onto the form, FileCtrl was automatically added to the uses clause.

And then when I removed the FileListBox I had pasted onto the form, FileCtrl remained in the uses clause.

My apologies if this was blatantly obvious to you guys. I'm very new to Delphi, so I'm appreciating every bit of info you are offering.

I only wish I could give you guys more stars.

Thankyou Clive & Kistal

 
No problem :)

As a general hint, whenever you use a component by dynamically creating it (dynamically = at runtime) you should go to the help file, look it up and see what it uses...

Oh, and I take it you know not to use VCL and CLX through each other? Cause basically every component can be find in two units, but slightly different. CLX (the units with Q in front of them) are cross-platform but require overhead drivers to be shipped with them... so if you're pretty sure your app is only going to run on windows, never use anything with Q ahead of it.

Learned that one the hard way too :)
 
Often the "Undeclared identifier" error is because you have made reference to a component/object without including the necessary file in the "uses" clause. So immediately you get the error look for the component/object it highlights in the help file (as you found out and as Kistal pointed out).

Just another thing to note: you may come across the uses clause in two places - the interface section and the implementation section. Basically if the unit you want to include (in the uses clause) is needed in order to declare something in the interface part then place it in the interface section's uses clause. If, however, the unit to be included is only needed in your main code (implementation section) and not in the declarations (interface section) then declare it in the implementation section's uses clause.

Here's an example: if you wanted to use the
Code:
 Hypot
function to calculate the hypotenuse given two numbers as input, you would only be using it in the implementation of your code so you would place the Math unit in your implementation uses clause.

Code:
unit HypotExample;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  Math; 

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  hypotenuseValue: Extended;
begin
  hypotenuseValue := Hypot(StrToInt(Edit1.Text), StrToInt(Edit2.Text));
  Label1.Caption := FloatToStr(hypotenuseValue);
end;

end.

Marco Cantu has a tip on this in his book "Mastering Delphi 6":
"When you need to refer to another unit of a program, place the corresponding uses statement in the implementation portion instead of the interface portion if possible. This speeds up the compilation process, results in cleaner code (because the units you include are separate from those included by Delphi), and prevents circular unit compilation errors. To accomplish this, you can also use the File->Use Unit menu command." (p327) Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top