I have a long string ("sara james joseph NAUMAN") which is displayed using Crystal Reports in VS2008(c#) using a stored procedure.
I want to convert it to title case ("Sara Williams Joseph Nauman")
I also want to remove spaces if there are more than two between the words.
I want to know how to do the conversion in a stored procedure, Crystal Reports formula, or .cs file.
There is a function called ProperCase(str) that will fix the casing.
`ProperCase("sara james joseph NAUMAN")`
Borrowing a bit of Hariharan Anbazhagan's code; if you happen to have blank spaces before and after your string, use Trim(str). No function comes to mind to remove blank spaces between words so this code will do the job.
stringvar str1;
stringvar str2;
numbervar counter;
numbervar leng;
str2 := Trim(" Big Space ");
leng := len(str2);
if leng>0 then
(
for counter := 1 to leng do
(
If Not(Mid(str2, counter, 1) = " " and (Mid(str2, counter+1, 1)) = " ") Then
(
str1:=str1 + Mid(str2, counter, 1)
)
);
str1
)
Custom formula Format():
// Format()
Function (Stringvar value, Optional Stringvar delimiter:=",")
// create an array of formetted names (and blanks)
// "sara james joseph NAUMAN" => "Sara James Joseph Nauman"
Local Stringvar Array temp:=Split( ProperCase(value), " ");
Local Stringvar Array values;
Local Numbervar i;
// remove empty array positions
For i:= 1 To Ubound(temp) Do (
If temp[i]<>"" Then (
Redim Preserve values[Ubound(values)+1];
values[Ubound(values)]:=temp[i]
)
);
// delimited list
Join(values, delimiter);
Reference it in a formula:
// returns "Sara,James,Joseph,Nauman"
Format("sara james joseph NAUMAN")
In VB.net, the equivalent is:
str1 = StrConv(str1, vbProperCase)
This is just an FYI in case someone else is looking for this in VB.net.
Related
Can you please help me:
I have a database and I need to "concatenate records" based on fields in a table.
Table: Order
Field: Order-Number
Field: Previous-Order-Number
Field: Create-Date
I need to be able to find the first "order based".
Then be able to find all the other orders that are related and put them into a variable delimited by ",".
For example:
Record 1:
Order-Number is: 123456
Previous-Order-Number is: 999999
Record 2:
Order-Number is 999999
Previous-Order-Number is 111111
Record 3:
Order-Number is: 111111
Previous-Order-Number is: 777777
and so on and so on.
I want to put it in a variable, so it will have display/output like this: (Order-Number + "|" + Create-date, N) i.e. "123456|01/01/22, 999999|03/03/22, 111111|04/04/22"
Please let me know if you need more information
Thank you
you can do it with a RecursiveFunction
// RecursiveFunction
FUNCTION getOrderNumRecursive RETURN CHARACTER
(INPUT iOrderNum AS INTEGER):
FIND FIRST Order No-LOCK
WHERE Order.Order-Number = iOrderNum
No-ERROR.
IF AVAILABLE(Order) THEN
// in the Return you call the function again with the PreviousOrderNumber
RETURN STRING(Order.Order-Number) + "|" + STRING(Order.Create-date) +
"," + getOrderNumRecursive(Order.Previous-Order-Number).
RETURN "".
END FUNCTION.
DEFINE VARIABLE cList AS CHARACTER No-UNDO.
//Call the function with the first OrderNumber you want
cList = getOrderNumRecursive(123456).
MESSAGE cList
VIEW-AS ALERT-BOX.
You want to get this from all the elements from the table? You can run this code to generate it into a CHAR variable...
If you want to add more fields, just add into both of the i_rec into the FOR EACH loop.
DEF VAR i_rec AS CHAR NO-UNDO.
FOR EACH Order NO-LOCK:
IF i_rec <> "" THEN DO:
i_rec = i_rec + "," + Order.Order-Number + "|" + Order.Create-date.
END. ELSE DO:
i_rec = Order.Order-Number + "|" + Order.Create-date.
END.
END.
For example:
Regex: District ([0-9]{1,2})([^0-9]|$)
Input District 12 2021 returns 12
Input Southern District 3 returns 3
Input FooBar returns NULL
The function REGEXP_SUBSTR doesn't allow extracting a single capturing group.
You can use e.g. REGEXP_REPLACE(input, regex, '\\1') to replace occurrences of regex in input with the first capture group of regex.
The following stored function makes this easy to use:
DELIMITER $$
CREATE FUNCTION regexp_extract(inp TEXT, regex TEXT, capture INT) RETURNS TEXT DETERMINISTIC
BEGIN
DECLARE capstr VARCHAR(5);
DECLARE mregex TEXT;
IF inp IS NULL OR LENGTH(inp) = 0 OR inp NOT REGEXP regex THEN
RETURN NULL;
END IF;
SET capstr = CONCAT('\\', capture);
SET mregex = CONCAT('.*', regex, '.*'); -- Want to match the entire input string so it all gets replaced
RETURN REGEXP_REPLACE(inp, mregex, capstr);
END;
$$
DELIMITER ;
Used like so:
SELECT regexp_extract('District 12 2021', 'District ([0-9]{1,2})([^0-9]|$)', 1);
For those users who might be stuck with an earlier version of MySQL or MariaDB which does not have REGEXP_REPLACE available, we can also use SUBSTRING_INDEX here:
SELECT SUBSTRING_INDEX(
SUBSTRING_INDEX('Southern District 3', 'District ', -1), ' ', 1); -- 3
An address field in a Progress database evidently is multiple lines. So if I do something simple like:
for each customer where customer-number = "123" no-lock.
display customer-number
customer-name
customer-address.
I get results of:
123 John Smith 123 Easy St.
c/o Jane Smith
Apartment C12
I want results of:
123 John Smith 123 Easy St. c/o Jane Smith Apartment C12
I've tried Entry - but get an error if an element does not exists. I am trying to export to CSV and want each line to be another column and if a column does not exists then it is blank.
Any help will be MUCH appreciated!
If the delimiter is a newline then something like this should work:
define variable n as integer no-undo.
define variable i as integer no-undo.
define variable address as character no-undo.
output to value( "customer.csv").
for each customer no-lock:
address = "".
n = num-entries( customer-address, "~n" ).
do i = 1 to n:
address = address + entry( i, customer-address, "~n" ) + " ".
end.
export delimiter "," customer-number customer-name trim( address ).
end.
output close.
or, if you just need to change the delimiter within the customer-address field:
output to value( "customer.csv").
for each customer no-lock:
export delimiter "," customer-number customer-name replace( customer-address, "~n", "," ).
end.
output close.
(And, actually, my original code is really just replacing ~n with a space so you could do that too...)
In u-sql script I must extract a variable from file to a dataset and then use it to form a name of output file. How can I get the variable from the dataset?
In details.
I have 2 input files: csv file with a set of fields and a dictionary file. The 1st file has file name like ****ClintCode*****.csv. The 2nd file-dictionary has 2 fields with mapping: ClientCode - ClintCode2. My task is extract ClientCode value from the file name, get ClientCode2 from the dictionary, insert it as a field to output file (implemented), and, moreover, form the name of output file as ****ClientCode2****.csv.
Dictionary csv file has the content:
OldCode NewCode
6HAA Alfa
CCVV Beta
CVXX gamma
? Davis
The question is how to get ClientCode2 into scalar variable to write an expression for the output file?
DECLARE #inputFile string = "D:/DFS_SSC_Automation/Tasks/FundInfo/ESP_FAD_GL_6HAA_20170930.txt"; // '6HAA' is ClientCode here that mapped to other code in ClientCode_KVP.csv
DECLARE #outputFile string = "D:/DFS_SSC_Automation/Tasks/FundInfo/ClientCode_sftp_" + // 'ClientCode' should be replaced with ClientCode from mapping in ClientCode_KVP.csv
DateTime.Now.ToString("yyyymmdd") + "_" +
DateTime.Now.ToString("HHmmss") + ".csv";
DECLARE #dictionaryFile string = "D:/DFS_SSC_Automation/ClientCode_KVP.csv";
#dict =
EXTRACT [OldCode] string,
[NewCode] string
FROM #dictionaryFile
USING Extractors.Text(skipFirstNRows : 1, delimiter : ',');
#theCode =
SELECT Path.GetFileNameWithoutExtension(#inputFile).IndexOf([OldCode]) >= 0 ? 1 : 3 AS [CodeExists],
[NewCode]
FROM #dict
UNION
SELECT *
FROM(
VALUES
(
2,
""
)) AS t([CodeExists],[NewCode]);
#code =
SELECT [NewCode]
FROM #theCode
ORDER BY [CodeExists]
FETCH 1 ROWS;
#GLdata =
EXTRACT [ASAT] string,
[ASOF] string,
[BASIS_INDICATOR] string,
[CALENDAR_DATE] string,
[CR_EOP_AMOUNT] string,
[DR_EOP_AMOUNT] string,
[FUND_ID] string,
[GL_ACCT_TYPE_IND] string,
[TRANS_CLIENT_FUND_NUM] string
FROM #inputFile
USING Extractors.Text(delimiter : '|', skipFirstNRows : 1);
// Prepare output dataset
#FundInfoGL =
SELECT "" AS [AccountPeriodEnd],
"" AS [ClientCode],
[FUND_ID] AS [FundCode],
SUM(GL_ACCT_TYPE_IND == "A"? System.Convert.ToDecimal(DR_EOP_AMOUNT) : 0) AS [NetValueOtherAssets],
SUM(GL_ACCT_TYPE_IND == "L"? System.Convert.ToDecimal(CR_EOP_AMOUNT) : 0) AS [NetValueOtherLiabilities],
0.0000 AS [NetAssetsOfSeries]
FROM #GLdata
GROUP BY FUND_ID;
// NetAssetsOfSeries calculation
#FundInfoGLOut =
SELECT [AccountPeriodEnd],
[NewCode] AS [ClientCode],
[FundCode],
Convert.ToString([NetValueOtherAssets]) AS [NetValueOtherAssets],
Convert.ToString([NetValueOtherLiabilities]) AS [NetValueOtherLiabilities],
Convert.ToString([NetValueOtherAssets] - [NetValueOtherLiabilities]) AS [NetAssetsOfSeries]
FROM #FundInfoGL
CROSS JOIN #code;
// Output
OUTPUT #FundInfoGLOut
TO #outputFile
USING Outputters.Text(outputHeader : true, delimiter : '|', quoting : false);
As David points out: You cannot assign query results to scalar variables.
However, we have a dynamic partitioned output feature in private preview right now that will give you the ability to generate file names based on column values. Please contact me if you want to try it out.
You can't. Please see Convert Rowset variables to scalar value.
You may still be able to achieve your ultimate goal in a different manner. Please consider re-writing your post with clear & concise language, small dataset, expected output, and a very minimal amount of code needed to repro - remove all details and nuances that aren't necessary to create a test case.
This seems simple to me, but I can't get my brain around it.
I want to take a string, check for spaces, ignore the first space,
but remove all subsequent spaces. For example:
MyString := 'Alexander The Great';
Output would be 'Alexander TheGreat'
Much thanks in advance! (Using Turbo Pascal 7.0 for DOS)
I usually use Java so I don't know if this is the best way to do what you ask but at least it seems to work...
program nospaces(output);
var
MyString : string;
ResultStr: string;
count: integer;
i: integer;
Temp: string;
n: string;
begin
ResultStr:='';
MyString := 'Alexander The Great';
writeln(MyString);
count := 0;
for i := 1 to length(MyString) do
begin
Temp := copy(MyString, i, 1);
if Temp = ' ' then
begin
If count=0 then
begin
count := count + 1;
ResultStr := ResultStr + Temp;
end;
end
else
begin
ResultStr := ResultStr + Temp;
end
end;
writeln(ResultStr);
readln(n);
end.
what have I done? I cicle on the characters of the String. If the character that I found isn't a space I add that to the resulting String. If the character is a 'space' and it is the first (it's the first because count=0) I add 1 to count and add the character to the resulting string. Then if the character is a space again I'll have the count=1 that make me continue ignoring this space.
Thank you Mauros for your help, although I figured it out this morning before checking back here. This is the answer, for anyone else who might run into this in the future:
Crush the Name if it has more than one space in it
For example: "Alexander The Great" Becomes "Alexander TheGreat",
"John" stays as "John", "Doc Holiday" stays as "Doc Holiday"
"Alexander The Super Great" becomes "Alexander TheSuperGreat" and
so on and so forth.
FirstSpacePosition := POS(' ',LT.Name);
s := Copy(LT.Name,1,FirstSpacePosition);
s2 := Copy(LT.Name,FirstSpacePosition,Length(LT.Name));
s := StripAllSpaces(s);
s2 := StripAllSpaces(s2);
Insert(' ',s,(Length(s)+1));
LT.Name := s+s2;
StripTrailingBlanks2(LT.Name);
StripLeadingBlanks(LT.Name);
And the StripAllSpaces Function looked like this:
FUNCTION StripAllSpaces(s3:STRING):STRING;
BEGIN
WHILE POS(' ',s3)>0 DO Delete(s3,Pos(' ',s3),1);
StripAllSpaces:=s3;
END;{StripAllSpaces}
And The StripLeadingBlanks / StripTrailingBlanks Functions look like this:
PROCEDURE StripTrailingBlanks2(var Strg: string);
BEGIN
while Strg[Length(Strg)] = ' ' do
Delete(Strg, Length(Strg), 1);
END; { END StripTrailingBlanks }
PROCEDURE StripLeadingBlanks(var Strg: string);
BEGIN
While (Length(Strg) > 0) and (Strg[1] = ' ') do
Delete(Strg, 1, 1);
END; { END StripLeadingBlanks }