Link to home
Start Free TrialLog in
Avatar of Wayne Barron
Wayne BarronFlag for United States of America

asked on

RichEdit - Insert Text "before" Several Column's if does not Exist

This is going to be a little hard to explain, so please bear with me on this one.

Lets say that you have the following situation:

"34","My Something","And","Something","CanBe","Important","Without","nothing","There"

OK, in the above String's, I need to look at the 5th Column, Once i find this column.
I need to loop back and add in information "After" the 2nd Column (as it does not exist)
(The 5th column as demostrated here, is going to change in different situations, so I would
Need a way to change the Column# & The word [Important] will change as well.)

The output should look something like this:

"34","My Something","And","1234","Something","CanBe","Important","Without","nothing","There"

Were the 3rd Column Exist now, with "1234" inserted.

Thanks All;
Carrzkiss
Avatar of Wayne Barron
Wayne Barron
Flag of United States of America image

ASKER

View the following Post, for more information on what I am doing here:

https://www.experts-exchange.com/questions/21865362/RichEdit-Insert-Text-before-Column-if-does-not-Exist.html
I have found a way around this which is:

I run the file through the program that I have already created.
Then I open the Formatted file (Datafeed) into "Microsoft Excel"
I move the "Single" Column over in Excel.
Then I save the file.

Importing the file into "Microsoft Access" Works like a charm.
Everything runs correctly.
------------------------------------
If there is no way to do what I am needing here, then I will have to settle with the way I am
Doing it now, which is somewhat time-consuming.
I would rather have my program to do everything in 1-clean-sweep.
(Makes more since) then to have to rely on another program to finish up the work for me.

Thanks all
Carrzkiss
what about something like this?

function GetColumnValue(pos: integer; s:string): string;
function InsertColumnValue(pos: integer; s,snew:string): string;

...
//-- usage
//-- add
procedure TForm1.Button1Click(Sender: TObject);
begin
   Edit3.Text := GetColumnValue(strtoint(Edit4.Text),Edit2.Text);
   Edit3.Text := InsertColumnValue(2,Edit2.Text, Edit1.Text);
end;

//-- var pos= column #
//-- var s= comma del string
//-- result = colum value at that position

function GetColumnValue(pos: integer; s:string): string;
var
      tstr: TStringList;
begin
      result := '';
   tstr := TStringList.Create;
   try
         tstr.QuoteChar := '"';
//         tstr.Delimiter := ',';
      tstr.CommaText := s;
      result := tstr[pos];
   finally
         tstr.free;
   end;
end;

//-- var pos= column # to insert column value at
//-- var s= comma del string
//-- var snew=  new column value to insert at said position
//-- result = new comma del string
function InsertColumnValue(pos: integer; s,snew:string): string;
var
      tstr: TStringList;
begin
   result := '';
   tstr := TStringList.Create;
   try
         tstr.QuoteChar := '"';
         //tstr.Delimiter := ',';
      tstr.CommaText := s;
      tstr.Insert(pos,snew);

      result := tstr.CommaText;
   finally
         tstr.Free;
   end;
end;
Not sure that I am following you on this one?

Would the [Edit3.Text] Be the "RichEdit1.text"?

Could you please provide a full demo of how to use these functions to accomplish what I am needing?
Right now, I am slightly lost.

Thanks Now.
loop thru the lines/strings of the richedit, read each line
check the line for a certain value in a deliminated string at a certain position
if result = true than add a new cloumn & value into the line/string

example:
add a richedit called "redt1"
add a button called "btn1"

function GetColumnValue(pos: integer; s:string): string;
function InsertColumnValue(pos: integer; s,snew:string): string;
..

procedure TForm1.btn1Click(Sender: TObject);
var
      i: integer;
   ln: string;
begin
      //- read each line of the richedit
      for i := 0 to redt1.Lines.Count + 1 do
         if redt1.Lines[i] <> '' then begin
            //-- check to see if column value exists in the row
         if GetColumnValue(5,redt1.Lines[i])= 'CanBe1' then begin
               //-- column value exists so insert NEW at column defined
            ln := InsertColumnValue(2,redt1.Lines[i],'New Value to insert');
            redt1.Lines.Delete(i);
            redt1.Lines.Insert(i,ln);
         end;
      end;
end;

//-- var pos= column #
//-- var s= comma del string
//-- result = colum value at that position

function GetColumnValue(pos: integer; s:string): string;
var
     tstr: TStringList;
begin
     result := '';
   tstr := TStringList.Create;
   try
        tstr.QuoteChar := '"';
        tstr.Delimiter := ',';
      tstr.CommaText := s;
      if tstr.Count >= pos then
            result := tstr[pos];
   finally
        tstr.free;
   end;
end;

//-- var pos= column # to insert column value at
//-- var s= comma del string
//-- var snew=  new column value to insert at said position
//-- result = new comma del string
function InsertColumnValue(pos: integer; s,snew:string): string;
var
     tstr: TStringList;
begin
   result := '';
   tstr := TStringList.Create;
   try
      tstr.QuoteChar := '"';
      tstr.Delimiter := ',';
      tstr.CommaText := s;
      tstr.Insert(pos,snew);

      result := tstr.CommaText;
   finally
        tstr.Free;
   end;
end;

you can speed things up by making the tstringlists used in the function global, and create and destroy them both before and after the parsing instead of on each line.

Hope this is what you want
Thank you [LMuadDIb];

  I do not have the time right now to try it out, but will either later on this evening
Or sometime tomorrow.

You mentioned :    tStringLists used in a function global.

Are you referring to adding it to the form like so:

Var
   Form1 : TForm1;
var
     tstr: TStringList;

implementation

{$R *.dfm}

Or am I way off track?
ASKER CERTIFIED SOLUTION
Avatar of LMuadDIb
LMuadDIb
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The code works great.
I had to change it up a little to allow me to pick and choose the locations instead of
Hard coding it.

if GetColumnValue((StrToInt(Form1.Edit1.Text)),redt1.Lines[i])= (Edit2.Text) then begin
               //-- column value exists so insert NEW at column defined
             ln := InsertColumnValue((StrToInt(Form1.Edit3.Text)),redt1.Lines[i],(Edit4.Text));

As you can see, I added in the Edit1.text - Edit4.Text
This way I can pick and choose which word, and were they are located at.

Works like a charm.
Thanks a bunch for the better explaination on how to use the Functions.

Wayne
I have got 1 more question for you about this code, if you do not mind?
============
Lets say the follow:

"34","My Something","And","1234","Something","CanBe76","Important","Without","nothing","There"
"34","My Something","And","4321","Something","CanBe23","Important","Without","nothing","There"

As you can see by the lines above.
There is [1-Column] to look at.
But [2-different words] to add information in the other [Column] for.

I was thinking about have like maybe a:
Memo1
Memo2

Memo1 - Would have the words in it that we need to "Look" for.
Memo2 - Would have the #'s in it that need to be "Added".

The Words in the [Memo1] Will be listed in the same order as the words in [Memo2]
So that they would be added in at the right place.

Any idea's on how to do something like that to your code here?

Thanks a bunch.
Wayne
ok, if I got want you mean... you want to check Memo1 for the "Look" for, if found you look into Memo2 for its #s, and then we add this # to the richedit? We are not editing memo1 nor memo2 data correct? Just the RichEdit data yes?

procedure TForm1.btn1Click(Sender: TObject);
var
   i: integer;
   ln: string;
begin

   tstr := TStringList.create;
   try
         tstr.QuoteChar := '"';
      tstr.Delimiter := ',';
     //- read each line of the richedit
      for i := 0 to memo1.Lines.Count + 1 do
         if memo1.Lines[i] <> '' then begin
            //-- check to see if column value exists in the row
           if GetColumnValue(StrToInt(Edit1.Text),memo1.Lines[i])= Edit2.Text then begin
               //-- column value exists so insert NEW at column defined
             ln := InsertColumnValue(StrToInt(Edit3.Text),redt1.Lines[i],GetColumnValue(3,memo2.lines[i]));  //-- <<<<
             redt1.Lines.Delete(i);
             redt1.Lines.Insert(i,ln);
           end;
        end;
    finally
       tstr.Free;
    end;

end;

when you InsertColumnValue, you will need to execute GetColumnValue within it to read the new value from memo2, you will have another tEdit component. Im about to go to bed, so I might not understand exactly what you are trying to do; sleppy =)
OK.
I think that you might have it, but I am not able to get it to work.
I think that you might have a few too many TEdits here.

Edit1 - The Column to look at
Edit2 - The Column to place the new values
Memo1 - Goes with [Edit1] for the Look at Values
Memo2 - Goes with [Edit2] Which contains the values to place in the new Column

The code that you have provided here has several new Edit fields,
Also for here:  GetColumnValue(3,memo2.lines[i]));
The (3)
I would take that too be the new Column to be created. Which would need to be the same as
(IntToStr(Edit2.Text),Memo2.Lines[i])); (If I am undestanding the code correctly?)

So basically, just
2 - TEdit's
2 - TMemo's
1 - TRichEdit
1 - TButton
And that should be all that would be needed.
Anything else, would come into being a bit confusing :)

I will look over the code again, and see if I can implement it to work the way you have it here
Then I will try to see if I can implement what I am needing, until you can get back up with me on this.

So, until then, I hope that you can get some sleep tonight, as I am needing some myself.

Take Care
Wayne
edit1 = column # position to FIND (integer), this is the column to search in
edit2 = column value (string),  FIND this value in the column

edit3 = column # position to FIND (integer), this is the column to grab NEW column from to be INSERTed
edit4 = column # position to INSERT, this is the column we INSERT the new column at

**edit4 we dont need to use unless the INSERT position is different than edit3

this is getting confusing sense we are not defining the vars, but are just using component names.
you should use something like:
 
FindColPosition : integer;
FindColValue : string;
InsertColPosition: integer;
InsertColNewPosition: integer;

instead of edit1.text, edit3.text ..etc... use FindColPosition & InsertFindColPosition
would make reading the code alot easier for both of use

..
procedure TForm1.btn1Click(Sender: TObject);
var
   i: integer;
   ln: string;
  FindColPosition : integer;
  FindColValue : string;
  InsertFindColPosition: integer;
begin

  FindColPosition := strtoint(edit1.text);
  FindColValue := edit2.text;
  InsertColPosition := strtoint(edit3.text);

   tstr := TStringList.create;
   try
        tstr.QuoteChar := '"';
      tstr.Delimiter := ',';
     //- read each line of the richedit
      for i := 0 to memo1.Lines.Count + 1 do
         if memo1.Lines[i] <> '' then begin
            //-- check to see if column value exists in the row
           if GetColumnValue(FindColPosition ,memo1.Lines[i])= FindColValue then begin
               //-- column value exists so insert NEW at column defined
             ln := InsertColumnValue(InsertColPosition,redt1.Lines[i],GetColumnValue(InsertColPosition,memo2.lines[i]));
             redt1.Lines.Delete(i);
             redt1.Lines.Insert(i,ln);
           end;
        end;
    finally
       tstr.Free;
    end;

end;

hopefully I got it right =)
I cannot get it to work.
Maybe it is just that I am still not following what it is that you are doing in the code.
It is very confusing to me at this point. (Sorry about that).

The only way that I "think" that I will understand what is going on is if you can
Just copy the .dfm & .pas {FULL} into here, and then I can copy it out.
But if you do that, Have the "Strings" all ready in place in all the components.
This way I have see how you have it all working, then I might be able to understand it a lot better.
As it sits right now, I am totally lost, as I am unable to get the code to work.

Sorry for all the aggrivation that this might be causing you, but I am lost.

Wayne
I will post a full project later tonight (hopefully), I dont have alot of time right at this moment
no problem on the wait.
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    redt1: TRichEdit;
    pnl1: TPanel;
    mmo1: TMemo;
    mmo2: TMemo;
    btn1: TButton;
    edt1: TEdit;
    edt2: TEdit;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
    tstr : TStringList;
  public
    { Public declarations }
    function GetColumnValue(pos: integer; s:string): string;
    function InsertColumnValue(pos: integer; s,snew:string): string;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
var
   i: integer;
   ln, tmpln: string;
   iPosFind, iPosInsert: integer;
   sInsertColValue: string;
begin
      redt1.Clear;
   // zero based if we dont "-1"
   iPosFind:= StrToInt(edt1.text)-1;
   iPosInsert:= StrToInt(edt2.text)-1;

   tstr := TStringList.create;
   try
      tstr.QuoteChar := '"';
      tstr.Delimiter := ',';
      //- read each line of memo 1
      for i := 0 to mmo1.Lines.Count + 1 do
         if mmo1.Lines[i] <> '' then begin
            //-- check to see if column value exists in the row
          if GetColumnValue(iPosFind,mmo1.Lines[i])= 'Can' then begin
             //-- grab column value from memo 2
             sInsertColValue := GetColumnValue(iPosInsert,mmo2.Lines[i]);
             //-- insert this column value into the new string
             ln := InsertColumnValue(iPosInsert,mmo1.Lines[i],sInsertColValue);
          end else
                ln := mmo1.Lines[i];
          //-- add ln to richedit, which might be new or old
          redt1.Lines.Add(ln);
       end;
    finally
       tstr.Free;
    end;

end;

function TForm1.GetColumnValue(pos: integer; s:string): string;
begin
   result := '';
   tstr.CommaText := s;
   if tstr.Count >= pos then
        result := tstr[pos];
end;

function TForm1.InsertColumnValue(pos: integer; s,snew:string): string;
begin
   result := '';
   tstr.CommaText := s;
   if tstr.Count >= pos then begin
        tstr.Insert(pos,snew);
        result := tstr.CommaText;
   end;
end;

end.

//------------

this should do the trick
cya
:(

What ever I type in mmo2
Deletes "All" lines from the "redt1" then only places in the items from mmo1.

This line here:
if GetColumnValue(iPosFind,mmo1.Lines[i])= 'Can' then begin

What is the:    'Can'
It is a String. but is it what we are "looking" for?

Here is your code with the added [Columns] in the RichEdit
And the Added Column #'s in the Edt1 & edt2 as well as the information in the mmo1 & mmo2
(I know, I used component names again, sorry about that)

http://www.carrz-fox-fire.com/c/AddColumns.zip

Download, unzip, compile, run.
Hit the [btn1] and you will see everything leave the Richedit, except just the lines in the Memo1

If you are able to make your code wotk on your end, then please let me know how you are doing it
Because I cannot make it work on my end.

Wayne
procedure TForm1.btn1Click(Sender: TObject);
var
   i: integer;
   ln, tmpln: string;
   iPosFind, iPosInsert: integer;
   sInsertColValue: string;
begin
   // zero based if we dont "-1"
   iPosFind:= StrToInt(edt1.text)-1;
   iPosInsert:= StrToInt(edt2.text)-1;

   tstr := TStringList.create;
   try
      tstr.QuoteChar := '"';
      tstr.Delimiter := ',';
     //- read each line of the richedit
      for i := 0 to redt1.Lines.Count + 1 do
         if redt1.Lines[i] <> '' then begin
            //-- check to see if column value exists in the row
           if GetColumnValue(iPosFind ,redt1.Lines[i])= mmo1.Lines[i] then begin
               //-- column value exists so insert NEW at column defined
             ln := InsertColumnValue(iPosInsert,redt1.Lines[i],mmo2.Lines[i]);
             redt1.Lines.Delete(i);
             redt1.Lines.Insert(i,ln);
           end;
        end;
    finally
       tstr.Free;
    end;

end;

//--

that should do it :)
In my previous code I was thinking that your memo had columns
Works good.
But it is gettting rid of all the         ","
And the beginning         "
In the Richedit, which I know is coming from these 2 lines
      tstr.QuoteChar := '"';
      tstr.Delimiter := ',';
But I cannot add in the correct String, as this is strickly for [Char] and not [String]
What would need to be added in for it "not" to get rid of all the   ","  &  "  from the RichEdit?
I have tested out the code in a working string.
Out of 30-Lines, it will only grab and insert a New Column in "2-Lines"
But not the remaining 28-Lines in the RichEdit control.

I do not know if there is something wrong with the fact that it is changing up the  ","   & Beginning   "
Or what it is, but right now as it sits, this code is not working correctly.

Here is an example I made up for you.
It has a Test "Feed" loaded into the RichEdit.
The Column #'s are set correctly.
The mmo1 & mmo2
Already have the items added into them as well,
Just compile, run and the file will load.
Then click on the Button, and "nothing" will happen.

Change the Column # to "Look for" to [14] and then hit the Button, and it will change "2" lines.
It suppose to be looking at the [13] column, not the [14] column.
Totally confused, and not understanding why it is not grabbing the other lines as well.
I mean, if it would grab all the lines, but the Column # incorrect, I could deal with, I would just
Jump up 1-# on all Feeds that I have to work with.

http://www.carrz-fox-fire.com/c/AddColumns-2.zip

Good Luck.
I do not fully understand all of the code yet, to fix the issue myself.
But I am looking into it, as it was not what I originally thought the problem was.

Wayne
delphi drops the double quotes if they are not needed.
If its a pharse with spaces the quotes are kept.
If its a single word,char,numeral with no spaces...then quotes are left out.

Im glad you sent me this last code, we just were not on the same page as to what exactly you wanted it to do.
thanks :)
...

procedure TForm1.btn1Click(Sender: TObject);
var
   i,x: integer;
   ln: string;
   iPosFind, iPosInsert: integer;
   sFindColValue: string;
begin
   // zero based if we dont "-1"
   iPosFind:= StrToInt(edt1.text);
   iPosInsert:= StrToInt(edt2.text);

   tstr := TStringList.create;
   try
      tstr.QuoteChar := '"';
      tstr.Delimiter := ',';
      //-- Read each line in the
      for x := 0 to mmo1.Lines.Count -1 do begin
            for i := 0 to redt1.Lines.Count -1 do begin
            sFindColValue := mmo1.Lines[x];
            if sFindColValue = GetColumnValue(iPosFind ,redt1.Lines[i]) then begin
             ln := InsertColumnValue(iPosInsert,redt1.Lines[i],mmo2.Lines[x]);
             redt1.Lines.Delete(i);
             redt1.Lines.Insert(i,ln);
            end;
         end;
      end;
    finally
       tstr.Free;
    end;
end;


function TForm1.GetColumnValue(pos: integer; s:string): string;
begin
   result := '';
   tstr.CommaText := s;
   if tstr.Count >= pos then
        result := tstr[pos];
end;

function TForm1.InsertColumnValue(pos: integer; s,snew:string): string;
begin
   result := '';
   tstr.CommaText := s;
   if tstr.Count >= pos then begin
        tstr.Insert(pos,snew);
        result := tstr.CommaText;
   end;
end;

Code works great.
But is there anyway to make Delphi "STOP" messing with my ","  &  "  Quotes.

(Me and Delphi are getting ready to get into a fight here)

And you are welcome for the last code.
I figured that it would help you out, to know what is going on.
Sorry, no idea how to stop that.
But you should have no problems importing into databases/spreadsheets etc...

hope you get things straighten out with delphi. And I hope you win ;)

Some info on CommaText:
CommaText is the list of Strings in the TStrings object, listed in system data format (SDF) style.
Use CommaText to get or set all the Strings in the TStrings object in a single comma-delimited String.
When retrieving CommaText, any String in the list that include spaces, commas or quotes will be
contained in double quotes, and any double quotes in a String will be repeated.
Hello "LmuaDlb"

rlibby assisted on keeping the Comma's & Quotes where they needed to be at.
----------------------
function TForm1.InsertColumnValue(pos: integer; s, snew: String): String;
var  dwFields:      Integer;
begin
 
   SetLength(result, 0);
   tstr.CommaText:=s;
   if (tstr.Count >= pos) then tstr.Insert(pos, snew);
   if (tstr.Count >= 0) then
   begin
     // Recreate the quoted comma sep string
     for dwFields:=0 to Pred(tstr.Count) do result:=resul t+ AnsiQuotedStr(tstr[dwFields], '"') + ',';
     // Remove trailing comma
     Delete(result, Length(result), 1);
   end;
 
end;
-------------------------------
Works like a charm.

Just wanted to let you know.

Take Care and thank you so very much for your assistance in this issue.
You are among the best here at EE.

Wayne