How to convert or replace the string "-" to bracket "()" in vba - arrays

Dear All Master,
How to convert or replace the string "-" to bracket "()" in vba ?.
I can only do it manually with find and replace. The original record there were three thousand.
please recommend the solution.
FILENAME
DESIRED FILENAME
4715-(0).jpg
4715(0).jpg
TC45-1.jpg
TC45(1).jpg
TC51-1b.jpg
TC51(1b).jpg
TC52-B-1.jpg
TC52(B1).jpg
WSO.19-A.jpg
WSO.19(A).jpg
N.WAB25-AF.jpg
N.WAB25(AF).jpg
WA.4-K1.jpg
WA.4(K1).jpg
PD.133-AFa.jpg
PD.133(Afa).jpg
KP02-10.jpg
KP02(10).jpg
01-4-1-B.jpg
01-4-1(B).jpg
01-4-01-1.jpg
01-4-01(1).jpg

You could have a go with a regular expression. Something like:
-\(?(\w+)\)?(\.\w+)$
See an online demo
-\(? - Match an hyphen and an optional literal opening paranthesis;
(\w+) - A 1st capture group to match 1+ word-characters;
\)? - An optional closing paranthesis;
(\.\w+) - A 2nd capture group just to assert that previous matches are done before the extension. Here we match a dot and 1+ word-characters;
$ - End-line anchor to assert all previous matching is done at end of string.
You could chuck this into a VBA UDF and either call it from inside another sub or directly from th worksheet:
Public Function RegexReplace(s As String) As String
Static RE As Object: If RE Is Nothing Then Set RE = CreateObject("vbscript.regexp")
RE.Pattern = "-\(?(\w+)\)?(\.\w+)$"
RegexReplace = RE.Replace(s, "($1)$2")
End Function

Related

Snowflake REGEXP_REPLACE guidence

I'm looking for some assistance in debugging a REGEXP_REPLACE() statement in Snowflake.
I wanted to replace |(pipe) between double quoted string only with #.
Example:
"Foreign Corporate| Name| Registration"|"99999"|"Valuation Research"
Required Result:
"Foreign Corporate# Name# Registration"|"99999"|"Valuation Research"
I have tried regex101.com with (?!(([^"]"){2})[^"]*$)[|] and substitution\1#, works, but doesn't work in Snowflake.
The regexp functions in Snowflake do not lookahead and lookbehind. If you want to use regular expressions with lookahead and lookbehind functions, you can do so in a JavaScript UDF.
Note that the regular expression here finds all the pipes including those inside double quotes. I was able to find a regular expression that finds pipes outside double quotes, which is why this UDF splits by those findings and rejoins the string. If you can find a regular expression that finds the pipes inside rather than outside the double quotes, you can simplify the UDF. However, splitting it allows other possibilities such as removing wrapping quotes if you want to do that.
set my_string = '"Foreign Corporate| Name| Registration"|"99999"|"Valuation Research"';
create or replace function REPLACE_QUOTED_PIPES(STR string)
returns string
language javascript
as
$$
const search = `(?!\\B"[^"]*)\\|(?![^"]*"\\B)`;
const searchRegExp = new RegExp(search, 'g');
var splits = STR.split(searchRegExp);
var out = "";
var del = "|";
for(var i = 0; i < splits.length; i++) {
if (i == splits.length -1) del = "";
out += splits[i].replace(/\|/g, '#') + del;
}
return out;
$$;
select REPLACE_QUOTED_PIPES($my_string);
Different approach, just using REPLACE
Replace "|" with a string that will never appear in your data. I've used ### in my example
Replace the remaining pipes with #
Replace the dummy string, ###, back to the original value "|"
e.g.
replace(replace(replace(sample_text,'"|"','###'),'|','#'),'###','"|"')
SQL statement to show each step:
select
sample_text
,replace(sample_text,'"|"','###') r1
,replace(replace(sample_text,'"|"','###'),'|','#') r2
,replace(replace(replace(sample_text,'"|"','###'),'|','#'),'###','"|"') r3
from test_solution;

calculating null or empty value in Access report returns #Type! error

i have database which has Column 'Name' of the employee with "Surname, Name" like ' Gambel, Peter'.
I want to replace this name in report like ' Peter. G'. I have created a Vba function which converts the Name like as shown above, but if the field value is empty than it always return me '#Type!'. I have tried a lot but still i am unable to resolve this error.
Public Function name_change(Name_pass As String) As String
If (IsNull(Name_pass) Or Name_pass = "") Then
name_change = "-"
Else
Dim Name_split() As String
Name_split = split(Name_pass, ",")
Name_split(0) = Left$(Name_split(0), 1)
name_change = Name_split(1) & "." & Name_split(0)
End If
End Function
If not comma is present, UBound of of Name_split is 0 and Name_split(1) will fail.
As Gustav points out you are only checking for an empty string, but not for one that has no comma. You need something like this:
If Nz(Name_pass) LIKE "*,*" Then
Dim Name_split() As String
Name_split = split(Name_pass, ",")
Name_split(0) = Left$(Name_split(0), 1)
name_change = Name_split(1) & "." & Name_split(0)
Elseif Trim(Nz(Name_pass)) = "" then
name_change = "-"
Else
[Deal with names that have content but not comma]
End if
Finally I find the answer.
In control source before passing the value to function we have to check the value is Null or not with NZ function.
=name_change(Nz([Name],"-"))
Thanks guys for your input.

VB.NET removing formatting from a formatted Phone number before inserting into SQL Server

I have a string when a telephone number is inputted - there is a mask so it always looks like (123) 456-7890 - I'd like to take the formatting out before saving it to the DB. I have it set up to only 10 charachters as nvarchar(10) - I only need it to be numbers like this 1234567890.
Another way to do it(basically replace every non number character with ""):
Imports System.Text.RegularExpressions //You need to Import this Namespace
Dim phone as string = "(123) 456-7890 -"
Dim match as string = Regex.Replace(phone, "[^\d]", "")
Console.WriteLine(match)
This outputs to: 1234567890
If you are using a MaskedTextBox then you could set the property TextMaskFormat
masked1.Mask = "(999)999-9999"
tb.Text = "(123)456-7890";
masked1.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals
....
Console.WriteLine(masked1.Text) ' => 1234567890
and when you get the Text property you get only the characters excluding the formatting characters
Notice that I have set the mask with 9 to allow only numbers. This of course depends on how telephone numbers are expected by your application.

how to copy excel column data to another worksheet and do text-to-columns programatically

I have a working copy of an application that will open workbooks/sheets and copy data succesffully between the two then saves but I need to parse some data as I copy it into another cell.
I was thinking..
~ create array
~ get all values in xlSourceFile.worksheets("sheet1") and store into an array
~ parse through the array extracting the data I need (text-to-column programatically)
~ write the array data to two specific columns in excel worksheet
the data I am trying to parse is Firstname / Lastname - Email and I want this as a result:
Joe Shmoe to go into one column // Joe Shmoes Email to another column.
I am writing this in vb.net using the imports Microsoft.Office.Interop to manipulate Excel.
Excuse the formatting, I'm new to SO. This is VBA but I believe the general logic will work. It assumes that the email address has no space padding after it. It searches backward on the raw combined string for the first blank space and flags that as the start of the email address (end of the name).
It loops out when the next cell is empty.
The data is assumed to look like this:
"First Name Last Name myaddress#example.com"
For Each cell In Worksheets("Sheet1").Range("A:A")
i = i + 1
If cell = "" Then GoTo loopout
rawstring = cell.Value
'rawString = "First Name Last Name myaddress#example.com"
emailStartPosition = InStrRev(rawstring, " ")
myname = Left(rawstring, emailStartPosition)
myemail = Right(rawstring, Len(rawstring) - emailStartPosition)
Worksheets("Sheet1").Range("B" & i).Value = myname
Worksheets("Sheet1").Range("C" & i).Value = myemail
Next
loopout:
End Sub
Column B will have the name and Column C will have the email address.

Nested loop conditional

Supposed I have this table:
TDID TDLINE
F04 04-AA
F04 04-BB <-- call a function
F05 05-AA
F05 05-BB <-- call a function
F06 06-AA <-- call a function
I would like to call a function while the TDID field is not the same as the previous one. I have the code below, it works but somehow it's not perfectly works (it missed the last row):
LOOP AT lines ASSIGNING <fs1>.
IF <fs2> IS INITIAL.
<fs2> = <fs1>.
ELSE.
li_line-tdline = <fs2>-tdline.
APPEND li_line.
IF <fs1>-tdid NE <fs2>-tdid.
li_thead-tdid = <fs2>-tdid.
CALL FUNCTION 'SAVE_TEXT'
EXPORTING
header = li_thead
savemode_direct = 'X'
TABLES
lines = li_line
CLEAR: li_thead,
li_line.
FREE: li_thead,
li_line.
ENDIF.
ENDIF.
ENDLOOP.
ANSWER
Thank you to vwegert for the answer:
LOOP AT lines ASSIGNING <fs1>.
AT NEW tdid.
REFRESH li_thead.
REFRESH li_line.
li_thead-tdid = <fs1>-tdid.
APPEND li_thead.
ENDAT.
li_line-tdline = <fs1>-tdline.
APPEND li_line.
AT END OF tdid.
CALL FUNCTION 'SAVE_TEXT'
EXPORTING
header = li_thead
savemode_direct = 'X'
TABLES
lines = li_line
ENDAT.
ENDLOOP.
Assuming that the table is sorted by TDID and no field left of TDID changes more frequently than TDID:
LOOP AT lines ASSIGNING <fs1>.
AT NEW tdid.
REFRESH some_other_tab.
ENDAT.
APPEND <fs1> TO some_other_tab.
AT END OF tdid.
CALL FUNCTION ...
ENDAT.
ENDLOOP.
The unpredictability as mentioned by vwegert comes because the characters fields next to the field on which Control statement is applied are converted to asterisks(*). If you want to use these values in the control statement make sure you copy the values in a temporary table and loop on it instead of the original internal table and use the values using READ on the original internal table. Also keep in mind that control statement considers all columns to the left of the column being used in the statement for it's condition.

Resources