I have declared and assigned a value to a string variable in VBA.
The variable contains a number of line breaks, can you advise how to remove these, this variable has been assigned a value from an xml document using the following code:-
s = Application.GetOpenFilename()
myFolder = ActiveWorkbook.Path
s = Dir(myFolder & "\*.xml")
Do While s <> ""
If s <> "False" Then
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(s) Then
t = myFolder & "\" & Replace(FSO.GetTempName(), ".tmp", ".xml")
Name s As t
Set ts(0) = FSO.OpenTextFile(t, 1, False, -2)
FileContents = ts(0).READALL
ts(0).Close
Set ts(0) = Nothing
End If
End If
s = Dir$
loop
Can anyone advise a solution?
Thanks Nick
First, you need to determine which line break your variable has - or you can test for all of them using multiple replaces. Luckily, VBA has the vbConstants for line breaks which make your life a little easier:
myStr = Replace(myStr, vbCr, " ")
myStr = Replace(myStr, vbLf, " ")
myStr = Replace(myStr, vbCrLf, " ") '// or vbNewLine
Notice I've used a space as the replacement otherwise you will end up with words being merged:
Example of some text
with a line break
replacing the line break with a zero length string "" would result in:
Example of some textwith a line break
whereas replacing with a space " " will produce:
Example of some text with a line break
Just for fun another way of doing this is like so:
myStr = Join$(Split(myStr, vbCrLf), " ")
This uses the line break as a delimiter to split the string out into a single dimension array, then joins each element of the array with a space. No real advantage in either method just down to preference in this case.
Related
I want to create a code which looks for the file in the file directory and tells me if its there given only a fraction of the file name.
I have put this fraction i column I8 of the Macro sheet which is a number "121"
The below code works if i manually put the number 121 instead of i, but when referencing i from the cell it just flags a random excel file in the directory
Dim FilePath3 As String
Dim i As String
FilePath3 = Sheets("Macro").Range("J6")
i = Sheets("Macro").Range("I8")
file = Dir$(FilePath3 & "*i*" & ".*")
If (Len(file) > 0) Then
MsgBox "found " & file
End If
i is inside of your block of text "*i*" , so it isn't the variable i that you defined earlier in the code!
Furthermore, you can use Dir() inside of a loop like this to see if there is multiple results :
Dim FilePath3 As String
Dim i As String
FilePath3 = Sheets("Macro").Range("J6")
i = Sheets("Macro").Range("I8")
file = Dir$(FilePath3 & "*" & i & "*.*")
Do While file <> vbNullString
If (Len(file) > 0) Then
MsgBox "found " & file
End If
file = Dir()
Loop
Filename = Dir(Filepath & "\" & "*.csv")
While Filename <> ""
SourceFile = Filepath & "\" & Filename
TargetFile = SavePath & "\" & Replace(Filename, ".csv", ".txt")
OpenAsUnicode = False
Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject")
'Detect Unicode Files
Dim Stream: Set Stream = objFSO.OpenTextFile(SourceFile, 1, False)
intChar1 = Asc(Stream.Read(1))
intChar2 = Asc(Stream.Read(1))
Stream.Close
If intChar1 = 255 And intChar2 = 254 Then
OpenAsUnicode = True
End If
'Get script content
Set Stream = objFSO.OpenTextFile(SourceFile, 1, 0, OpenAsUnicode)
arrData = Stream.ReadAll()
Stream.Close
'Create output file
Dim objOut: Set objOut = objFSO.CreateTextFile(TargetFile)
objOut.Write Replace(Replace(arrData,",", "#|#"), Chr(34), "") '-- This line is working fine but it is replacing all the commas inside the text qualifier as well..
objOut.Close
Filename = Dir
Wend
In the above code the line objOut.Write Replace(Replace(arrData,",", "#|#"), Chr(34), "") is replacing all the commas with #|# including the commas inside string.so I want to replace only commas which are not in double quotes.
File containing the string
"A","B,C",D
Result I need is
A#|#B,C#|#D
Thanks for your help in advance.
How about something along the line of:
objOut.Write Mid(Replace(Replace(arrData,""",""", "#|#"), Chr(34), ""), 2)
Basically, this exchanges now "," for #|#. But that's not enough as the file begins with a ". So, this one is being eliminated using the Mid() function. If the file also ends with a " then you would have to adjust that as well.
Based on the speed concerns noted in the comments here is the complete code which I used to test this solution:
Option Explicit
Option Compare Text
Public Sub ConvertFile()
Dim lngRowNumber As Long
Dim strLineFromFile As String
Dim strSourceFile As String
Dim strDestinationFile As String
strSourceFile = "C:\tmp\Extract.txt"
strDestinationFile = "C:\tmp\Extract_b.txt"
Open strSourceFile For Input As #1
Open strDestinationFile For Output As #2
lngRowNumber = 0
Do Until EOF(1)
Line Input #1, strLineFromFile
strLineFromFile = Mid(Replace(strLineFromFile, """,""", "#|#"), 2)
Write #2, strLineFromFile
strLineFromFile = vbNullString
Loop
Close #1
Close #2
End Sub
The tested file was 350 MB with a bit over 4 million rows. The code completed in less than a minute.
Interesting problem here. This line of code works through multiple iterations until it reaches a point where it throws an Run-time error 91 at me: "Object Variable or With block variable not set". This is occurring in a function designed to find a deal number. The entire program is an end of day email generation program that sends attachments to various different counter-parties. The error occurs on the ** line. For additional color, temp deal is not empty when execution is attempted. There doesn't appear to be any extraneous trailing or leading spaces either. Thanks in advance!
Function getPDFs(cFirm As Variant, iFirm As Variant, row_counter As Variant, reportsByFirm As Worksheet, trMaster As Worksheet, trSeparate As Variant, trName As Variant, reportDate As Variant) As String
dealCol = 1
Dim locationArray() As String
Dim DealArray() As String
cDes = "_vs._NY"
iDes = "_vs._IC"
filePath = "X:\Office\Confirm Drop File\"
dealNum = reportsByFirm.Cells(row_counter, dealCol)
FileType = ".pdf"
If InStr(1, dealNum, "-") > 0 Then
DealArray() = Split(dealNum, "-")
tempDeal = DealArray(LBound(DealArray))
Else
tempDeal = dealNum
End If
'Finds deal location in spread sheet for further detail to obtain file path
**trLocation = trMaster.Columns(2).Find(What:=tempDeal).Address
locationArray() = Split(trLocation, "$")
trRow = locationArray(UBound(locationArray))
'Formats client names for 20 characters and removes punctuation (".") in order to stay within convention of file naming
cFirmFormatted = Trim(Left(cFirm, 20))
iFirmFormatted = Trim(Left(iFirm, 20))
'Finds clearing method
clMethod = trMaster.Cells(trRow, 6).Value
Select Case clmethod
Case "Clport"
'Prevents naming convention issues with punctuations in the name
If InStr(1, cFirmFormatted, ".") > 0 Then
cFirmFormatted = Replace(cFirmFormatted, ".", "")
End If
getPDFs = filePath & cFirmFormatted & "\" & reportDate & "_" & dealNum & "_" & cFirmFormatted & cDes & FileType
Case "ICE"
If InStr(1, iFirmFormatted, ".") > 0 Then
iFirmFormatted = Replace(iFirmFormatted, ".", "")
End If
getPDFs = filePath & iFirmFormatted & "\" & reportDate & "_" & dealNum & "_" & iFirmFormatted & iDes & FileType
End Select
End Function
Your code assumes that trLocation is always found, if it isn't found then you will receive an error because you don't have a range to return the .Address property for.
Try testing the result first:
Dim testLocation As Excel.Range
Set testLocation = trMaster.Columns(2).Find(tempDeal)
If Not testLocation Is Nothing Then
trLocation = testLocation.Address
'// Rest of code here...
Else
MsgBox "Cannot find """ & tempDeal & """!"
Exit Function
End If
I have around 400 textfiles with circa 41000 corrupt lines.
I am searching for an option (VBA maybe?) which searches for these corrupt lines and basically executes a backspace, so that the corrupt lines are written behind the line before, because the corruption is caused by an unwanted wordwrap. The indicator for corrupt lines is that they don't start with the letters TEQ.
Has anyone any idea how and where to build a script like that? Search and replace does not work since i cant but a backspace in the replace field obviously.
Thanks in advance!
EDIT:
An example of a corrupted line:
TEQ;231232;OFNENJD;29840389;TPOS;
TEQ;54111232;O2D;29829;
TPOS;
Line 3 is the corrupted one since it belongs to line 2 but there was a wordwrap. I need to execute a backspace to get it back behind line 2. That's what i'd like to have automated.
To isolate the bad end-of-lines, first convert the good end-of-lines to an abstract. You can then remove the vbCrLF or vbLf which will have the effect of backspacing them away. The last step would be to restore the good end-of-lines by reversing the abstract.
dim str as string
'use your favorite method to read the TXT file into the str variable
str = Replace(str, chr(59) & vbCrLf & "TEQ;", chrw(8203)) 'convert good eol to unicode zero-length space
str = Replace(str, vbLf, vbNullString) 'remove bad eols
str = Replace(str, chrw(8203), chr(59) & vbCrLf & "TEQ;") 'revert back to good eol
'write the str back to the TXT file
It wouldn't be a bad idea to throw a few of the .TXT files into a hex editor to determine whether the bad end-of-lines are created with vbCrLf (Chr(13) & Chr(10)) or just vbLf (Chr(10)). Same with the good end-of-lines although I suspect the good ones will be vbCrLF and the bad ones just vbLf.
The following Sub procedure requires that you go into the VBE's Tools ► References and add Microsoft Scripting Runtime to the project.
Sub fix_TEQ_text()
Dim str As String, fp As String, fn As String
Dim fso As New FileSystemObject, ts As TextStream
fp = Environ("TEMP")
fn = Dir(fp & Chr(92) & "TEQ*.txt", vbNormal)
Do While CBool(Len(fn))
If Not CBool(InStr(1, fn, "_fixed", vbTextCompare)) Then
Set ts = fso.OpenTextFile(fp & Chr(92) & fn, ForReading)
str = ts.ReadAll
ts.Close
str = Replace(str, Chr(59) & vbCrLf & "TEQ;", ChrW(8203)) 'convert good eol to unicode zero-length space
str = Replace(str, vbLf, vbNullString) 'remove bad eols
str = Replace(str, ChrW(8203), Chr(59) & vbCrLf & "TEQ;") 'revert back to good eol
Set ts = fso.CreateTextFile(fp & Chr(92) & Replace(fn, ".txt", "_fixed.txt"), True)
ts.Write str
ts.Close
End If
fn = Dir
Loop
End Sub
You will want to change the file path (e.g. fp) and the file mask (currently "TEQ*.txt" which matched my sample TXT files).
I have the following VBA code:
Sub read_in_data_from_txt_file()
Dim dataArray() As String
Dim i As Integer
Const strFileName As String = "Z:\sample_text.txt"
Open strFileName For Input As #1
' -------- read from txt file to dataArrayay -------- '
i = 0
Do Until EOF(1)
ReDim Preserve dataArray(i)
Line Input #1, dataArray(i)
i = i + 1
Loop
Close #1
Debug.Print UBound(dataArray())
End Sub
I'm trying to read in text line by line (assume 'sample.txt' is a regular ascii file) from a file and assign this data to consecutive elements in an array.
When I run this, I get all my data in the first value of the array.
For example, if 'sample.txt' is:
foo
bar
...
dog
cat
I want each one of these words in a consecutive array element.
What you have is fine; if everything ends up in dataArray(0) then the lines in the file are not using a CrLf delimiter so line input is grabbing everything.
Instead;
open strFileName for Input as #1
dataArray = split(input$(LOF(1), #1), vbLf)
close #1
Assuming the delimiter is VbLf (what it would be coming from a *nix system)
Here is a clean code on how to use for each loop in VBA
Function TxtParse(ByVal FileName As String) As String
Dim fs, ts As Object
Dim strdic() As String
Dim oitem As Variant
Set fs = CreateObject("Scripting.FileSystemObject")
Set ts = fs.OpenTextFile(FileName, 1, False, -2)
strdic = Split(ts.ReadAll, vbLf)
For Each oitem In strdic
If InStr(oitem, "YourString") <> 0 Then
Else
If InStr(1, oitem, vbTab) <> 0 Then
Debug.Print "Line number is : "; "'" & Replace(oitem, vbTab, "','") & "'"
Else
Debug.Print "Line number is : "; "'" & Replace(oitem, ",", "','") & "'"
End If
End If
Next
End Function