Does anyone know of an easy way of removing extra @VMs from a data field. Such as converting "1 2 3 4
" to " 2 3 4".
Thanks
Rick
Rick,
Here's a function I once made for that purpose.
I wrote it to handle 2-dimensional arrays as well, i.e, a @FM-delimited array of @VM-delimited arrays. So it can trim trailing @VMs in several fields at once, for instance in a whole record.
I also made the function able to trim all empty mv-values in the array, not just the ones at the end. Unfortunately this doesn't work so well on 2-dimensional arrays with AMVs. It trims each field independently of the others.
Also I sometimes needed the function to distinguish between a really empty mv-value, i.e, the null string, and a value containing a space (or several spaces).
Finally I wanted the function to be able to return the number of mv-values after the trimming was done.
But all these features and considerations are of no importance if you simply want to do what you described. Just call the function like
Data=1 : @VM : 2 : @VM : 3 : @VM : 4 : @VM : @VM : @VM : @VM
NewData=Strip_Empty_MVs( Data, "T", true$, CountMV )
===================
function Strip_Empty_MVs( Data, Where, Strict, CountMV )
/*
Data is a @VM-delimited array.
Or a @FM-delimited array of @VM-delimited arrays.
Where: where to strip empty mv-values: "T"=trailing. "A"=all. Default: all.
Strict=true$: mv-value must be null to be regarded as empty.
Strict=false$: mv-value=null or a string of one or more spaces is regarded as empty.
CountMV is returned as number of MVs in the returned result when viewed as a 2-dim array,
i.e, the length of the longest @VM-delimited array.
test: e.g,
run Strip_Empty_MVs "test"," ","","more"," ", "", "T", 1 -] "test
more "
run Strip_Empty_MVs "test"," ","","more"," ", "", "A", 1 -] "test
more "
run Strip_Empty_MVs "test"," ","","more"," ", "", "T", 0 -] "test
more"
run Strip_Empty_MVs "test"," ","","more"," ", "", "A", 0 -] "test more"
*/
$insert Logical
NumFields=count(Data, @FM) + (Data "")
New_Data="
CountMV=0
for F=1 to NumFields
New_Value=Data
Num_MV1=count(New_Value, @VM) + (New_Value "")
Done=false$
CountMV1=Num_MV1
for M=Num_MV1 to 1 step -1
if Strict then
if New_Value=" then
New_Value=delete( New_Value, 1, M, 0 )
CountMV1 -= 1
end else
if Where=T" then
Done=true$
end
end
end else
if Trim(New_Value)=" then
New_Value=delete( New_Value, 1, M, 0 )
CountMV1 -= 1
end else
if Where=T" then
Done=true$
end
end
end
until Done
next M
if F ] 1 then New_Data := @FM
New_Data := New_Value
if CountMV1 ] CountMV then CountMV=CountMV1
next F
return New_Data
===================
- Oystein -
Oystein's response shows a lot more elegance than the following which we present for the joy of a q&d…
Assuming MvVar is the thing with the trailing MVs
Loop
While MvVar-1,1=@Vm
MvVar-1,1='
Repeat
World Leaders in all things RevSoft
While Oystein's is grand (I grabbed a copy of it, TYVM Oystein), yours is the one I've been using for years.
Don M.
Thanks for the code.
Mine is better because it can remove more @VMs! Not just those at the end!
In my next version I will add audio so you can hear each @VM scream as they are removed.
Or I'll make a fully docced and very elegant 1000 lines version that can even remove all characters, be they @VM or not.
- Oystein -
Couldn't resist…this will trim all trailing instances of the passed in delimiter. It would be easy enough to modify this to trim not only the passed in delimiter, but all delimiters greater than or equal to the passed in delimiter.
Pat
SUBROUTINE TRIM_ALL_DELIMITERS(Record, Delim) Equate True$ to 1 Equate False$ to 0 ix =len(Record) // Index to current character eof=True$ // End Of Field flag loop while ix ] 0 ch=Recordix,1 if ch Delim then eof=True$ end else if eof then Recordix,1=' end end end ix -= 1 repeat
Oystein ..
Removing all characters .. now THAT's a grand idea .. but why stop there .. issue a CLEARTABLE to go along with it. Won't that bring a nice surprise.
I'm a little leery of removing stray @VM's in the middle unless I'm sure it's not part of an AMV chain and is not the controlling AMV. I DO like your routine, though and will use it .. thanks. BTW, are you going to be in Las Vegas?? If so, I'd like to say Hi and shake your hand.
Don Miller
SeeThruInk
Pat .. since we're having fun, I have a suboutine called UPDATE which works like:
UPDATE SET =….. SET =
or
UPDATE REPLACE WITH …..
This routine allows for standard R/LIST WITH clause logic
The=item after SET option allows for:
1. Constant e.g. SET STATE=CT"
2. Dict Symbolic e.g. SET PRICE=NEWPRICE
3. In-line computation e.g. set PRICE=PRICE * 1.25 reprice
4. Null e.g. SET LAST_DATE="
The REPLACE item works similarly except it works on MV elements. It requires the Existing Value and what to do with it .. so REPLACE 1.23 WITH 4.56 would do this. Or REPLACE "USA" WITH "" would delete this value.
Anyway .. just braggin'
Don M.
Sorry Pat, I know I don't REALLY want to go here but… even with a variable delimiter the method we posted is quicker. Well, like 2.5 secs vs 4 secs on what we tested .
World Leaders in all things RevSoft
I should hope yours is faster, it does not remove trailing delimiters in the middle of the record…
Now what's all this fuss with trailing vs middle @VMs anyway. Let's have circular fields and variables so all the @VMs are in the middle!
- Oystein -
Don,
I agree with what you say about @VMs in the middle of AMVs. It doesn't make sense to remove an empty value in a field in an AMV group unless all the corresponding values are empty, and then one must remove all the corresponding empty values, like deleting a row of empty cells in an edit table.
Vegas - can't come. Just used up all my money on a trip to Sprezz UK.
![]()
- Oystein -
Don,
I have something similar to your REPLACE, but implemented as a tool in an application window. I have Find Next/Replace/Replace All/Cancel options like the ones in the System Editor's Search and Replace. Also I have substring replacement instead of replacement of the whole field value, because substring replacement suits my clients' data better.
Actually whole value replacement like you have would come in handy too!
Or what I really would like to have is regular expressions!! Anybody with code to share?
- Oystein -
Assuming the input string has no @rm…
declare function stripthis( instr, stripthis)
*stripthis is a single character to trim from the end of the instr
ans=instr; convert " ":stripthis to @rm:" "
ans=trimb( ans); convert @rm:" " to " ":stripthis in ans
return ans
Dave Harmacek