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

Memo-fields and empty lines 4

Status
Not open for further replies.

german12

Programmer
Nov 12, 2001
563
DE
Hi,

it is very hot today here in Germany - but perhaps somebody has a small routine which
scans through all memo-fields of a table and makes it possible that each memo-field
has not double empty lines.
(2 ore more empty lines should be reduced to only one empty line to make the text
better readable.)

This would save me thinking.

Thanks

Regards from Germany.

Klaus


example:
----------
memofield before:

xxxxxxx
xxxxxxxxxx
empty line
empty line
xxxxxxxxx
empty line
xxxxxxxxxx
xxxxx
empty line
empty line
empty line
xxxxxxxxxxxx

= e.g. 6 empty lines

...should look after the procedure has worked like this:

xxxxxxx
xxxxxxxxxx
empty line
xxxxxxxxx
empty line
xxxxxxxxxx
xxxxx
empty line
xxxxxxxxxxxx

..now 3 empty lines would be successful for my requirement.
 
Klaus

I don't have a fully written solution for you, but here is somewhere to start.
Since a carriage return is "CHR(13)", then it would stand to reason that 2 carriage returns is "CHR(13)+CHR(13)". So you could send you memo to a variable, and use something like:
Code:
LOCAL lcProblem,mNotes
lcProblem = CHR(13)+CHR(13)
select myTable
store myTable.notes to mNotes
STRTRAN(mNotes,lcProblem,CHR(13))
And replace your memo with mNotes
And do the same for the triple carriage returns.

Hope that will get you going

 
HI German,

I can give you an idea...

** number of lines in your memo field
nLines=ALINES(myArray,myMemoField)

** NOw scan the memo checking for empty lines and delete..
SCAN the array... for i=1 to nLines...

IF EMPTY(ALLTRIM(myArray(,i)))

** check if this is first empty line or extra empty line..

ADEL(myArray,i)

Add the text opf the array and rewrite the memo lines..

I am in too hurry now, and if some one else doesnt post the code or you dont solve by that time, I will post the code later.

Have a good day :)


ramani :)
(Subramanian.G),FoxAcc, ramani_g@yahoo.com
 
Mike, thank you - but it did not work

you can check it by this:
write this into a memo-field:

you are a good guy (plus enter)
empty line (write nothing plus enter)
empty (write nothing plus enter)
I know that (enter).

Now in the command window try this:
? chr(13)+(chr(13)$mymemofield &&result = .f.
but:
? chr(13)$mymemofield &&result = .t.

therefore in my opinion the double chr(13) can not work.

I expanded your program with only a check-routine but nothing happened (pls check)

what did I do wrong there?

regards from germany
Klaus

*Noemptyline.prg

*This program should reduce empty lines within memo-fields following
*one against another to one empty line per group

*With thanks to best help by Mgagnon.
*German12

PUBLIC gctable, notes

CLEA
SET PROCEDURE TO noemptyline
CLOSE DATA

*Choose a table
gctable = GETFILE('DBF', 'Which table?')

SELE 1
USE (gctable)

*Approval whether a memo-field is existing
flag = 0
FOR i = 1 TO FCOUNT()
IF TYPE(FIELD(i)) = "M"
flag = flag+1
ENDIF
ENDFOR


DO CASE
CASE flag >0 &&memo-field exists
*now show all memo-fields in that table
COPY TO temp STRUCTURE EXTENDED
SELE 2
USE temp
BROWSE FOR field_type ="M" ;
TITLE "Please click on your memo-field to be cleaned ";
+" and leave browse-mode"
STORE ALLTR(field_name) TO notes
*back to the original-table
SELE (gctable)
DO lessemptyline && Procedure to clean the memo-field

OTHERWISE
WAIT WINDOW "sorry "+FULLPATH(DBF())+ " has no memo-fields"
ENDCASE
close data
RETURN

PROCEDURE lessemptyline
*written by Magagnon
LOCAL lcProblem,mNotes
lcProblem = CHR(13)+CHR(13)
SELECT (gctable)
STORE (notes) TO mNotes
STRTRAN(mNotes,lcProblem,CHR(13))

CLOSE DATA
USE (gctable)
BROWSE TITLE FULLPATH(DBF())+ "please look into the cleaned memo-fields now and enjoy"
*but nothing has happened, why? there are still more than 2 following lines empty
ENDPROC

*eof program
 
Thanks Ramani
I will approve your idea - however can only do it at home, as my vfp 5.0 has
no ALINE-command here in the company. I am going to order 7.0 next time.

thanks anyway.
We have now about 35 degree celsius here - I can only think of cold beer at the moment.

Klaus
 
Klaus,

Going back to MGAGNON's answer, instead of looking for two successive CHR(13), try looking for CHR(13)+CHR(10)+CHR(13)+CHR(10). Usually a 'return' is followed by a 'line feed'.

Steve
 
Klaus
Here is modification to Ramani's code that seems to work:
Code:
Local i,x
i = 1
Use d:\reports\myTable
Set STEP ON
nLines=ALINES(myArray,notes)
x = nLines
For i =1 to nLines
    if x = 1
      exit
    endif
	If EMPTY(ALLTRIM(myArray(i))) 
*	Messagebox("Line is empty")
		=Adel(myArray,i)
	Endif
	x = x -1
Endfor

That will delete all the carriage returns in the array and just restore the memo field with the resulting array.
If you need to leave a carriage return (instead of 2) you could do a small count of empty array elements.
 
hi ramani, mike, steve
you gave me very valuable hints.
Although I could not yet check due to the missing alines-function in vfp 5.0 (I also did not find it in
foxtools) - it seems that b o t h variants work, because Steve gave the additional hint about chr(10).

This is what I tested in connection with the line-feed added - can be done interactively


*small program

*produce a variable with 2 empty lines between:

m.mymemo = "you are a"+chr(13)+chr(10)+chr(13)+chr(10) +chr(13)+chr(10)+"good guy"+chr(13)

*result:
*------------------------
you are a


good guy
*------------------------

*and now:

x = CHR(13)+CHR(10)+CHR(13)+CHR(10) &&variable to search for



replace mymemo with strtran(m.mymemo,x,chr(13)+chr(10))

? mymemo

*result
*---------------
you are a

good guy
*---------------

*works!

Thanks to all 3 of you and 3 stars are on the way!

Regards from Germany

Klaus (a little bit more intelligent now) - and it is not yet so hot here anymore...
 
Mike,
Meanwhile I checked your program - it works partly correct, but there is still a bug:

Consider this memo-contents:

you enter
enter
enter
are
enter

leads to two blank lines and after your program has run one is left.
output =
you

are

so far o.k.

but now when I write it that way, that there is one empty line more:

you enter
enter
enter
enter
are +enter

it will lead to a program-error called:
"value, type or number of function-arguments are invalid"
in connection with the statement

IF EMPTY(ALLTRIM(myArray(i)))

what does that mean?
does the program only work when I have two empty lines?

Klaus








 
Klaus

Because I hadn't accounted for it. :p
You see the problem is if you do a loop with the line count, and you find an empty record an delete it, the array resorts itself and the delete record ends up at the bottom, so in the meantime the line count keeps going up, so at the last element you trigger an error because the last element no longer exist. But if you play around with the linecount, I think it will work with this:
Code:
LOCAL i,x
i = 1
x = 0
USE c:\myTable
nLines=ALINES(myArray,notes)
FOR i = 1 TO nLines
	x = x + 1
	IF x = nLines
		EXIT
	ENDIF
	IF EMPTY(ALLTRIM(myArray(i)))
		=ADEL(myArray,i)
		i = i -1
	ENDIF
ENDFOR


Maybe this will work better
 
Hi, German12
I got another idea for you. It works without using ALines.
Each character of the orginal memo is examined before writing to a new memo. Of course, more memory is required.


CRLF=chr(13)+chr(10)

MyMemo = "you are a"+CRLF+CRLF+CRLF
+"good guy."+CRLF+CRLF+CRLF
+"God"+CRLF+"isn't it?"+CRLF

? LessLines(MyMemo)

*****************************************
Function LessLines
* reduce two of more empty lines into one empty line.
parameter InputMemo
local OutPutMemo, CRLF, nCounter, c
OutputMemo='' && the result memo
CRLF=chr(13)+chr(10) && carriage return and line feed
nCounter=0
* counter for no. of CR, LF counted before I saw a non CRLF character

c='' && dummy character

for i=1 to len(InputMemo)
c=substr(InputMemo,i,1)
if c $ CRLF
nCounter=nCounter+1
else
do case
case nCounter=0 && no line feed before
OutputMemo=OutputMemo+c
case nCounter<=2 && have 1 or 2 CR+LF combination
OutputMemo=OutputMemo+CRLF+c
nCounter=0 && reset the counter
case nCounter>=3 && have 3 CR+LF combination
OutputMemo=OutputMemo+CRLF+CRLF+c
nCounter=0 && reset the counter
endcase
endif
endfor
return OutputMemo


Good luck!
Norman

 
Thanks Norman,
this was basically a very good (star-worthy) idea - especially to help VFP 5.0 - users to ship
around the missing alines-function
(it's always interesting how different the approaches here are).

Your program works ok but - as you already stated concerning memory -
in this case (a table with about 144,000 memo-lines which I have) it becomes very very
slow so that I interrupted it when it came to memo-fields of more than 1000 lines each.

I tried to enhance the performance by using integers for the loop and defined some of
your expressions in advance (preprocessing) - but it was still very slow - perhaps it could be
used as an overnight-job - and of course - it is better than nothing...

Thank you with a star.

Mike, as I said - I can only check your prog tonight. I am curious about the performance...
Thank you very much too


Regards from Germany

Klaus


 
The ALINES function stands out as working for this situation because it ignores CHR(10) and splits on CHR(13) (removing any incidental CHR(10)'s), all the while ignoring repeated CHR(13)'s, too; ie:

z='one'+chr(13)+'two'+chr(10)+'three'+chr(13)+chr(13)+'four'+chr(13)+chr(10)+'five'+chr(13)+chr(10)+chr(13)+chr(10)+'six'
x=alines(aa,z)

will result in lines:
Code:
one
two
three
four
five

six

So, the only way to get blank lines out of an ALINES call is to have repeated CRLF's, not just CR's, so a quick way to remove them all might be:
Code:
nLn = ALINES( aLn, STRTRAN(Notes,chr(10),'') )
CleanNotes = ''
for lnI = 1 to nLn
  CleanNotes = CleanNotes + aLn[lnI] + chr(13)+chr(10)
endfor

----
For anyone in VFP5 who misses ALINES, here is a routine I wrote a while ago, SPLIT, which must be called by placing an &quot;@&quot; sign before the array name (so that VFP knows to pass the array by reference). You must also DIMENSION the array before hand, though SPLIT will redimension it to the size it needs (in contrast, ALINES needs neither.. it can create the array and always receives the array by reference):
Code:
*************************************************************************
* Split( paArr, pcLine, pcSep1 )                                         
*                                                                        
* auth: WGCS GTWv8 7/22/98                                               
* purp: This takes the string pcLine and splits it into the array        
*         paArr, using pcSep as the seperator character                  
*                                                                        
* todo: Extend this to support more seperator characters (for 2 dimensions) 
****************************************************************************
FUNCTION Split
PARAMETERS paArr, pcLine, pcDiv
PRIVATE lnLen, lnWid, lnCnt, lnNum, lnStrt, lnPos, lcSub
  lnLen = aLen( paArr, 1 ) && Number of rows
  lnWid = aLen( paArr, 2 ) && Number of cols
  
  lnCnt = AtcCnt( pcLine+pcDiv, pcDiv )
  if lnLen < lnCnt
    if lnWid > 0
      DIMENSION paArr[ lnCnt, aLen(paArr,2) ]
    else
      DIMENSION paArr[ lnCnt ]
    endif
  endif
  lnStrt = 1
  lnNum  = 0
  do While atc( pcDiv, pcLine+pcDiv, lnNum+1 ) > 0
    lnNum = lnNum + 1
    lnPos = atc( pcDiv, pcLine+pcDiv, lnNum )
    if lnStrt > len(pcLine) && 9/23/99 wgcs
      lcSub = ''
    else
      lcSub = Substr( pcLine, lnStrt, lnPos-lnStrt )
    endif
    lnStrt = lnPos + len(pcDiv)
    if lnWid > 0
      paArr[ lnNum, 1 ] = lcSub
    else
      paArr[ lnNum ] = lcSub
    endif
  enddo
    
RETURN lnCnt
 
The simple solution to the array element deleting is to start from the end and work backward. That way, when you delete an element, the only elements that get renumbered are the ones you've already done. You get no errors that way. Here's my version of Mike's code:
[tt]
Local i
Use d:\reports\myTable
Set STEP ON
nLines=ALINES(myArray,notes)
lFound=.F.
For i = nLines to 1 step -1
If EMPTY(ALLTRIM(myArray(i))) && Blank line
If lFound && Already found empty line
=Adel(myArray,i)
Endif
lFound=.T. && delete any further blanks
Else && Line not blank, reset flag
lFound=.F.
Endif
Endfor
[/tt]
Ian
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top