Find and Replace text using VBA - vba

I use Excel VBA and the following method to search a string in html files, and replace it with the same string after adding bold tag.
FindAndReplace ("C:\xxx.htm", "hello world", "<b>hello world</b>")
Private Sub FindAndReplace(filePath As String, findWhat As String, replaceWith As String)
Dim nextFileNum As Long
Dim oldFileContents As String
Dim newFileContents As String
Dim textFileTypes() As String
Dim fileExtension As String
Dim sFileName As String
Dim iFileNum As Integer
Dim sBuf As String
Dim strFound As Integer
If Len(Dir(filePath)) = 0 Then
Exit Sub
End If
nextFileNum = FreeFile
Open filePath For Input As #nextFileNum
oldFileContents = Input$(LOF(nextFileNum), #nextFileNum)
Close #nextFileNum
newFileContents = Replace(oldFileContents, findWhat, replaceWith)
nextFileNum = FreeFile
Open filePath For Output As #nextFileNum
Print #nextFileNum, newFileContents
Close #nextFileNum
End Sub
The problem I am facing is the function won;t find the string if it splits in between because of the html source code line break.
For example, the string is found if the code is:
<p>hi hola hello world</p>
but it is not found if the code is:
<p>hi hola hello
world</p>
Is there any other VBA method that I can use to search and replace text, or some functionality can be added to the above code so that it ignores the line break in between.

Try using a variation of:
Function RemoveCarriageReturns(SourceString As String) As String
Dim s As String
'strip out CR and LF characters together
s = Replace(SourceString, vbCrLf, "")
'just in case, remove them one at a time
s = Replace(s, Chr(13), "")
s = Replace(s, Chr(10), "")
RemoveCarriageReturns = s
End Function
The ASCII characters 13 and 10 are the carriage return and line feed characters.

If the split is only with linefeeds/returns (Chr(10), Chr(13)) and/or spaces Chr(32) then you might just search for "hello" first.
When found look for those characters (10, 13 and 32) and skip over them until you run into something else (use a DO WHILE ... OR ... OR ... OR loop).
Now check if that something else would be "world" and at least 1 of these characters was encountered.
In that case you will change "hello" into "<b>hello" and "world" into "world</b>"

Related

VBA VAL forcing a comma (,) instead of a period (.)

Basically, I am writting a small AutoCAD VBA that reads CSV files to run commands.
First, I put the csv into a string array (as it contains characters as well). One array position I need to use as a double for the command (as it requires it).
I though this would be a simple VAL() since it is supposed to keep the period regardlesss of my region.
Any insight is greatly appreciated.
Private Sub CommandButton2_Click()
sfilename = "C:\Users\Patrick.Legault\OneDrive - Cima+\Projects\AutoCAD Styles\" & ComboBox1.Value & ".csv"
Dim sLineFromFile As String
Dim name As String
Dim font As String
Dim height As String
Dim vlineItems() As String
Open sfilename For Input As #1
Do Until EOF(1)
Line Input #1, sLineFromFile
vlineItems = Split(sLineFromFile, ",")
Call add_textstyle(vlineItems)
Loop
Close #1
End Sub
Sub add_textstyle(vlineItems() As String)
'''Patrick Legault 2021-11-15
'''This routine creates new textstyles with height
Dim textStyle As AcadTextStyle
Dim TextColl As AcadTextStyles
Dim newfontstyle As String
Dim fontpath As String
Dim h_long As Double
fontpath = "C:\Users\Patrick.Legault\OneDrive - Cima+\Projects\AutoCAD Styles\Fonts" '''to be changed
Set TextColl = ThisDrawing.TextStyles '''get the textstyles from this drawing
Set textStyle = TextColl.add(vlineItems(1)) '''add new textstyle
textStyle.fontFile = fontpath & "\" & (vlineItems(2)) '''add new font style to textstyle
h_long = CDbl(Val(vlineItems(3))) ''this returns the value with comma
textStyle.height = (h_long)
MsgBox h_long
End Sub
The csv in question is below:
Text,STD,Romans.shx,2.032,Main Text heght and style
Text,MD,Romans.shx,3.048,
Text,LG,Romans.shx,4.064,
Text,BOM TEXT,Romans.shx,1.5875,Text for Bill of Material
Text,BOLD,Bold.shx,5.08,"Custom FortisBC ""SHX file (Bold)"
Text,BOLDFILL,Boldfill.shx,5.08,"Custom FortisBC ""SHX"" file (Boldfill)"
Text,DIM,Romans.shx,0,"Dim used in Dimension Style ""Engineering"""
Text,NAMEPLATE,Romans.shx,6.35,"Use ""bigfont.shx"""

select only text between quotes in VB

Is it some function which can return me text between qoutes.? Text before and between quotes is variable length. I find a function mid but in specify is length. I would like to get from this string text between both quots(APP_STATUS_RUNNING) and (PRIMARY):
string: Error gim_icon_cfg_1 Application with DBID 736 has status "APP_STATUS_RUNNING", runmode "PRIMARY"
Thank you
EDIT: I try to get output to the label but show me error:BC30452: Operator '&' is not defined for types 'String' and '1-dimensional array of String'.
Dim output As String = myProcess.StandardOutput.ReadToEnd()
Dim StandardError As String = myProcess.StandardError.ReadToEnd()
Dim Splitted() As String
Splitted = Split(output, """")
Label1.text="Ahoj " & Splitted & "Error " & StandardError
You can split your string by quotes beeing the delimiter Split(InputString, """") the odd numbers of the output array then are the strings between quotes, the even numbers are the rest.
Option Explicit
Public Sub Example()
Dim InputString As String
InputString = "Error gim_icon_cfg_1 Application with DBID 736 has status ""APP_STATUS_RUNNING"", runmode ""PRIMARY"""
Dim Splitted() As String
Splitted = Split(InputString, """")
' between quotes (all odd numbers)
Debug.Print Splitted(1) ' APP_STATUS_RUNNING
Debug.Print Splitted(3) ' PRIMARY
' rest (all even numbers)
Debug.Print Splitted(0) ' Error gim_icon_cfg_1 Application with DBID 736 has status
Debug.Print Splitted(2) ' , runmode
End Sub
Or:
The follow code gives you what you are trying to have.
In practice you can search patterns that are between quotes then get from each element the first element sliced by quote (which means quote = 0 element = 1 other quote = 2)
Dim s As String = "Error gim_icon_cfg_1 Application With DBID 736 has status ""APP_STATUS_RUNNING"", runmode ""PRIMARY"""
Dim parts() As String = s.Split(" "c).Where(Function(el) el Like "*""*""*").Select(Function(el) el.Split(""""c)(1)).ToArray

How can I format value between 2nd and 4th underscore in the file name?

I have VBA code to capture filenames to a table in an MS Access Database.
The values look like this:
FileName
----------------------------------------------------
WC1603992365_Michael_Cert_03-19-2019_858680723.csv
WC1603992365_John_Non-Cert_03-19-2019_858680722.csv
WC1703611403_Paul_Cert_03-27-2019_858679288.csv
Each filename has 4 _ underscores and the length of the filename varies.
I want to capture the value between the 2nd and the 3rd underscore, e.g.:
Cert
Non-Cert
Cert
I have another file downloading program, and it has "renaming" feature with a regular expression. And I set up the following:
Source file Name: (.*)\_(.*)\_(.*)\_(.*)\_\-(.*)\.(.*)
New File Name: \5.\6
In this example, I move the 5th section of the file name to the front, and add the file extension.
For example, WC1603992365_Michael_Cert_03-19-2019_858680723.csv would be saved as 858680723.csv in the folder.
Is there a way that I can use RegEx to capture 3rd section of the file name, and save the value in a field?
I tried VBA code, and searched SQL examples, but I did not find any.
Because the file name length is not fixed, I cannot use LEFT or RIGHT...
Thank you in advance.
One possible solution is to use the VBA Split function to split the string into an array of strings using the underscore as a delimiter, and then return the item at index 2 in this array.
For example, you could define a VBA function such as the following, residing in a public module:
Function StringElement(strStr, intIdx As Integer) As String
Dim strArr() As String
strArr = Split(Nz(strStr, ""), "_")
If intIdx <= UBound(strArr) Then StringElement = strArr(intIdx)
End Function
Here, I've defined the argument strStr as a Variant so that you may pass it Null values without error.
If supplied with a Null value or if the supplied index exceeds the bounds of the array returned by splitting the string using an underscore, the function will return an empty string.
You can then call the above function from a SQL statement:
select StringElement(t.Filename, 2) from Filenames t
Here I have assumed that your table is called Filenames - change this to suit.
This is the working code that I completed. Thank you for sharing your answers.
Public Function getSourceFiles()
Dim rs As Recordset
Dim strFile As String
Dim strPath As String
Dim newFileName As String
Dim FirstFileName As String
Dim newPathFileName As String
Dim RecSeq1 As Integer
Dim RecSeq2 As Integer
Dim FileName2 As String
Dim WrdArrat() As String
RecSeq1 = 0
Set rs = CurrentDb.OpenRecordset("tcsvFileNames", dbOpenDynaset) 'open a recordset
strPath = "c:\in\RegEx\"
strFile = Dir(strPath, vbNormal)
Do 'Loop through the balance of files
RecSeq1 = RecSeq1 + 1
If strFile = "" Then 'If no file, exit function
GoTo ExitHere
End If
FirstFileName = strPath & strFile
newFileName = strFile
newPathFileName = strPath & newFileName
FileName2 = strFile
Dim SubStrings() As String
SubStrings = Split(FileName2, "_")
Debug.Print SubStrings(2)
rs.AddNew
rs!FileName = strFile
rs!FileName68 = newFileName 'assign new files name max 68 characters
rs!Decision = SubStrings(2) 'extract the value after the 3rd underscore, and add it to Decision Field
rs.Update
Name FirstFileName As newPathFileName
strFile = Dir()
Loop
ExitHere:
Set rs = Nothing
MsgBox ("Directory list is complete.")
End Function

Reading csv file with strange line deliminter in VBA

I have a input file which I am struggling to read in line by line, The file can be found here and is also shown below:
I would like to add the first value as key and the third value as item in a dictonary
Then later I can do this: a = myDictonary("CREATED_BY") and this will then return "Eigil..." (Order and number of lines my vary from time to time..)
But somehow I can not get the split to work:
Dim hf As Integer: hf = FreeFile
Dim lines() As String, i As Long
Open FileName For Input As #hf
Line Input #hf, dataLine
lines = Split(dataLine, vbNewLine)
lines = Split(dataLine, "\n")
lines = Split(dataLine, "CR")
lines = Split(dataLine, "LF")
Close #hf
I also tried to follow this thread
For people who like to use dictinary here is my code for that:
Set getProjectDictionary = CreateObject("Scripting.Dictionary")
Dim item As String
Dim key As String
Dim dataLine As String
Open FileName For Input As 1
While Not EOF(1)
On Error Resume Next
Line Input #1, dataLine
temp = Split(dataLine, ",")
If Not temp(0) = "" Then
getProjectDictionary.Add temp(0), temp(3)
End If
Wend
Close 1
I added some debug output below:
The screenshot you attached shows that the file uses CR LF as linebreaks but the file I downloaded from your Google Drive link actually uses LF only, so you might want to use:
lines = Split(dataLine, vbLf)
Also, the file uses Little Endian UCS-2 encoding with BOM. If you simply open the file using the Open statement, you are likely to run into corrupt characters and other encoding related problems. I would suggest using Filesystem object instead.
I think this has the answer - split on vbcrlf?
CRLF in VBScript
Of the 4 examples you gave, "CR" and "LF" would look for the literal strings "CR" and "LF", which is not what you want. VB doesn't recognize "\n" like most C-like languages, so that's out. vbnewline was the closest to working, but I think this might help you:
http://www.jaypm.com/2012/08/the-difference-between-vbcrlf-vbnewline-and-environment-newline/
Here is my code that currently seems to work well:
Option Explicit
Sub test()
Dim a As Object
Set a = getPropertiesDictionary("c:\Temp\Creo\param_table.csv")
Debug.Print a.item("PTC_WM_CREATED_BY")
End Sub
' populate dictinoary with document types based on input file
Function getPropertiesDictionary(FileName As String) As Object
Set getPropertiesDictionary = CreateObject("Scripting.Dictionary")
Dim temp() As String
Dim dataLine As String
Dim hf As Integer: hf = FreeFile
Dim lines() As String, i As Long
Open FileName For Input As #hf
Line Input #hf, dataLine
lines = Split(dataLine, vbLf)
Close #hf
For i = 0 To UBound(lines) - 1
temp = Split(lines(i), ",")
If Not temp(0) = "" Then
getPropertiesDictionary.Add temp(0), temp(2)
End If
Next
End Function

Compile error caused by vba 'Left' trim function in string parser

Im attempting to create a vba function to parse strings of text line by line into an excel table. I'd like the function to only print sub-strings that are between two characters in each line. For example, html tags. While debugging, the Right() function does what I'd like. But the Left() function will not even compile. The error message is very little help, "Invalid procedure call or argument". What is going on? I didn't change that line of code at all and it was just working.
to explain what im trying to accomplish, lets say i'm parsing html text. Id like to only view text inside the "<" and ">" tags. but I'm also trying to code it so I could use this to parse substrings between any two desired characters.
so text like this:
<html>
<head>
</head>
<body>
</body>
</html>
will print:
html
head
/head
body
/body
/html
It was just working. Not sure why I'm getting this error. Only for the Left() trim.
Sub ParseTextFromFile()
Dim myFileName As String
Dim myLine As String
Dim FileNum As Long
Dim n As Integer
n = 1
myFileName = "C:\Users\user\Desktop\myfile.TXT"
FileNum = FreeFile
Close FileNum
Open myFileName For Input As FileNum
Do While Not EOF(FileNum)
Line Input #FileNum, myLine
'Debug.Print TrimString(CStr(myLine))
Cells(n, 1).Value = TrimString(CStr(myLine))
n = n + 1
Loop
MsgBox "" & n - 1 & " items added."
End Sub
'parses a string between two chars/string key values
Function TrimString(s As String) As String
Dim indexOfKey As Integer
Dim firstTrim As String
Dim secondTrim As String
Dim textLength As Integer
Dim key1 As String
Dim key2 As String
firstTrim = ""
secondTrim = ""
key1 = CStr(Cells(5, 8)) 'H5 = "<"
key2 = CStr(Cells(6, 8)) 'H6 = ">"
'remove everything to the left of the first appearance of the key char/string
indexOfKey = InStr(1, s, key1)
firstTrim = Right(s, Len(s) - indexOfKey)
'remove everything to the right of the second appearance of the key char/string
indexOfKey = InStr(1, firstTrim, key2)
secondTrim = Left(firstTrim, indexOfKey - 1) 'this line is throwing the error
TrimString = secondTrim
End Function