Trying to write text to a file error '5' - vba

I am trying to take code, go through it and delete all tags and then write it to a new document testfile.txt. For some reason I am getting an error with line 5:
Set ts = f.openastextstream(forwriting, tristateusedefault)
and am getting error invalid procedure.
Here is my code:
Sub elizabethwhite()
Set fs = CreateObject("scripting.filesystemobject")
fs.createtextfile "testfile.txt"
Set f = fs.getfile("testfile.txt")
Set ts = f.openastextstream(forwriting, tristateusedefault)
textline = ""
Do While f.opentextstream(forwriting, tristateusedefault).atendofstream <> True
textline = textline & f.opentextstream(forwriting, tristateusedefault).readline & "<BR>"
count = 0
pOne = 1
Do While InStr(textline, "<img") <> 0
count = count + 1
pOne = InStr(pOne, textline, "<img")
Do While InStr(pOne, textline, ">") = 0 & ts.atendofstream <> True
pTwo = InStr(pOne, textline, ">")
Loop
If 0 < count < 10 Then
textline = Left(textline, pOne - 1) & "{{image00" & count & ".jpg}}" & Right(textline, pTwo + 1)
ElseIf 9 < count < 100 Then
textline = Left(textline, pOne - 1) & "{{image0" & count & "}}.jpg" & Right(textline, pTwo + 1)
End If
Loop
Loop
ts.write textline
ts.Close
End Sub

Properly declaring your variables, and using Option Explict will identify the problem. Not tomention, these are good habits to develop and will help you write better code. They also enable the script assist feature, which comes in very handy.
The problem is that you have not enabled a reference to MS Scripting Runtime library AND because of this, ForReading and TriStateUseDefault are being interpreted by the compiler as variables and they are variables with no values, so you are passing invalid parameters to the OpenAsTextStream method.
Option Explicit would have helped you identified this error:
If you add a reference to the Microsoft Scripting Runtime, your code will work as-is, but would still urge you to declare ALL variables by type, and use Option Explicit. Both will save you a lot of trouble in the future :)
Sub elizabethwhite()
Dim fs As New Scripting.FileSystemObject
Dim f As Scripting.File
Dim ts As Scripting.TextStream
fs.CreateTextFile "testfile.txt"
Set f = fs.getfile("testfile.txt")
Set ts = f.OpenAsTextStream(ForWriting, TristateUseDefault)
ts.WriteLine "Hello!"
'
'### The rest of your code goes here... remember to declare any other variables :)
'
Set ts = Nothing
Set f = Nothing
Set fs = Nothing
End Sub
See also (documentation about the OpenAsTextStream method):
http://msdn.microsoft.com/en-us/library/aa265341(v=vs.60).aspx

I got this error when I tried to write unicode string to non-unicode text file. You have two options:
Open the file as unicode explicitly
Set ts = f.OpenAsTextStream(ForWriting, TristateTrue)
Convert string from unicode to ASCII before writing to the file
Following code will help you strip unicode characters from output string before writing to the file:
Dim regex
Set regex = CreateObject("vbscript.regexp")
With regex
.Global = True
.Pattern = "[^\u0000-\u007F]+"
End With
MsgBox regex.Replace(Replace(yourStringHere, Chr(160), Chr(32)), vbNullString)
Inner Replace function is just standard VBA Replace which translates one whitespace character to another. I had to add it because regex replace stripped the character \u00A0 too for some reason .
So your code will be:
Sub elizabethwhite()
Dim regex
Set regex = CreateObject("vbscript.regexp")
With regex
.Global = True
.Pattern = "[^\u0000-\u007F]+"
End With
Set fs = CreateObject("scripting.filesystemobject")
fs.createtextfile "testfile.txt"
Set f = fs.getfile("testfile.txt")
Set ts = f.openastextstream(forwriting, tristateusedefault)
textline = ""
Do While f.opentextstream(forwriting, tristateusedefault).atendofstream <> True
textline = textline & f.opentextstream(forwriting, tristateusedefault).readline & " <BR>"
count = 0
pOne = 1
Do While InStr(textline, "<img") <> 0
count = count + 1
pOne = InStr(pOne, textline, "<img")
Do While InStr(pOne, textline, ">") = 0 & ts.atendofstream <> True
pTwo = InStr(pOne, textline, ">")
Loop
If 0 < count < 10 Then
textline = Left(textline, pOne - 1) & "{{image00" & count & ".jpg}}" & Right(textline, pTwo + 1)
ElseIf 9 < count < 100 Then
textline = Left(textline, pOne - 1) & "{{image0" & count & "}}.jpg" & Right(textline, pTwo + 1)
End If
Loop
Loop
ts.write regex.Replace(Replace(textline, Chr(160), Chr(32)), vbNullString)
ts.Close
End Sub
Stripping unicode characters is just a quick-fix for diagnostics. You may have to do more thorough troubleshooting (and maybe to do some translation of unicode characters instead of simply stripping them).

Related

Find and Replace text with tabs and line breaks in VBA

I am trying to replace part of the code in my Python script using VBA.
I need to replace two lines of code with nothing. The VBA is not able to "find" these two lines in the code, which I think is because of the spaces, tabs in the Python script.
strContents = Replace(strContents, "if time == 12:" & vbNewLine & vbTab & "Freq = 1", "")
' *** THIS IS THE MOST CRUCIAL LINE - WHICH IS FAILING RIGHT NOW***
I am not adding the rest of the code of finding and replacing as it works, and the issue is finding this particular expression.
The Python script I am trying to delete (or replace with nothing):
if time == 12:
Freq = 1
else:
Freq = 12
In another attempt, I tried counting the number of spaces, and asking the VBA to find the text in the Python script with the number of spaces I could count in the script.
Thanks #Aldert for responding, here is the entire code :
Sub FindReplaceTrials()
Dim objFSO
Const ForReading = 1
Const ForWriting = 2
Dim objTS 'define a TextStream object
Dim strContents As String
Dim path As String
Dim fileSpec As String
Dim filename As String
path = Application.ActiveWorkbook.path
For m = 4 To 11 ' we need to make this dynamic too
filename = Worksheets("ScriptName").Cells(m, 1).Value
fileSpec = path & "\" & filename & ".py"
'MsgBox (vbCrLf & vbTab & "else:")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTS = objFSO.OpenTextFile(fileSpec, ForReading)
If Worksheets(4).Range("B" & 7).Value = 1 Then
If filename = "econ" Then
strContents = objTS.ReadAll
strContents = Replace(strContents, "if time == 12:" & vbCrLf & Space(20) & "freq = 1" & vbCrLf & Space(16) & "else:" & vbCrLf & Space(20) & "freq = 12", "freq = 12")
Set objTS = objFSO.OpenTextFile(fileSpec, ForWriting)
objTS.Write strContents
objTS.Close
End If
End If
objTS.Close
Next
End Sub
The vbCrLf & Space() objects worked to find the right sentences in the script.

Import EDI file into Access line by line

I need to import into Access table this EDI text file ( ' as line terminator):
UNA:+.?'
UNB+UNOC:3+BRANDEUROPE+ANYCODE+180206:1121+5439'
UNH+5439-1+DESADV:D:99B:UN'
BGM+351+0089430043+9'
DTM+11:20180205:102'
DTM+137:20180205:102'
MEA+WT+AAD+KGM:2126.100'
MEA+CT+SQ+NMP:00000'
NAD+DP+0017309707++NameStreet 22+Rome++00100+IT'
CTA+DL'
NAD+SU+DE++BRAND Systems+Rome+Rome++00100+IT'
CTA+DL'
TOD+6++CIP'
CPS+1'
PAC+2++BX'
MEA+WT+G+KGM:88'
PCI+24'
GIN+ML+AL7B009435+AL7B009438'
LIN+1++46550705:VP'
PIA+1+4114793:BP'
IMD+A++:::C833dn-EURO'
QTY+12:2'
RFF+OP:44CKV07S:000001'
CPS+2'
PAC+1++BX'
MEA+WT+G+KGM:0.01'
PCI+24'
LIN+1++01182907:VP'
PIA+1+4113617:BP'
IMD+A++:::RAM-256MB-C3/C5/C6/C7/MC3/MC5/C8'
QTY+12:1'
RFF+OP:44CKV07S:000003'
CPS+3'
PAC+4++BX'
MEA+WT+G+KGM:43.2'
PCI+24'
LIN+1++46361802:VP'
PIA+1+4114805:BP'
IMD+A++:::Tray-C5x2/MC5x3'
QTY+12:4'
RFF+OP:44CKV07S:000006'
This is the result I need:
0089430043 05/02/2018 46550705 AL7B009435
0089430043 05/02/2018 46550705 AL7B009438
etc...
and this is what I tried:
Public Function import1()
Dim strFilename As String: strFilename = "C:\despatch.txt"
Dim strTextLine, CodProd, DataDoc As String
Dim SNarray() As String
Dim NumDoc As Long
Dim nPAC, NumRig, intCount As Integer
Dim iFile As Integer: iFile = FreeFile
Open strFilename For Input As #iFile
Do Until EOF(1)
Line Input #1, strTextLine
strTextLine = Replace(strTextLine, "'", "")
'BGM
If Left(strTextLine, 3) = "BGM" Then
NumDoc = Mid(strTextLine, 9, 10)
End If
'DTM
If Left(strTextLine, 6) = "DTM+11" Then
DataDoc = Mid(strTextLine, 14, 2) & "/" & Mid(strTextLine, 12, 2) & "/" & Mid(strTextLine, 8, 4)
End If
'CPS = numero record
If Left(strTextLine, 3) = "CPS" Then
NumRig = Val(Mid(strTextLine, 5, 3))
End If
'PAC = numero di matricole da estrarre
If Left(strTextLine, 3) = "PAC" Then
nPAC = Val(Mid(strTextLine, 5, 3))
End If
'GIN
If Left(strTextLine, 3) = "GIN" Then
'strTextLine.MoveNext
End If
'LIN
If Left(strTextLine, 3) = "LIN" Then
CodProd = Mid(strTextLine, 8, 8)
End If
'strTextLine.MovePrevious
SNarray = Split(Mid(strTextLine, 8), "+")
For intCount = LBound(SNarray) To UBound(SNarray)
Debug.Print NumDoc & " " & DataDoc & " " & NumRig & " " & CodProd & " " & SNarray(intCount)
Next
'strTextLine.MovePrevious
'strTextLine.MovePrevious
Loop
Close #iFile
End Function
Before to import GIN record with serial numbers, I need to achieve the LIN record with che product code, and then pass them to variables.
I've tried with .MoveNext and then with two .MovePrevious but it gives me error: object needed.
Any help would be appreciated.
Thanks.
This is an example of a function that parses an EDIFACT segment, it's not debugged but it shows the algorithm to read the EDI data. It can be easily adapted to read ANSI X12.
Function GetLine() as String()
Dim Elements as String(99,3)
Do Until EOF(1)
mychar = Input(1, #1) ' Get one character
If mychar = vbCr Or \
mychar = vbLf Then ' Skip Line Breaks
Continue
Else If mychar = "?" Then ' Process Escape
If EOF(1) Then Exit Do ' Reached end of file
mychar = Input(1, #1)
data = data & mychar ' Treat next char as regular
Else If mychar = "'" Then ' End of Segment
Exit Do
Else If mychar = "+" Then ' Element separator
Elements(Elem,Comp) = data
data = ""
Comp = 1
Elem = Elem + 1
Else If mychar = ":" Then ' Composite separator
Elements(Elem,Comp) = data
data = ""
Comp = Comp + 1
Else ' Regular data
data = data & mychar
End If
Loop
Elements(Elem,Comp) = data
GetLine = Elements
End Function
Example use
'BGM
If Elements(0,0) = "BGM" Then
NumDoc = Elements(2,1)
End If
Finally I solved (I really don't know how I did), here my code:
Function GetLine() As String()
Dim FSO As Object, objFile, objFolderIN, objFolderOUT As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
Set objFolderIN = FSO.GetFolder("C:\IN")
Set objFolderOUT = FSO.GetFolder("C:\Archivio")
Dim data, elem, comp
Dim i As Integer
Dim iFile As Integer: iFile = FreeFile
Dim Elements(99, 3) As String
Dim mychar As String
Dim NumDoc As Long
i = 1
For Each objFile In objFolderIN.Files
Open objFile For Input As #iFile
Do Until EOF(1)
Line Input #1, data
'Debug.Print data
mychar = Input(1, #1) ' Get one character.
If mychar = "'" Then Exit Do ' End of Segment
If mychar = vbCr Or _
mychar = vbLf Then
'Continue
ElseIf mychar = "?" Then
mychar = Input(1, #1) ' Skip Line Breaks and Escape
data = data & mychar
ElseIf mychar = "'" Then
Exit Do
ElseIf mychar = "+" Then ' Element separator
Elements(elem, comp) = data
data = ""
comp = 1
elem = elem + 1
ElseIf mychar = ":" Then ' Composite separator
Elements(elem, comp) = data
data = ""
comp = comp + 1
Else ' Regular data
data = data & mychar
End If
Loop
Elements(elem, comp) = data
GetLine = Elements
Close #iFile
i = i + 1
Next objFile
'BGM
If Elements(0, 0) = "BGM" Then
NumDoc = Elements(2, 1)
Debug.Print NumDoc
End If
End Function

Passing values from Excel to Word with VBA

For Each cell In rng
workSheetName = Format(SaturdayIsComing(), "mm-dd-yyyy") & " " & cell.Value
If WorksheetExists(workSheetName) Then
Dim localRange, localCell As Range
Set localRange = Worksheets(workSheetName).Range("D8:D19")
Dim contents As Variant
contents = ""
Dim firstLine As Boolean
firstLine = True
For Each localCell In localRange
If Len(localCell.Value) > 0 Then
If firstLine Then
contents = contents & localCell.Value & Chr(11)
Else
contents = contents & Chr(9) & Chr(9) & Chr(9) & localCell.Value & Chr(11)
End If
Else
contents = fixString(contents)
End If
If Len(contents) > 0 Then
firstLine = False
End If
Next localCell
For Each cc In wDoc.SelectContentControlsByTag(cell.Value & "Notes")
If Len(contents) > 0 Then
cc.Range.Text = fixString(contents)
Else
cc.Range.Text = "No Issues Found"
End If
Next
Else
errorCodesString = errorCodesString & cell.Value & ":"
End If
Next cell
Output to Word
Forgot to terminate the meeting
This is a test message\'s
If my cell contains a ' then I get an error saying
One of the values passwed to this method or property is incorrect
I know a ' is a comment in VBA. How do I go around this while preserving the notes that someone had added to the Excel cell?
You need to write a piece of code to search for quotes, either the single (') or double (") variety and either add a backslash before them OR double the character so '' in place of ' and "" in place of " and run this on contents before assigning it to cc.Range.Text.
This routine can also check for other instances of incorrect strings and fix them.
Something like this would do:
Function fixString(ByVal strIn As Variant) As String
Dim i As Integer
Const strIllegals = "\'"""
For i = 1 To Len(strIllegals)
strIn = Replace(strIn, Mid$(strIllegals, i, 1), "\" & Mid$(strIllegals, i, 1))
Next i
fixString = strIn
End Function
Try changing cell.Value to Replace(cell.Value, "'", "")
Or is it contents that has the apostrophe in it? A bit confusing.
Try changing contents to Replace(contents , "'", "")

Condition for Empty String in VBA

how do I check if the string variable is empty in vba?
if:
Dim StrFile1 As String, StrFile2 As String
Dim Text3 As String
Dim Len1 as Integer, Len2 As Integer
With NewMail
Text3 = Cells(i, 3).Value
StrPath = Cells(i, 2).Value & Text3
Text = Cells(i, 1).Value
.Subject =
' adds the data in column3 with space as subject
.From =
.To = Text
.BCC = ""
.TextBody =
StrFile1 = Dir(StrPath & "*.txt")
Len1 = Len(StrFile1)
Do While Len(StrFile1) > 0
.AddAttachment StrPath & StrFile1
StrFile1 = Dir
Loop
StrFile2 = Dir(StrPath & "*.pdf")
Len2 = Len(StrFile2)
Do While Len(StrFile2) > 0
.AddAttachment StrPath & StrFile2
StrFile2 = Dir
Loop
If (Len1 & Len2) = 0 Then
GoTo Last
'.AddAttachment Text3
.Send
End With
i = i + 1
Loop
Last:
End With
i = i + 1
Loop
Now i want to check simultaneously if Len1 and Len2 are 0, if so then I want to go to Last.
When I use this code I get a message/Compile error "Want to end with without with"
and
i am not sure if
If (Len1 & Len2) = 0 Then
GoTo Last
this is a proper code.
and Do i need to declare the label Last??
You have many way to do that like below :
Dim StrFiles As String
StrFiles = Trim(StrFile1 & StrFile2)
If IsEmpty(StrFiles) Then
If StrFiles = vbNullString Then
If StrFiles = "" Then
If StrFiles = Empty Then
If Len(StrFiles) = 0 Then
you can use + operator to check 2 strings are empty reference to your code, because Len Function returns an integer containing either the number of characters in a string
If (Len1 + Len2) = 0 Then
You can use Trim(strFile1 & vbNullString) = vbNullString to check if the string is empty.
So:
If Trim(strFile1 & vbNullString) = vbNullString Then
Debug.print "Empty String!"
End If
Thanks to #LordPeter
is.empty doesn't exist for VBA, but the second option works.
Alternatively, you can write:
(strFile1 & strFile2) = vbNullString
or
(strFile1 & strFile2) = ""
Yet another way is:
If Len(strFile1 & strFile2) > 0 Then
I did test to ensure that strings which aren't set return a length of 0, which appeared to be the case.

Error 91 occurring during iterations randomly

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