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 gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to replace text between a certain character in a memo field with other text 3

Status
Not open for further replies.

Steve-vfp9user

Programmer
Feb 5, 2013
337
GB
Hello all

I am trying to replace certain text within a memo field (ACTIONS) with other characters that are between a certain character.

For example:

This is some text in the memo field and I require !This text removed! (That is surrrounded by ! together with the !) and replace with XXXXXXXXXXXXXXXXX (or whatever length of the string that is surrounded by the character !

It would be most advantageous if the text replaced could be with some sort of black square. I recall there is such a character but I couldn't see it in the ASCII list.

I am aware of:

Code:
USE MYTABLE IN 0
REPLACE ALL ACTIONS WITH ;
  STRTRAN(ACTIONS,"THE TEXT","XXXXXXXXXX") ;
  IN "MYTABLE"

The above only replaces text with a predefined alternative but I need it to recognise the length of the text to be replaced and replace it with characters fitting that length as described above.

Can anyone please shed some light or give me a pointer please?

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Steve,

A combination of STRTRAN, STREXTRACT, and REPLICATE will give you what you need in a single expression that you can put in a SQL statement. That said, I would advise to use improbable character combinations for the placeholders delimiters.

Code:
LOCAL Source AS String
LOCAL Replacement AS Character
LOCAL Delimiter AS Character

m.Replacement = "X"
m.Delimiter = "!"

TEXT TO m.Source NOSHOW FLAGS 1 PRETEXT 8
This is some text in the memo field and I require
!This text removed! (That is surrrounded by ! together with the !)
and replace with XXXXXXXXXXXXXXXXX (or whatever length of the string that
is surrounded by the character !
ENDTEXT

LOCAL Removed AS String

SET MEMOWIDTH TO 1024
? m.Source FONT "Courier"
m.Source = STRTRAN(m.Source, STREXTRACT(m.Source, m.Delimiter, m.Delimiter, 1, 4), REPLICATE(m.Replacement, LEN(STREXTRACT(m.Source, m.Delimiter, m.Delimiter, 1, 4))))
? m.Source FONT "Courier"
 
You don't have such a mode of STRTRAN, Atlopes gave you code dealing with the first such match, if that would be done multiple times in your example text there are further matches at places you wouldn't want to replace, so I second to use another delimiter than "!". It should be checked you find them as pairs, too.

You could also use AT() to find all the delimiting character positions and STUFF() to stuff in the replacement, just to add two more string functions to your knowledge.
The combination of STREXTRACT and STRTRAN also is a fine solution, as the way STREXTRACT is parameterized (with the last 4) is including delimiters. Look up the parameterization to learn it.

You could also split with ALINES(), by default splitting at CRLF, but you can split at any character, then take the length of the second array element +2 to create the replacement. You'd put together a new string from all odd array elements and for the even elements take their length+2 as blocks.

And about the block character: Such characters exist for sure in Unicode, but that's not usable in VFP. DOS codepages have them, but that doesn't go well with Windows. Many control characters with codes <32 will be represented with a white square/rectangle: , so you could perhaps set m.Replacement = CHR(0) to get nearest in that aspect.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Hi Steve,

that's something that could be done with STRTRAN()

Single Chars can be replaced like this:

Code:
m.vStream = STRTRAN( m.vStream , CHR(   9 ) , [    ] )		&& TAB
m.vStream = STRTRAN( m.vStream , [<] , [&lt;] )			&& <
m.vStream = STRTRAN( m.vStream , [>] , [&gt;] )			&& >
m.vStream = STRTRAN( m.vStream , CHR(  10 ) , [<br/>] )		&& LF

To replace placeholders you can also make use of this function. Usually I recognize my placeholder by two @ signs as start and end sign ( -> @@myPlaceholder@@ ).
Replacing the with the real values within their corresponding m.Vars I do something like this (This is part of a routine that replaces placeholders within a mail body):

Code:
IF NOT EMPTY( Thisform.txtTo.Value ) ;
AND USED( [crsEmails] )
	* // thats the structure of the placeholderlist cursor crsMailPlh
	* // plh c(20), mfield c(15)
	* // [@@Salutation@@] , [ap_salutation]
	* // [@@Prename@@] , [ap_prename]
	* // [@@Name@@] , [ap_name]
	* // [@@Phone@@] , [ap_phone]
	* // [@@Mobile@@] , [ap_mobile]
	* // [@@Fax@@] , [ap_fax]
	* // [@@EMail@@] , [ap_email]
	* // [@@Position@@] , [ap_position]
	lcTo1 = GETWORDNUM( ALLTRIM( Thisform.txtTo.Value ) , 1 , [;] )
	SELECT crsEmails
	LOCATE FOR ALLTRIM( ii_mail ) == lcTo1
	IF FOUND()
		SCATTER MEMVAR 
		SELECT crsMailplh
		GO TOP 
		FOR liLoop = 1 TO RECCOUNT( [crsMailplh] )
			STRTRAN( Thisform.EditBox.TextRTF , ALLTRIM( crsMailplh.plh ) , EVALUATE( [m.] + ALLTRIM( crsMailplh.mfield ) ) )
			SKIP IN crsMailplh	
		ENDFOR 	
	ENDIF 
ENDIF

This code replaces placeholders with receiver data based on the first email adress within the forms 'TO' textbox. The cursor 'crsEMails' contains all data thats available for each selected mailadresse in 'TO', 'CC' ond/or 'BCC'. But as only ONE main receiver can be used, it has to be the first in 'TO'.
The code shows, that I am using a richtext editbox, but in this case this doesn't matter. The RTF editbox would make it easier if something has to be replaced at cursor pos or in a marked area which isn't the case here.

HTH



-Tom
 
My thanks to those who have posted examples/advice so far, the details of which I'll try out over the weekend.

Much appreciated.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Good evening

Atlopes:

Your example works of course.

I did also take the advice of Olaf:

I second to use another delimiter than "!". It should be checked you find them as pairs, too.

That was also mentioned in Tom Borgmann's suggestion so the use of @@ surrounding text is a first step e.g.

The text to be removed and replace is @@surrounded by@@ at signs

Code:
LOCAL Source AS String
LOCAL Replacement AS Character
LOCAL Delimiter AS Character

m.Replacement = "X"
m.Delimiter = "@@"

TEXT TO m.Source NOSHOW FLAGS 1 PRETEXT 8
This is some text in the memo field and I require
!This text removed! (That is surrrounded by ! together with the !)
and replace with XXXXXXXXXXXXXXXXX (or whatever length of the string that
is surrounded by the character !
ENDTEXT

LOCAL Removed AS String

SET MEMOWIDTH TO 1024
? m.Source FONT "Courier"
m.Source = STRTRAN(m.Source, STREXTRACT(m.Source, m.Delimiter, m.Delimiter, 1, 4), ;
  REPLICATE(m.Replacement, LEN(STREXTRACT(m.Source, m.Delimiter, m.Delimiter, 1, 4))))
? m.Source FONT "Courier"

I'll adapt the above to use the text from a memo field which is the original request,

So that works but reverting back to Olaf's comment:

Atlopes gave you code dealing with the first such match

So if there are two or more instances of text surrounded by @@ such as @@my text@@ and @@more text@@ how do I identify those?

Appreciate the advise so far.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
I think you can't have that ability in a single statement, so you must use a user defined function instead (that you can use in a SQL statement, nevertheless).

Code:
LOCAL Source AS String
LOCAL Replacement AS Character
LOCAL Delimiter AS Character

m.Replacement = "X"
m.Delimiter = "@@"

TEXT TO m.Source NOSHOW FLAGS 1 PRETEXT 8
This is some text in the memo field and I require
@@This text removed@@ (That is surrrounded by ! together with the !)
and replace with XXXXXXXXXXXXXXXXX (or whatever length of the string that
is surrounded by the character ! and this too @@kaboom!@@
ENDTEXT

SET MEMOWIDTH TO 1024
? m.Source FONT "Courier"
? Replacer(m.Source, m.Delimiter, m.Delimiter, m.Replacement) FONT "Courier"

FUNCTION Replacer (Source AS String, LeftDelimiter AS String, RightDelimiter AS String, Replacement AS Character)

	LOCAL Match AS String

	m.Match = STREXTRACT(m.Source, m.LeftDelimiter, m.RightDelimiter, 1, 4)
	IF EMPTY(m.Match)
		RETURN m.Source
	ELSE
		RETURN Replacer(STRTRAN(m.Source, m.Match, PADR('', LEN(m.Match), m.Replacement)), m.LeftDelimiter, m.RightDelimiter, m.Replacement)
	ENDIF

ENDFUNC
 
Hi Atlops

Perfect!

My thanks to those who posted suggestions and code which is much appreciated.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top