I have experience of VB and c# but not ST. Im trying to find the value of the nth digit in a value. ie 654321 the nth value when n = 3 should return 4. Is it possible to do this in ST?
I suggest to convert the number to STRING and then you can find the nth character from the string. Of course, you didn't tell that if your number 654321 is a string or number value, but it doesn't really matter.
The following code takes the 3rd character from the left. If you need to get the digit from right, you can edit the code using LEN() etc. functions.
VAR
TestNumber : DINT;
TestString : STRING;
NthDigitAsString : STRING(1);
NthDigit : BYTE;
END_VAR
TestNumber := 654321;
//Convert to string
TestString := DINT_TO_STRING(TestNumber);
//Find the 3rd character (counting from from left)
NthDigitAsString := MID(TestString, 1, 3);
//Convert the character to number (if necessary)
NthDigit := STRING_TO_BYTE(NthDigitAsString);
That is of course a long version. Find the one-liner below:
NthDigit := STRING_TO_BYTE(MID(DINT_TO_STRING(654321), 1, 3));
I have one field in a dataset which has a multi-line textbox value. I want to split that record, store it into an array, and when I fetch the value from the array by a for-loop, I want to prepend a "*" to each line. I have written a formula for that but it's working only for 2 values. After that it's not working and I'm not able to get how to retrieve the value like this.
I want the result to be:
* 123
* 234
* 786
But I'm getting the result:
*123
234
786
my formula is
Local StringVar y;
Local StringVar x;
Local NumberVar i;
y := ""+ chrw(10);
x := y;
Stringvar Array strings := Split({Touche.Concerns}, "\r\n");
Stringvar Array numbers;
For i :=1 To Ubound(strings) Do
(
y := y + chrw(10)+ "$" + strings[i];
);
y;
Instead of a long formula which breaks into arrays and manipulates each line, why not just replace the line breaks with a line break and the asterisk?
"* " & replace(trim({Touche.Concerns}), "\r\n", "\r\n* ");
The leading '*' is to place the char on the first line and the trim function is called to remove any trailing line breaks (so there won't be a line with just the asterisk).
As a side note, use & when concatenating strings and not the + char. Use the + can sometimes cause coercion to where numeric values would be added together. For example "12" + "34" would yield 46 instead of 1234. The & char ensures string concatenation is used.
I am using Autohotkey.
I have a string that looks like this S523.WW.E.SIMA. I want to remove the last few characters of the string after the dot (including the dot itself). So, after the removal, the string will look like S523.WW.E.
This may look like a simple question but I just cannot figure out using the available string functions in Autohotkey. How can this be done using Autohotkey? Thank you very much.
Example 1 (last index of)
string := "S523.WW.E.SIMA"
LastDotPos := InStr(string,".",0,0) ; get position of last occurrence of "."
result := SubStr(string,1,LastDotPos-1) ; get substring from start to last dot
MsgBox %result% ; display result
See InStr
See SubStr
Example 2 (StrSplit)
; Split it into the dot-separated parts,
; then join them again excluding the last part
parts := StrSplit(string, ".")
result := ""
Loop % parts.MaxIndex() - 1
{
if(StrLen(result)) {
result .= "."
}
result .= parts[A_Index]
}
Example 3 (RegExMatch)
; Extract everything up until the last dot
RegExMatch(string, "(.*)\.", result)
msgbox % result1
Example 4 (RegExReplace)
; RegExReplace to remove everything, starting with the last dot
result := RegExReplace(string, "\.[^\.]+$", "")
How do I convert a string to title case in OpenEdge ABL (aka Progress 4GL)?
I know I can get upper case with CAPS(), and lower case with LC(), but I can't find the title case (sometimes called proper case) function.
Examples:
Input Output
------------ ------------
hello world! Hello World!
HELLO WORLD! Hello World!
function titleWord returns character ( input inString as character ):
return caps( substring( inString, 1, 1 )) + lc( substring( inString, 2 )).
end.
function titleCase returns character ( input inString as character ):
define variable i as integer no-undo.
define variable n as integer no-undo.
define variable outString as character no-undo.
n = num-entries( inString, " " ).
do i = 1 to n:
outString =
outString +
( if i > 1 and i <= n then " " else "" ) +
titleWord( entry( i, inString, " " ))
.
end.
return outString.
end.
display
titleCase( "the quick brown fox JUMPED over the lazy dog!" ) format "x(60)"
.
I think the order of one of those statements above is incorrect -
You'll be adding an extra " " at the beginning of the string! Also need to change the <= to < or you'll be tacking an extra " " into your return string.
It should be:
n = num-entries( inString, " " ).
do i = 1 to n:
outString =
outString +
titleWord( entry( i, inString, " " )) +
( if i < n then " " else "" ) +
.
end.
At least that's what I -think- it should be...
-Me
I was playing around with this a while back, and besides a solution similar to Tom's, I came up with two variations.
One of the problems I had was that not all words are separated by space, such as Run-Time and Read/Write, so I wrote this version to use any non-alphabetic characters as separators.
I also wanted to count diacritics and accented characters as alphabetic, so it became a little complicated. To solve the problem I create two versions of the title, one upper and one lower case. Where the two strings are the same, it's a non-alphabetic character, where they are different, it's alphabetical. Titles are usually very short, so this method is not as inefficient as might seem at first.
FUNCTION TitleCase2 RETURNS CHARACTER
( pcText AS CHARACTER ) :
/*------------------------------------------------------------------------------
Purpose: Converts a string to Title Case.
Notes: This version takes all non-alphabetic characters as word seperators
at the expense of a little speed. This affects things like
D'Arby vs D'arby or Week-End vs Week-end.
------------------------------------------------------------------------------*/
DEFINE VARIABLE cUText AS CHARACTER NO-UNDO CASE-SENSITIVE.
DEFINE VARIABLE cLText AS CHARACTER NO-UNDO CASE-SENSITIVE.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE VARIABLE lFound AS LOGICAL NO-UNDO INITIAL TRUE.
cUText = CAPS(pcText).
cLText = LC(pcText).
DO i = 1 TO LENGTH(pcText):
IF (SUBSTRING(cUText, i, 1)) <> (SUBSTRING(cLText, i, 1)) THEN
DO:
IF lFound THEN
DO:
SUBSTRING(cLText, i, 1) = (SUBSTRING(cUText, i, 1)).
lFound = FALSE.
END.
END.
ELSE lFound = TRUE.
END.
RETURN cLText.
END FUNCTION.
Another issue is that title case is supposed to be language specific, i.e. verbs and nouns are treated differently to prepositions and conjunctions. These are some possible rules for title case:
First and last word always get capitalized
Capitalize all nouns, verbs (including "is" and other forms of "to
be"), adverbs (including "than" and "when"), adjectives (including
"this" and "that"), and pronouns (including "its").
Capitalize prepositions that are part of a verb phrase.
Lowercase articles (a, an, the).
Lowercase coordinate conjunctions (and, but, for, nor, or).
Lowercase prepositions of four or fewer letters.
Lowercase "to" in an infinitive phrase.
Capitalize the second word in compound words if it is a noun or
proper adjective or the words have equal weight (Cross-Reference,
Pre-Microsoft Software, Read/Write Access, Run-Time). Lowercase the
second word if it is another part of speech or a participle
modifying the first word (How-to, Take-off).
I could of course not code all this without teaching the computer English, so I created this version as a simple if crude compromise; it works in most cases, but there are exceptions.
FUNCTION TitleCaseE RETURNS CHARACTER
( pcText AS CHARACTER ) :
/*------------------------------------------------------------------------------
Purpose: Converts an English string to Title Case.
Notes:
------------------------------------------------------------------------------*/
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE VARIABLE cWord AS CHARACTER NO-UNDO.
DEFINE VARIABLE lFound AS LOGICAL NO-UNDO INITIAL TRUE.
DEFINE VARIABLE iLast AS INTEGER NO-UNDO.
DEFINE VARIABLE cSmallWords AS CHARACTER NO-UNDO
INITIAL "and,but,or,for,nor,the,a,an,to,amid,anti,as,at,but,by,down,from,in" +
",into,like,near,of,off,on,onto,over,per,than,to,up,upon,via,with".
pcText = REPLACE(REPLACE(LC(pcText),"-"," - "),"/"," / ").
iLast = NUM-ENTRIES(pcText, " ").
DO i = 1 TO iLast:
cWord = ENTRY(i, pcText, " ").
IF LENGTH(cWord) > 0 THEN
IF i = 1 OR i = iLast OR LOOKUP(cWord, cSmallWords) = 0 THEN
ENTRY(i, pcText, " ") = CAPS(SUBSTRING(cWord, 1, 1)) + LC(SUBSTRING(cWord, 2)).
END.
RETURN REPLACE(REPLACE(pcText," - ","-")," / ","/").
END FUNCTION.
I have to mention that Tom's solution is very much faster than both of mine. Depending on what you need, you may find that the speed is not that important, since you're unlikely to use this in large data crunching processes or with long strings, but I wouldn't ignore it. Make sure that your needs justify the performance loss.
I am using a formula field to concatonate 2 decimal values separated by a dash. However, I want the result to trim all unneccesary trailing zeros and decimal points for both values.
For example, I want values 10 and 8.5 to be "10 - 8.5". Now it shows "10.00 - 8.50".
The formula I am using is CSTR({field1}) + " - " + CSTR({field2}).
I believe this is what you're looking for:
Convert Decimal Numbers to Text showing only the non-zero decimals
Especially this line might be helpful:
StringVar text := Totext ( {Your.NumberField} , 6 , "" ) ;
The first parameter is the decimal to be converted, the second parameter is the number of decimal places and the third parameter is the separator for thousands/millions etc.
CSTR({number_field}, 0, '')
The second placeholder is for decimals.
The last placeholder is for thousands separator.
i wrote a simple function for this:
Function (stringVar param)
(
Local stringVar oneChar := '0';
Local numberVar strLen := Length(param);
Local numberVar index := strLen;
oneChar = param[strLen];
while index > 0 and oneChar = '0' do
(
oneChar := param[index];
index := index - 1;
);
Left(param , index + 1);
)