I have copy text from multiple TEdit using sLineBreak, and I would like to paste the clipboard row by row in other TEdit
Thank you
You can use a TStringList to convert Clipboard.AsText to a list of separate lines. Then get individual lines from the string list using the strings index. For example:
procedure TForm21.Button1Click(Sender: TObject);
var
sl: TStringList;
begin
sl := TStringList.Create;
try
sl.Text := clipboard.AsText;
Edit1.Text := sl[2];
finally
sl.Free;
end;
end;
Related
What is the best way to allow a user to search for a record in a database table by typing text into a tedit box clicking a button then the results will then display onto a tcxgrid.
I have a tadquery/datasource that is looking at a table which contains various fields. It would be nice if the user was able to search for more than one field in the table.
Thanks.
You can use TDataSet.Locate for this, passing a semicolon delimited list of field names and an array of constant field values to match. Typically, this is easy:
DataSet.Locate('Field1;Field2', ['Value1', 'Value2'], [loPartialKey]);
However, as you don't know ahead of time how many columns, you'll need to handle the array differently, using VarArrayCreate and setting each array value separately.
This example takes the list of fields from Edit1 (separated by semicolon), the list of values to match from Edit2 (again, separated by semicolons, with string values surrounded by ' characters so they're properly included in the array). It splits the content of Edit1 into an array to find out how many elements, allocates a variant array of the proper size, populates it, and then passes both the field list and the array of values to TDataSet.Locate. It was tested with Edit1.Text := 'Customer_No;Name'; and Edit2.Text := '1;''Smith''';.
procedure TForm5.Button1Click(Sender: TObject);
var
Temp: string;
Fields: TArray<string>;
Vals: TArray<string>;
FieldValues: Variant;
i: Integer;
begin
// Grab a copy so we can split it into separate values
Temp := Edit1.Text;
Fields := Temp.Split([';']);
// Create the array of variants to hold the field values
FieldValues := VarArrayCreate([0, High(Fields)], VarVariant);
// Temporary copy to allow splitting into individual values
Temp := Edit2.Text;
Vals := Temp.Split([';']);
for i := 0 to High(Fields) do
FieldValues[i] := Vals[i];
// Use original field list from Edit1 for the Locate operation
DataSet1.Locate(Edit1.Text, FieldValues, [loCaseInsensitive]);
end;
For versions of Delphi prior to the inclusion of TStringHelper (such as the XE2 you're using, just add Types and StrUtils to your uses clause and use SplitString and TStringDynArray instead:
procedure TForm5.Button1Click(Sender: TObject);
var
Temp: string;
Fields: TStringDynArray;
Vals: TStringDynArray;
FieldValues: Variant;
i: Integer;
begin
Temp := Edit1.Text;
Fields := SplitString(Temp, ';');
FieldValues := VarArrayCreate([0, Length(Fields)], VarVariant);
Temp := Edit2.Text;
Vals := SplitString(Temp, ';');
for i := 0 to High(Fields) do
FieldValues[i] := Vals[i];
DataSet1.Locate(Temp, FieldValues, [loCaseInsensitive]);
end;
I would use a query for the datasource and in the onclick event of the button, reload the query with a WHERE clause along the lines of
Query1.SQL.Add('WHERE Name LIKE :P1 OR Postcode LIKE :P2 OR Town LIKE :P3');
and add the parameters
Query1.SQL.Parameters.ParamByName('P1').Value := '%' + Edit1.Text + '%';
Query1.SQL.Parameters.ParamByName('P2').Value := '%' + Edit1.Text + '%';
Query1.SQL.Parameters.ParamByName('P3').Value := '%' + Edit1.Text + '%';
using '%' to allow searching anywhere in the string as an option.
Query1.Open;
I've used this technique many times.
It has been awhile since I have done any programming in Delphi and I was looking around for some examples on how to incrementally search a dbgrid by typing a search term into a edit box and I found the following code which seems to do the trick for the most part, but it checks for the filter condition on every column in the grid and I would like to limit the filter condition so it only checks one column in the grid (Column 1 for instance), how would I do that using the code provided ?
procedure TForm1.Edit1Change(Sender: TObject);
begin
FDTable1.Filtered := false;
FDTable1.Filtered := Edit1.Text <> '';
end;
procedure TForm1.FDTable1FilterRecord(DataSet: TDataSet;
var Accept: Boolean);
var
i: integer;
begin
for i := 0 to DataSet.FieldCount - 1 do begin
Accept := Pos(UpperCase(Edit1.Text),
UpperCase(DataSet.Fields[i].AsString)) = 1;
if Accept then exit;
end;
end;
I am parsing a dataset and assigning values to TStringList i want to avoid the duplicates. I use the following code but still duplicates are inserted.
channelList := TStringList.Create;
channelList.Duplicates := dupIgnore;
try
dataset.First;
while not dataset.EOF do
begin
channelList.Add(dataset.FieldByName('CHANNEL_INT').AsString) ;
dataset.Next;
end;
why does the duplicates added?
http://docwiki.embarcadero.com/Libraries/XE2/en/System.Classes.TStringList.Duplicates
You did read http://docwiki.embarcadero.com/Libraries/XE2/en/System.Classes.TStringList.Duplicates , didn't you ?
Then you missed the most repeated word there - "sorted"
channelList.Sorted := true
var F: TField;
channelList := TStringList.Create;
channelList.Sorted := True;
channelList.Duplicates := dupIgnore;
try
dataset.First;
F := dataset.FieldByName('CHANNEL_INT');
while not dataset.EOF do
begin
channelList.Add(F.AsString);
dataset.Next;
end;
Think out of the box and avoid the duplicates up front?
I don't know what DB you are using but for example on SQL server it is just a matter of querying:
'SELECT DISTINCT CHANNEL_INT FROM MYTABLE';
and then you can add the results to your TStringList without being worried about duplicates.
I am using the following to insert text from a text file into TMemo.
procedure TForm1.Button1Click(Sender: TObject);
var
SL: TStringList;
begin
SL := TStringList.Create;
try
SL.LoadFromFile('c:\testimeng\keyfil.txt');
Memo1.Lines.Assign(SL);
finally
SL.Free;
end;
end;
What i want to know is how to add a single line according to row number to TMemo when i choose the specific row number.
Example output:
During this time he has distinguished himself in the academic, sporting and cultural spheres of school life.
During this time he has distinguished himself in the academic and sporting spheres of school life.
During this time he has distinguished himself in the academic and cultural spheres of school life.
During this time he has distinguished himself in the academic aspect of school life.
During this time he has distinguished himself in both the sporting and cultural aspects of school life.
Any help appreciated.
I think you're asking about putting a single line from the TStringList into the TMemo when you specify which item (index, or line number) from the TStringList. If that's the case, you can use something like this:
Memo1.Lines.Add(SL[Index]);
So if the first line in your keyfile.txt is
During this time he has distinguished himself in the academic, sporting and cultural spheres of school life.
You would use
Memo1.Lines.Add(SL[0]); // Desired line number - 1
Ok, after your comment to your question, I think I know what you're wanting to do. Here's one way to do it:
Drop a TListBox, a TButton, and a TMemo on your form. I arranged mine with the ListBox on the left, the button next to it (at the top right corner), and then the memo just to the right of the button.
In the FormCreate event, populate the TListBox with your text file and clear the existing memo content:
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
ListBox1.Items.LoadFromFile('c:\testimeng\keyfil.txt');
end;
Double-click the button to add an OnClick handler:
procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
begin
// If there's an item selected in the listbox...
if ListBox1.ItemIndex <> -1 then
begin
// Get the selected item
s := ListBox1.Items[ListBox1.ItemIndex];
// See if it's already in the memo. If it's not, add it at the end.
if Memo1.Lines.IndexOf(s) = -1 then
Memo1.Lines.Add(s);
end;
end;
Now run the app. Click on an item in the listbox, and then click the button. If the item is not already present in the memo, it will be added as a new last line. If it's already there, it won't be added (to prevent duplicates).
If you're wanting to add it to the end of the current last line (extending the paragraph, perhaps), then you'd do it like this:
// Add selected sentence to the end of the last line of the memo,
// separating it with a space from the content that's there.
Memo1.Lines[Memo1.Lines.Count - 1] := Memo1.Lines[Memo1.Lines.Count - 1] + #32 + s;
So, it should be clear by now that to add to the end of a specific line, you just grab the content that's already
there and add to it. For instance, if the user types 3 into a TEdit:
procedure TForm1.FormCreate(Sender: TObject);
begin
SL := TStringList.Create;
SL.LoadFromFile('c:\testimeng\keyfil.txt');
end;
procedure TForm1.ButtonAddTextClick(Sender: TObject);
var
TheLine: Integer;
begin
// SL is the TStringList from the FormCreate code above
TheLine := StrToIntDef(Edit1.Text, -1);
if (TheLine > -1) and (TheLine < Memo1.Lines.Count) then
if TheLine < SL.Count then
Memo1.Lines[TheLine] := Memo1.Lines[TheLine] + SL[TheLine];
end;
Write a specific line with String by Mouse Clicking on TMemo
Procedure TForm1.Button1Click(Sender: TObject);
Var SL: TStringList;
LineNumber : Integer;
Begin
LineNumber := Memo1.Perform(EM_LINEFROMCHAR, Memo1.SelStart, 0);
Memo1.SelStart := Memo1.Perform(EM_LINEINDEX, LineNumber, 0);
Memo1.SelLength := Length(Memo1.Lines[LineNumber]) ;
Memo1.SetFocus;
SL := TStringList.Create;
try
SL.LoadFromFile('c:\testimeng\keyfil.txt');
Memo1.SelText := SL.Strings[0];
finally
SL.Free;
end;
End;
Say i have a combobox with
apples
apples
pears
oranges
oranges
i would like to have it show
apples
pears
oranges
how can i do this?
for iter := combobox.Items.Count - 1 downto 0 do
begin
index := combobox.Items.IndexOf(combobox.Items[iter]);
if index < iter then
combobox.Items.Delete(iter);
end;
I suggest that you simply refill the combo box each time. That makes the logic simpler:
ComboBox.Items.BeginUpdate;
try
ComboBox.Clear;
for Str in Values do
begin
if ComboBox.Items.IndexOf (Str) = -1 then
ComboBox.Items.Add (Str);
end;
finally
ComboBox.Items.EndUpdate;
end;
Just to put methods against eachother: one keeps the order but is increasingly slow with larger number of items. The other stays relatively faster but doesn't keep order:
procedure SortStringlist;
var
i,index,itimer: integer;
sl : TStringlist;
const
numberofitems = 10000;
begin
sl := TStringlist.Create;
for i := 0 to numberofitems-1 do begin
sl.Add(IntToStr(random(2000)));
end;
Showmessage(IntToStr(sl.Count));
itimer := GetTickCount;
sl.Sort;
for I := sl.Count-1 downto 1 do begin
if sl[i]=sl[i-1] then sl.Delete(i);
end;
Showmessage(IntToStr(sl.Count)+' Time taken in ms: '+IntToStr(GetTickCount-itimer));
sl.free;
sl := TStringlist.Create;
for i := 0 to numberofitems-1 do begin
sl.Add(IntToStr(random(2000)));
end;
Showmessage(IntToStr(sl.Count));
itimer := GetTickCount;
for i := sl.Count - 1 downto 0 do
begin
index := sl.IndexOf(sl[i]);
if index < i then
sl.Delete(i);
end;
Showmessage(IntToStr(sl.Count)+' Time taken in ms: '+IntToStr(GetTickCount-itimer));
end;
If you don't care if the items get reordered (or they're sorted already), TStrings can do the work for you - it eliminates all of the looping, deletion, and other work. (Of course, it requires the creation/destruction of a temporary TStringList, so if that's an issue for you it won't work.)
var
SL: TStringList;
begin
ComboBox1.Items.BeginUpdate;
try
SL := TStringList.Create;
try
SL.Sorted := True; // Required for Duplicates to work
SL.Duplicates := dupIgnore;
SL.AddStrings(ComboBox1.Items);
ComboBox1.Items.Assign(SL);
finally
SL.Free;
end;
finally
ComboBox1.Items.EndUpdate;
end;
end;
To properly compare with Igor's answer (which includes no BeginUpdate/EndUpdate), remove those things:
var
SL: TStringList;
begin
SL := TStringList.Create;
try
SL.Sorted := True; // Required for Duplicates to work
SL.Duplicates := dupIgnore;
SL.AddStrings(ComboBox1.Items);
ComboBox1.Items.Assign(SL);
finally
SL.Free;
end;
end;
You have to remove duplicates from the source data.
In most scenarios, a ComboBox is filled with data in run-time, which means, data is coming from some source. There are basically 2 scenarios here: a dataset from database and a collection of strings from any other source. In both cases you filter out duplicates before inserting anything into the ComboBox.
If source is a dataset from database, simply use the SQL DISTINCT keyword.
If source is any collection of strings, use a peace of code provided in the answer by #Smasher.
I faced this problem several times before, and i used all the previous approaches and I'm still using them, but do you know : i think the best approach , though not mentioned here, is to subclass TComboBox, creating a new method (say AddUnique ) that add the string to the combo ONLY if it does not exist previously , otherwise it will drop it.
This solution may cost some extra time in the beginning , but it will solve the problem once and for all.