Loop through a string in PowerBuilder - string

First of all, I'm a noob at PowerBuilder and can't seem to find how to do this anywhere.
I have been give the task of rewriting an application at work. My boss wants the new application to mimic the old one as much as possible, so that leads to my question. There is a date field that will allow a date input separated by a tilde (01/01/15~01/31/15) and it uses this to get a beginning date and end date for a between SQL statement.
With all that being said, I am trying to do the same thing in PowerBuilder 12.6 classic. I know that I can accomplish the same thing by using two date pickers (begin date and end date), but my boss wants this transition to be as seamless as possible to the end users.
I have a sle_date_shipped on my form that currently takes in a date format of mm/dd/yy and will process it, but I want to allow mm/dd/yy~mm/dd/yy and parse out a begin and end date. My pseudo code would look something like this:
int i
String s
String start_date
String end_date
if this.textsize > 8 then
s = this.text(value of this position in the string)
start_date = s + s
if this.text = "~" then
s = s + 1
s = this.text(value of this position in the string)
end_date = s + s
end if
this.textsize + 1
else
start_date = this.text
end if
I do realize that my pseudo code probably needs some work, I'm just trying to get the point across.
Thanks

Don't loop...
string ls_start, ls_end
ls_start = left( this.text, pos( this.text, '~' ) - 1)
ls_end = right( this.text, Len( this.text) - pos( this.text, '~'))
-Paul Horan-

Related

Convert Dropdownlist String Value to Date

I want to do a date comparison to check whether is the Before Period is bigger than After Periode
So far it has been working properly until the date range is a bit tricky
For example
The value is from a dropdownlist item
Before period is 21-10-2022
After period is 04-11-2022
It will trigger the error message I set if the before period is bigger than the period after
I have a code like this
If CDate(ddlPeriodeBefore.SelectedValue) <= CDate(ddlPeriodeBefore.SelectedValue) Then
'Does the job if the the before period is smaller than after period
Else
lblInfo.Text = "Period BEFORE Must Be SMALLER Than Period AFTER."
End If
Can anyone help me? it keeps saying "conversion from string to date is not valid"
I've tried datetime.parse, parse exact, cdate, convert.todatetime but nothing works so far, or maybe I used it the wrong way
Please help, thanks in advance
Tim Schmelter's suggestion is not wrong, but I did want to provide an alternative. Create a collection of Tuple, add the dates (both formatted string and native value) to the collection, then bind the control to the list.
Here is the alternative:
Dim dates As New List(Of Tuple(Of String, DateTime))()
Dim today = DateTime.Today
For daysSubtract = 90 To 0 Step -1
Dim dateToAdd = today.AddDays(-daysSubtract)
dates.Add(New Tuple(Of String, DateTime)(dateToAdd.ToString("dd-MM-yyyy"), dateToAdd))
Next
ddlPeriodeBefore.ValueMember = "Item1"
ddlPeriodeBefore.DisplayMember = "Item2"
ddlPeriodeBefore.DataSource = dates
ddlPeriodeAfter.ValueMember = "Item1"
ddlPeriodeAfter.DisplayMember = "Item2"
ddlPeriodeAfter.DataSource = dates
Now when you go to get the selected value, you can use a simpler conversion since the stored object is already a DateTime:
Dim beforePeriod = DirectCast(ddlPeriodeBefore.SelectedValue, DateTime)
Dim afterPeriod = DirectCast(ddlPeriodeAfter.SelectedValue, DateTime)
If (beforePeriod <= afterPeriod) Then
' ...
Else
lblInfo.Text = "Period BEFORE Must Be SMALLER Than Period AFTER."
End If
The advantage to this approach is that you do not have to refactor your code if the date formatting changes.
If DateTime.Parse works depends on your curren culture because you don't pass any. For me this works fine (but for you not):
Dim selectedValue1 = "21-10-2022"
Dim selectedValue2 = "04-11-2022"
Dim beforePeriod = Date.Parse(selectedValue1)
Dim afterPeriod = Date.Parse(selectedValue2)
So either you know the correct culture that you have used when you have created this string, then you can pass this as second parameter to Date.Parse, or you use ParseExact:
Dim beforePeriod = Date.ParseExact(selectedValue1, "dd-MM-yyyy", CultureInfo.InvariantCulture)
Dim afterPeriod = Date.ParseExact(selectedValue2, "dd-MM-yyyy", CultureInfo.InvariantCulture)
The culture is relevant because they can have different date separators and the order of the day-, month- and year-tokens are different.

Filter phone numbers from open text field - Power BI, excel, VBA

I have a text field in a table where I need to substitute phone numbers where applicable.
For example the text field could have:
Call me on 08588812885 immediately
Call me on 07525812845
I need assistance please contact me
Good service
Sometimes a phone number will be in the text but not always and the phone number entered will always be different.
Is there a measure to use to replace the phone numbers with no text.
Ideally the solution would be Power BI, but can also be done in the raw data using excel or VBA
Regular expression in VBA (excel) or Python (Power BI) is a straightforward solution.
I have never used PowerBI with Python before but manage to make following python script.
In PowerBI transformation steps I created a new column that would copy [message] columns and named it [noPhoneNumber], then next step ran this python script
import re
def removePhone(x):
return re.sub('\d{10,11}', "**number removed**", x)
length = len(dataset["noPhoneNumber"])
for iRow in range(length):
dataset["noPhoneNumber"][iRow] = removePhone(dataset["noPhoneNumber"][iRow])
so column "noPhoneNumber"
Call me on 08588812885 immediately
Call me on 07525812845
I need assistance please contact me
Good service
becomes
Call me on **number removed** immediately
Call me on **number removed**
I need assistance please contact me
Good service
In VBA Preferable create UDF (user defined function) and don't create a subroutine, that would be too error prone for this kind of problem.
[Added]
If you need to make a Excel based solution, you can create a UDF function like so:
(remember early binding to import of VBScript_RegExp_55.RegExp in excel)
Function removePhoneNumber(text As String, Optional replacement As String = "**number removed**") As String
Dim regex As New RegExp
regex.Pattern = "\d{10,11}"
removePhoneNumber = regex.Replace(text, replacement)
End Function
...and then use excel function like so:
=removePhoneNumber(A2),
=removePhoneNumber(A3)
and so on...
A simple VBA function alternative
Function removePhone(s As String) As String
Const DELIM As String = " "
Dim i As Long, tokens As Variant
tokens = Split(s, DELIM)
For i = LBound(tokens) To UBound(tokens)
If IsNumeric(tokens(i)) Then
tokens(i) = "*Removed*" ' << change to your needs
Exit For ' assuming a single phone number per string
End If
Next
removePhone = Join(tokens, DELIM)
End Function
You can do this in Power Query. Create a custom column with this below code. I have considered the column name is Comments but please adjust this with your column name.
if Text.Length(Text.Select([comments], {"0".."9"})) = 11
then
Text.Replace(
[comments],
Text.Select([comments], {"0".."9"}),
""
)
else [comments]
Here is the output below. You can also replace phone numbers with other text like #### to make is anonymous.
NOTE
This will only work if there are only 1 number in the string with length 11 (You can adjust the length in code as per requirement).
This will Not work if there are more than one Numbers in the string.
If there are 1 number in the string but length not equal 11, this will keep the whole string as original.

Excel TEXT(dd.mm.yyyy) function and different client languages

How can I make a function with a formatted date that will work in every language? I want to make the following function:
=CONCATENATE(TEXT(C8;"TT.MM.JJJJ");"/";G8)
The problem here is, that I use the english client but because I'm a german, excel forces me to use T for day and J for year. I think this will cause problem on a PC located in england (for example).
I think [$-409] won't work because I still have to use T for day and J for year. Is there a good solution for this (function wise)?
If you pass the value of a formula in "" then it cannot be changed based on the localisation settings.
A good way to do it is to use a custom function with VBA, returning "TT.MM.JJJJ" if you are in Germany and "DD.MM.YYYY" if you are in England.
Public Function CorrectString() As String
Select Case Application.International(XlApplicationInternational.xlCountryCode)
Case 1
CorrectString = "DD.MM.YYYY"
Case 49
CorrectString = "TT.MM.JJJJ"
Case Else
CorrectString = "ERROR"
End Select
End Function
Would allow you to call the function like this:
=CONCATENATE(TEXT(C8;CorrectString());"/";G8)
And depending on the excel language, it would give either the German or the English versions.
To simplify the formula, try calling only:
=TEXT(21322;CorrectString())
This should return 17.05.1958.
Source for the regional languages, mentioned by #Dan at the comments:
https://bettersolutions.com/vba/macros/region-language.htm
Or run this to see the corresponding number of your current Excel:
MsgBox xlApplicationInternational.xlCountryCode
Just dropping in another imho elegant (VBA free) alternative taken from: Stackoverflow answer by #Taosique
=IF(TEXT(1,"mmmm")="January",[some logic for English system],[some logic for non-English system])
I've had the same problem and solved it with similar VBA Function. My function accepts input in international format, and outputs the local version for user.
Please see code below:
Function DateFormater(sFI As String)
Dim aFI() As String
aFI = split(StrConv(sFI, vbUnicode), Chr$(0))
ReDim Preserve aFI(UBound(aFI) - 1)
For i = 0 To UBound(aFI)
Select Case (aFI(i))
Case "m", "M"
DateFormater = DateFormater & Application.International(xlMonthCode)
Case "y", "Y"
DateFormater = DateFormater & Application.International(xlYearCode)
Case "d", "D"
DateFormater = DateFormater & Application.International(xlDayCode)
Case Else
DateFormater = DateFormater & aFI(i)
End Select
Next i
End Function
A simpler solution is to use generic Excel functions.
=CONCATENATE(TEXT(DAY(C8;"00");".";TEXT(MONTH(C8);"00");".";YEAR(C8);"/";G8)

How can I pick specific string fragments out of an excel cell using a custom formula written in VBA

At work I am required to reformat incorrect Addresses on a weekly basis from records in our Salesforce instance. We gather the incorrectly formatted addresses using a Report and export them to an Excel file. My job is simply to manipulate the data in the file to format them properly then reinsert them into the database.
Typically the addresses are formatted as so:
5 Sesame Street, Anytown, Anyplace
Separating these can be done easily by hand, but I typically have to work with hundreds of addresses at a time, and using default excel formulas tends to require lots of wrangling multiple cells at once to break it up into fragments.
Thus I wrote a custom formula to run through the cell and return a specific fragment of the string based on the "Comma Number" given. So if I give a Comma Number of 1, I would get "5 Sesame Street", 2 would get me "Anytown", etc.
Here is my code so far:
Public Function fragmentAddress(address As String, numberofcommas As Integer) As String
seen = 1
lastComma = -1
Dim x As Long
Dim frag As Long
For x = 0 To Len(address)
If Mid(address, x, 1) = "," & numberofcommas = seen Then
Exit For
ElseIf Mid(address, x, 1) = "," & numberofcommas <> seen Then
seen = seen + 1
lastComma = x
End If
Next
frag = Mid(address, lastComma + 1, seen - lastComma)
fragmentAddress = frag
I have not implemented the ability to handle the final value yet, but it does not give me any outputs, only outputting a "#VALUE!" error when I attempt to give it the input
=fragmentAddress("3 Ashley Close, Charlton Kings",1)
I have some experience with programming, but this is my first time writing anything in VBA.
Any help would be appreciated, thank you.
Not exactly sure what your question is, but this is simpler:
Public Function GetAddressFragment(ByVal Address As String, ByVal Index As Integer) As String
Dim addr() As String
addr = Split(Address, ",")
On Error Resume Next
GetAddressFragment = Trim(addr(Index - 1))
End Function

Formatting strings in a text field in Crystal Reports XI

Good morning!
I'm hoping someone can help me with what is probably a simple question but I just cant get things to work the way I would like. I am currently working with a report that has a "catch-all" text field. In this field the user can input anything they want, and on occasion, will input information in a column format (ex. 1.1). This field allows carriage returns which are used to create "rows" in this field. The problem is that the user wants the "columns" in this field to line up on the report without having to count spaces between the columns when the information is entered (ex. 1.2). The problem is that even when this type of information is entered there is no set protocol or formatting guidelines. There may be multiple "subtitles", rows, rows separated by subtitles, etc.. The carriage return (Chr(10)) at the end of each line (or beginning of each new line) is the only thing that can be relied on consistantly.
I am currently trying to seperate each individual row, format each as desired, and put it back together like so:
Dim output As String
Dim sections as String
Dim returnCount as Int
Dim leftText as String
Dim rightText as String
Dim sectionTogether as String
Dim totalText as String
Dim textLength as Int
output = {table.textfield}
sections = ExtractString(output, Chr(10), Chr(10))
If Instr(sections," ") > 0 Then
leftText = Left(sections, Instr(sections, " "))
textLength = Length(Left(sections, Instr(sections, " "))
rightText = Right(sections, Instr(sections, " "))
Replace(sections," "," ")
sectionTogether = rightText + (Space(20) - (textLength - 3)) + leftText
totalText = totalText + sectionTogether
formula = totalText
else
formula = output
This is the gist of what I'm trying to do. A couple of notes:
1) I know I am missing a loop of some kind to format every section but I dont know how to set that up in crystal
2) I have VB programming experience, but I am noob in crystal and its limited tools so I feel hamstringed and I'm having trouble finding the methods and tools I would use in Visual Studio
3) My syntax may also be off in a few places because I am still learning how to set this up and I REALLY miss a debugger.
I hope someone can help me, I have been researching for over a week and it feels like I'm just beating my head against a wall.
Thank you in advance.
The output examples
ex. 1.1
"Your current charges are:
Jan 12.89
Feb 117.44
Mar 15.02
Apr 4.17"
ex. 1.2
"Your current charges are:
Jan 12.89
Feb 117.44
Mar 15.02
Apr 4.17"
The first thing you're going to want to do is split up your rows via split(), like this:
local stringvar array wallOText := split({table.textfield},chr(10));
This will give you an array of strings where each array entry is a "row". Now you can loop over your rows with the following:
for i := 1 to ubound(wallOText) step 1 do <some stuff to wallOText[i]>
Now, getting the columns right-justified is a little trickier, but here's some code to get you started. You can adjust the column widths to whatever you may need (in this case, 20 spaces). Also note, you have to use a fixed-width font.
local stringvar output;
local stringvar array row;
local numbervar i;
local numbervar j;
local stringvar array wallOText := split({#some text},chr(10));
local stringvar elem;
for i := 1 to ubound(wallOText) do //loop over lines
(row := split(wallOText[i]," ");
for j := 1 to ubound(row) do //loop over words
(elem := trim(row[j]); //get current element and cut white space
if not(elem="") then
output := output + space(20-len(elem)) + elem); //build output string
output := output + chr(10));
output

Resources