Related
I made a code to send some emails, using HCL NOTES and Excel, but I have been stuck.
ERROR 3000 appears when going through the line ".SEND 0, vaRecipient". I think what happens is that the connection with the database is lost, after going through the procedure of attaching an image to the body of the mail. Since if I remove those lines of code, no error arises.
Sub SendQuoteToEmail()
Dim NSession As Object
Dim NDatabase As Object
Dim NUIWorkSpace As Object
Dim NDoc As Object
Dim NUIdoc As Object
Dim NRichTextItem As Object
Dim NrichTextHeader As Object
Dim NMimeImage As Object
Dim strImageType As String
Dim WordApp As Object
Dim EmbedObj As Object
Dim Body As Object
Dim NStream As Object
Dim Subject As String
Dim MailAddress As String
Dim MailAddressCC As String
Dim MailAddressCC2 As String
Dim MailAddressCCO As String
Dim MailAddressCCO2 As String
Dim AttchFiles1, AttchFiles2, AttchFiles3, AttchFiles4 As String
Dim AddImage As String
Dim pf As Integer
Dim Uf As Integer
Dim x As Double
'On Error Resume Next
Set a = ThisWorkbook.Sheets("Base Emails")
pf = 4
Uf = 0
Do While Uf = 0
cuit = Range("a" & pf).Value
If cuit <> Empty Then
Subject = UserForm1.SubjectBox & a.Cells(pf, "D") & " - CUIL N°: " & a.Cells(pf, "A") '
MailAddress = a.Cells(pf, "F")
MailAddressCC = UserForm1.TextBoxCC
MailAddressCC2 = UserForm1.TextBoxCC2
MailAddressCCO = UserForm1.TextBoxCCO
MailAddressCCO2 = UserForm1.TextBoxCCO2
Set NSession = CreateObject("Notes.NotesSession")
Set NUIWorkSpace = CreateObject("Notes.NotesUIWorkspace")
Set NDatabase = NSession.GETDATABASE("", "")
If Not NDatabase.IsOpen Then NDatabase.OPENMAIL
Set NDoc = NDatabase.CREATEDOCUMENT
With NDoc
.SendTo = MailAddress
.CopyTo = MailAddressCC & ", " & MailAddressCC2
.Subject = Subject
.Body = UserForm1.FirstLineBox & vbLf & vbLf & _
UserForm1.FirstParagraphBox & vbLf & vbLf & _
UserForm1.SecondParagraphBox & vbLf & vbLf & _
UserForm1.ThirdParagraphBox & vbLf
.SAVEMESSAGEONSEND = True
End With
AddImage = ThisWorkbook.Path & "\Image\" & Worksheets("Files").Range("A" & 5)
If AddImage <> "" Then
Set NStream = NSession.CREATESTREAM
Call NStream.Open(AddImage)
Set Body = NDoc.CreateMIMEEntity("memo")
Set richTextHeader = Body.CreateHeader("Content-Type")
Call richTextHeader.SetHeaderVal("multipart/mixed")
Set mimeImage = Body.CreateChildEntity()
strImageType = "image/jpeg; image/gif" '" Other formats are "image/gif" "image/bmp" -
Call mimeImage.SetContentFromBytes(NStream, strImageType, ENC_IDENTITY_BINARY)
Call NStream.Close
End If
AttchFiles1 = ThisWorkbook.Path & "\Files\" & Worksheets("Files").Range("A" & 1)
If AttchFiles1 <> "" Then
Set AttachMe = NDoc.CREATERICHTEXTITEM("Attachment1")
Set EmbedObj = AttachMe.EmbedObject(1454, "", AttchFiles1, "Adjunto")
End If
AttchFiles2 = ThisWorkbook.Path & "\Files\" & Worksheets("Files").Range("A" & 2)
If AttchFiles2 <> "" Then
Set AttachMe = NDoc.CREATERICHTEXTITEM("Attachment2")
Set EmbedObj = AttachMe.EmbedObject(1454, "", AttchFiles2, "Adjunto")
End If
AttchFiles3 = ThisWorkbook.Path & "\Files\" & Worksheets("Files").Range("A" & 3)
If AttchFiles3 <> "" Then
Set AttachMe = NDoc.CREATERICHTEXTITEM("Attachment3")
Set EmbedObj = AttachMe.EmbedObject(1454, "", AttchFiles3, "Adjunto")
End If
AttchFiles4 = ThisWorkbook.Path & "\Files\" & Worksheets("Files").Range("A" & 4)
If AttchFiles4 <> "" Then
Set AttachMe = NDoc.CREATERICHTEXTITEM("Attachment4")
Set EmbedObj = AttachMe.EmbedObject(1454, "", AttchFiles4, "Adjunto")
End If
With NDoc
.PostedDate = Now()
.SEND 0, vaRecipient '<--- ERROR 3000
End With
Set NStream = Nothing
Set NDoc = Nothing
Set WordApp = Nothing
Set NSession = Nothing
Set EmbedObj = Nothing
pf = pf + 1
Else
Uf = 1
Exit Do
End If
Loop
VbMessage = "Sent messages"
Call Clean
End Sub
If I remove these lines of code, the procedure works. So I suppose that by manipulating "NSession", something happens, but I don't know what.
AddImage = ThisWorkbook.Path & "\Image\" & Worksheets("Files").Range("A" & 5)
If AddImage <> "" Then
Set NStream = NSession.CREATESTREAM
Call NStream.Open(AddImage)
Set Body = NDoc.CreateMIMEEntity("memo")
Set richTextHeader = Body.CreateHeader("Content-Type")
Call richTextHeader.SetHeaderVal("multipart/mixed")
Set mimeImage = Body.CreateChildEntity()
strImageType = "image/jpeg; image/gif" '" Other formats are "image/gif" "image/bmp" -
Call mimeImage.SetContentFromBytes(NStream, strImageType, ENC_IDENTITY_BINARY)
Call NStream.Close
End If
You've got two pieces of incompatible code here.
.Body = UserForm1.FirstLineBox & vbLf & vbLf & _
UserForm1.FirstParagraphBox & vbLf & vbLf & _
UserForm1.SecondParagraphBox & vbLf & vbLf & _
UserForm1.ThirdParagraphBox & vbLf
And
Set Body = NDoc.CreateMIMEEntity("memo")
Set richTextHeader = Body.CreateHeader("Content-Type")
Call richTextHeader.SetHeaderVal("multipart/mixed")
Set mimeImage = Body.CreateChildEntity()
strImageType = "image/jpeg; image/gif" '" Other formats are "image/gif" "image/bmp" -
Call mimeImage.SetContentFromBytes(NStream, strImageType, ENC_IDENTITY_BINARY)
You can't work with the message body both as Notes rich text (the first piece of code) and as MIME. You need to pick one or the other. I'm guessing you're going to pick MIME, in which case you are going to need to create a text/plain part and populate it with your three paragraphs of text.
I am trying to add a document to an email as a PDF. I am trying to change the file name to include the date which is stored in a table in the Word document.
I can create the email but the script gives me an error when it tries to export.
How can I attach the file as a PDF with a file name with the date pulled from the table in Word?
Sub CommandButton1_Click()
Dim OL As Object
Dim EmailItem As Object
Dim Doc As Document
Dim DateField As String
Dim desktoploc As String
Dim mypath As String
Application.ScreenUpdating = False
Set OL = CreateObject("Outlook.Application")
Set EmailItem = OL.CreateItem(olMailItem)
Set Doc = ActiveDocument
Doc.Save
'Pull date from table and change format
DateField = Format(Doc.Content.Tables(1).Cell(1, 4).Range.Text, "yyyymmdd")
'Pull line number and subject names from table 1 and table 2 in word to add to subject.
Dim linenum As Word.Range, subject1 As Word.Range, subjec2 As Word.Range
'Need to remove hidden line breaks from tables in word in order to fit on subject line of email
Set linenum = Doc.Content.Tables(1).Cell(1, 2).Range
linenum.MoveEnd unit:=wdCharacter, Count:=-1
Set subject1 = Doc.Content.Tables(2).Cell(2, 1).Range
subject1.MoveEnd unit:=wdCharacter, Count:=-1
Set subjec2 = Doc.Content.Tables(2).Cell(3, 1).Range
subjec2.MoveEnd unit:=wdCharacter, Count:=-1
'Create PDF File
Dim file_name As String
Dim NewFileName As String
NewFileName = "Load Limits Subjects " & linenum & " " & DateField
file_name = ActiveDocument.Path & "\" & Left(ActiveDocument.Name, InStrRev(ActiveDocument.Name, ".") - 1) & NewFileName & ".pdf"
'This is where I keep getting the error.....
ActiveDocument.ExportAsFixedFormat OutputFileName:=file_name, _
ExportFormat:=wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
wdExportOptimizeForPrint, Range:=wdExportAllDocument, Item:= _
wdExportDocumentContent, IncludeDocProps:=False, KeepIRM:=True, _
CreateBookmarks:=wdExportCreateNoBookmarks, DocStructureTags:=True, _
BitmapMissingFonts:=True, UseISO19005_1:=False
With EmailItem
.Display
.Subject = "Limit Notification - Subject " & linenum & " #line #" & linenum & _
" #" & subject1.Text & " #" & subjec2.Text & vbCrLf
.Body = "Please see the attached Limit Notification for Subject " & linenum.Text & vbCrLf & _
"" & vbCrLf & _
"Let me know if you have any questions." & vbCrLf & _
"" & vbCrLf & _
"Thank you," & vbCrLf & vbCrLf & _
"INSERT SIGNATURE HERE"
'Update Recipient List here:
.To = "LineEmail#email.com; "
.CC = "Another Email#demail.com"
'.Importance = olImportanceNormal
.Attachments.Add Doc.FullName
End With
End Sub
Your code has multiple flaws, including:
Your DateField string is trying to convert something that includes a table cell's end-of-cell marker into an ISO-format date
Your code is not validating the NewFileName string as a filename.
Your code is trying to to attach the document to the email, not the pdf.
Your code is referencing ActiveDocument (which may no longer be the same as Doc) when creating path etc. for the new filename.
Try something along the lines of:
Sub CommandButton1_Click()
Application.ScreenUpdating = False
Dim OL As Object
Dim EmailItem As Object
Dim Doc As Document
Dim Rng As Range
Dim i As Long
Dim NewFileName As String
Dim MailSubject As String
Dim MailBody As String
Const StrNoChr As String = """*./\:?|"
NewFileName = " Load Limits Subjects "
MailSubject = "Limit Notification - Subject "
MailBody = "Please see the attached Limit Notification for Subject "
Set OL = CreateObject("Outlook.Application")
Set EmailItem = OL.CreateItem(olMailItem)
Set Doc = ActiveDocument
With Doc
.Save
Set Rng = .Tables(1).Cell(1, 2).Range
Rng.End = Rng.End - 1
NewFileName = NewFileName & Rng.Text & " "
MailSubject = MailSubject & Rng.Text & " #line #" & Rng.Text & " #"
MailBody = MailBody & Rng.Text
Set Rng = .Tables(1).Cell(1, 4).Range
Rng.End = Rng.End - 1
NewFileName = NewFileName & Format(Rng.Text, "YYYYMMDD")
Set Rng = .Tables(2).Cell(2, 1).Range
Rng.End = Rng.End - 1
MailSubject = MailSubject & Rng.Text
Set Rng = .Tables(2).Cell(3, 1).Range
Rng.End = Rng.End - 1
MailSubject = MailSubject & Rng.Text
For i = 1 To Len(StrNoChr)
NewFileName = Replace(NewFileName, Mid(StrNoChr, i, 1), "_")
Next
NewFileName = Split(.FullName, ".doc")(0) & NewFileName & ".pdf"
SaveAs2 FileName:=NewFileName, FileFormat:=wdFormatPDF, AddToRecentFiles:=False
End With
MailBody = MailBody & vbCrLf & _
"" & vbCrLf & _
"Let me know if you have any questions." & vbCrLf & _
"" & vbCrLf & _
"Thank you," & vbCrLf & vbCrLf & _
"INSERT SIGNATURE HERE"
With EmailItem
.Display
.Subject = MailSubject
.Body = MailBody
'Update Recipient List here:
.To = "LineEmail#email.com; "
.CC = "Another Email#demail.com"
'.Importance = olImportanceNormal
.Attachments.Add NewFileName
End With
End Sub
On Error Resume Next
Set FileSysObj = CreateObject("Scripting.FileSystemObject")
Const ForReading = 1 ' Declare constant for reading for more clarity
Dim cntFile, strCSVFullFile, strCSVFile, strDIR, cntBadLines, cntAllLines, strArchiveDir, strSafeTime,strSafeDate
' -------------------------------------------------------------------------------------------
' Specify CSV file name from the input argument
strCSVFile = Wscript.Arguments(1) ' Transactions
strDIR = Wscript.Arguments(2) & "\" ' C:\Temp
strArchiveDir = Wscript.Arguments(3) & "\"
strSafeTime = Right("0" & Hour(Now), 2) & Right("0" & Minute(Now), 2) & Right("0" & Second(Now), 2)
strSafeDate = Year(Date) & Month(Date) & day(Date)
set folder = FileSysObj.getFolder(strDIR)
cntFile = 0
cntBadLines = 0
cntAllLines = 0
for each file in folder.Files
' check if the file is there and echo it.
if InStr(1,file.name,strCSVFile,1) <> 0 then
strCSVFullFile = file.name
cntFile = cntFile + 1
end if
next
if cntFile > 1 or cntFile = 0 then
' error and end
Wscript.Echo "Error - only 1 file required for this process. There are " & cntFile & " file(s) in the directory"
WScript.Quit
end if
wscript.echo "Checking the file " & strCSVFullFile & " in " & strDIR
NoOfCols = Wscript.Arguments(0) ' usually 8
strTemp = "temp.csv"
strmissing = "missingdata.csv"
Set objOutFile = FileSysObj.CreateTextFile(strDIR & strTemp,True)
Set objOutFileM = FileSysObj.CreateTextFile(strDIR & strmissing,True)
Set inputFile = FileSysObj.OpenTextFile(strDIR & strCSVFullFile, ForReading, True)
' Set inputFile as file to be read from
Dim row, column, outline
Dim fields '(7) '8 fields per line
inputFile.ReadAll 'read to end of file
outline = ""
ReDim MyArray(inputFile.Line-2,NoOfCols) 'current line, minus one for header, and minus one for starting at zero
inputFile.close 'close file so that MyArray can be filled with data starting at the top
Set inputFile = FileSysObj.OpenTextFile(strDIR & strCSVFullFile, ForReading, True) 'back at top
strheadLine = inputFile.ReadLine 'skip header , but keep it for the output file
objOutFile.Write(strheadLine & vbCrLf)
anyBadlines = False
badlineflag = False
Do Until inputFile.AtEndOfStream
fullLine = inputFile.Readline
fields = Split(fullLine,",") 'store line in temp array
For column = 0 To NoOfCols-1 'iterate through the fields of the temp array
myArray(row,column) = fields(column) 'store each field in the 2D array with the given coordinates
'Wscript.Echo myArray(row,column)
if myArray(row,0) = " " or myArray(row,1) = " " then
badlineflag = True
'missline = myArray(row,0) & ", " & myArray(row,1) & ", " & myArray(row,2) & ", " & myArray(row,3) & ", " & myArray(row,4) & ", " & myArray(row,5) & ", " & myArray(row,6) & ", " & myArray(row,7)
'Wscript.Echo missline
'Exit For
end if
if column = NoOfCols-1 then
outline = outline & myArray(row,column) & vbCrLf
else
outline = outline & myArray(row,column) & ","
'csvFile = Regex.Replace(csvFile, "(,\s*?"".*?)(,)(\s+.*?""\s*?,)", "$1$3") 'TEST
end if
Next
cntAllLines = cntAllLines + 1
' Wscript.Echo outline
if badlineflag = False then
objOutFile.Write(fullLine & vbCrLf)
else
' write it somewhere else, drop a header in the first time
if anyBadlines = False Then
objOutFileM.Write(strheadLine & vbCrLf)
End if
objOutFileM.Write(outline)
cntBadLines = cntBadLines + 1
badlineflag = False
anyBadlines = True
end if
outline = ""
row = row + 1 'next line
Loop
objOutFile.Close
objOutFileM.Close
inputFile.close
Wscript.Echo "Total lines in the transaction file = " & cntAllLines
Wscript.Echo "Total bad lines in the file = " & cntBadLines
The below line is able to work as it contains 7 commas (8 columns).
URXW_99,BYQ0JC6,2603834418,2017-10-30,Test,4.962644,2278.0000,ABC
The below line will throw an error as a result of more commas than 7 in the script.
URXW_99,BYQ0JC6,2603834418,2017-10-30,Test,4.962644,2278.0000,Redburn, Europe. Limited
If greater than 7 commas in the CSV file line, the aim is to wrap it all greater than 7 into one field.
E.g. how do you replace Redburn, Europe. Limited string with double quotes as it is one name.
For example, in a text file it would appear like below:
URXW_99,BYQ0JC6,2603834418,2017-10-30,Test,4.962644,2278.0000,"Redburn, Europe. Limited"
Is there a way to write a VB or VBA script to do the above and save it as a .csv file (which is opened via notepad to check the double quotes)?
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 = "U:\Book3.csv"
strDestinationFile = "U:\Book4.csv"
Open strSourceFile For Input As #1
Open strDestinationFile For Output As #2
lngRowNumber = 0
Do Until EOF(1)
Line Input #1, strLineFromFile
strLineFromFile = Right(Replace(strLineFromFile, ",", " ", 1), 1000)
Write #2, strLineFromFile
strLineFromFile = vbNullString
Loop
Close #1
Close #2
End Sub
As I see, you use MS Access (due to Option Compare Text line), so there is better built-in instruments for this task.
Use DoCmd.TransferText for it.
1st step is to create output specification via:
Here you can setup delimiters, even that differs from ", and handle other options.
After that you can use your set-up specification via following command
DoCmd.TransferText acExportDelim, "TblCustomers_export_spec", "TblCustomers", "C:\test\1.txt", True
In this case all characters escaping would be done through built-in instruments. It seems to be more easier to correct this code further.
As mentioned, there is VBScript workaround. For given input data, following function will do desired actions for given string:
Option Explicit
Function funAddLastQuotes( _
strInput _
)
Dim arrInput
arrInput = Split(strInput, ",")
Dim intArrSize
intArrSize = UBound(arrInput)
Dim intCurrentElement
Dim strOutput
Dim intPreLastElement
intPreLastElement = 6
For intCurrentElement = 1 To intPreLastElement
strOutput = strOutput & "," & arrInput(intCurrentElement)
Next
Dim strOutputLastField
For intCurrentElement = intPreLastElement + 1 To intArrSize
strOutputLastField = strOutputLastField & "," & arrInput(intCurrentElement)
Next
strOutputLastField = Right(strOutputLastField, Len(strOutputLastField) - 1)
strOutput = Right(strOutput, Len(strOutput) - 1)
strOutput = strOutput & "," & """" & strOutputLastField & """"
funAddLastQuotes = strOutput
End Function
MsgBox funAddLastQuotes("RXW_99,BYQ0JC6,2603834418,2017-10-30,Test,4.962644,2278.0000,Redburn, Europe,,, Limited")
Finally, here is working VBScript solution.
Option Explicit
Const ColumnsBeforeCommadColumn = 6
Function funAddLastQuotes( _
strInput _
)
Dim arrInput
arrInput = Split(strInput, ",")
Dim intArrSize
intArrSize = UBound(arrInput)
Dim intCurrentElement
Dim strOutput
Dim intPreLastElement
intPreLastElement = ColumnsBeforeCommadColumn
For intCurrentElement = 1 To intPreLastElement
strOutput = strOutput & "," & arrInput(intCurrentElement)
Next
Dim strOutputLastField
If (intPreLastElement + 1) < intArrSize _
Then
For intCurrentElement = intPreLastElement + 1 To intArrSize
strOutputLastField = strOutputLastField & "," & arrInput(intCurrentElement)
Next
Else
strOutputLastField = strOutputLastField & "," & arrInput(intArrSize)
End If
strOutputLastField = Right(strOutputLastField, Len(strOutputLastField) - 1)
strOutput = Right(strOutput, Len(strOutput) - 1)
strOutput = strOutput & "," & """" & strOutputLastField & """"
funAddLastQuotes = strOutput
End Function
Public Sub ConvertFile( _
strSourceFile _
)
Dim objFS
Dim strFile
Dim strTemp
Dim ts
Dim objOutFile
Dim objFile
Set objFS = CreateObject("Scripting.FileSystemObject")
Dim strLine
Dim strOutput
Dim strRow
strFile = strSourceFile
strTemp = strSourceFile & ".tmp"
Set objFile = objFS.GetFile(strFile)
Set objOutFile = objFS.CreateTextFile(strTemp,True)
Set ts = objFile.OpenAsTextStream(1,-2)
Do Until ts.AtEndOfStream
strLine = ts.ReadLine
objOutFile.WriteLine funAddLastQuotes(strLine)
Loop
objOutFile.Close
ts.Close
objFS.DeleteFile(strFile)
objFS.MoveFile strTemp,strFile
End Sub
ConvertFile "C:\!accsoft\_in.csv"
You should change following part: ConvertFile "C:\!accsoft\_in.csv as path to your file.
And ColumnsBeforeCommadColumn = 6 is the setting, at which column the chaos with commas begins
I want to be able to tell IF a form is the active window.
It seems simply invoking that method produces an error. I guess I could catch that error and run with it, but it's a backwards way of doing it.
Screen.ActiveForm.Name
This needs a form to be active. If I am breaking any rules of stackOverflow please be kind and remind me as I am new to forum.
Screen.parent, screen.activeControl, etc. What if VBA editor is open, as often it is?
Function CStatus(strStatus, ByRef intType As Integer, Optional ByRef erNo, Optional erMsg, Optional strDatum)
'pXname = "CStatus"
'pXStack = Left(pXStack, 500) & ">" & pXname
'Updates and manages the status bar
Dim strPreamble As String, strOut As String, strForm As String, strComment As String, strSQL As String, strPxStack As String, strCErrStack As String
Dim intColor As Double
Dim intPreLen As Integer
'On Error GoTo err_hand
'Color Codes
'12632256 = Lt Grey
'33023 = Orange
'65280 = Green
'16744576 = Steel Grey
'Define "Constants"
intPreLen = 350 'Length of previous message cache
'** Fix missings
If (IsMissing(strDatum) = True) Then strDatum = "[N/A]"
'** Other inits
strWindow = Screen.Parent.Name
strForm = Screen.ActiveForm.Name
'** intDebug ' Minimum Level of to report to status
'bEcho = True 'Whether to echo to status
intColor = errNoColor(intType)
'Error-level idiot explanations
strComment = "0"
If IsMissing(erNo) Then erNo = 0
If (IsNull(erMsg) = False) Then
If IsMissing(erMsg) = False Then strComment = erMsg
End If
strComment = errorTree(erNo)
strPreamble = Left(strPreamble, intPreLen) & "..."
strErrStack = Left(strErrStack, intPreLen) & " > " & pXname & ":" & intType
strCErrStack = strErrStack
reS:
If ((strForm = "finvmain") Or (strForm = "fclips")) Then Screen.ActiveForm.timeStatusUpdated = Now() 'Small field keeps time
If bEcho = True Then
strPxStack = ""
strCErrStack = "" 'Internal error stack
End If
strOut = Now() & " " & intType & " (" & strType & "): " & erNo & " " & strCErrStack & " >> " & strComment & " / " & strStatus & " [" & strDatum & "] .. " & strPreamble
If bEcho = True Then
If (strForm = "fInvMain") Then Screen.ActiveForm.txtStatus2 = Screen.ActiveForm.txtStatus 'Added second window to show previous message
Screen.ActiveForm.txtStatus = strOut
End If
Screen.ActiveForm.txtStatus.ForeColor = intColor
If strForm = "fInvMain" Then strTag = Screen.ActiveForm.Controls("txttag").value
'***Event Log
If erNo = "" Then erNo = 0
If IsMissing(erMsg) = True Then erMsg = ""
If IsMissing(strDatum) = True Then strDatum = ""
If Len(strPreamble) < 2 Then strPreamble = "[None]"
'Fixxed - Syntax Error for Some Odd Reason! Apr 27th
If ((strTag = Empty) And (strForm = "fInvMain")) Then strTag = Screen.ActiveForm.txtTag 'Attempt to add tag# to entry
strStatus = cleanString(strStatus)
strDatum = cleanString(strDatum)
strComment = cleanString(strComment)
strSQL = "INSERT INTO tEvents(txtdate, myerrno, interrno, myerrmsg, interrmsg, txtform, stack, process, Datum, idLink) VALUES ('" & Now() & "','" & intType & "','" & erNo & "','" & strStatus & "','" & strComment & "','" & strForm & "','" & strErrStack & "','" & pXname & "','" & strDatum & "','" & strTag & "');"
CurrentDb.Execute strSQL, dbFailOnError
Exit Function
err_hand:
If Err.Number = 2475 Then
bEcho = False
Resume reS
Else: MsgBox "555: CStatus Internal Error, Turn off error handling to view"
End If
End Function
I need a boolean true or false IF form is active. If it isn't, I can't put stuff into a textbox in that.
To determine if a particular form is open then set focus to form:
If CurrentProject.AllForms("finvmain").IsLoaded
strForm = "finvmain"
Elseif CurrentProject.AllForms("fclips").IsLoaded Then
strForm = "fclips"
End If
If strForm <> "" Then DoCmd.SelectObject acForm, strForm
I am looking for a way to convert a textfile with UTF8 encoding to ANSI encoding.
How can i go around and achieve this in Visual Basic (VB6) and or vbscript?
If your files aren't truly enormous (e.g. even merely 40MB can be painfully slow) you can do this using the following code in VB6, VBA, or VBScript:
Option Explicit
Private Const adReadAll = -1
Private Const adSaveCreateOverWrite = 2
Private Const adTypeBinary = 1
Private Const adTypeText = 2
Private Const adWriteChar = 0
Private Sub UTF8toANSI(ByVal UTF8FName, ByVal ANSIFName)
Dim strText
With CreateObject("ADODB.Stream")
.Open
.Type = adTypeBinary
.LoadFromFile UTF8FName
.Type = adTypeText
.Charset = "utf-8"
strText = .ReadText(adReadAll)
.Position = 0
.SetEOS
.Charset = "_autodetect" 'Use current ANSI codepage.
.WriteText strText, adWriteChar
.SaveToFile ANSIFName, adSaveCreateOverWrite
.Close
End With
End Sub
UTF8toANSI "UTF8-wBOM.txt", "ANSI1.txt"
UTF8toANSI "UTF8-noBOM.txt", "ANSI2.txt"
MsgBox "Complete!", vbOKOnly, WScript.ScriptName
Note that it will handle UTF-8 input files either with or without a BOM.
Using strong typing and early binding will improve performance a hair in VB6, and you won't need to declare those Const values. This isn't an option in script though.
For VB6 programs that need to process very large files you might be better off using VB6 native I/O against Byte arrays and use an API call to convert the data in chunks. This adds the extra messiness of finding the character boundaries though (UTF-8 uses a variable number of bytes per character). You'd need to scan each data block you read to find a safe ending point for an API translation.
I'd look at MultiByteToWideChar() and WideCharToMultiByte() to get started.
Note that UTF-8 often "arrives" with LF line delimiters instead of CRLF.
I'm using these helper functions
Private Function pvReadFile(sFile)
Const ForReading = 1
Dim sPrefix
With CreateObject("Scripting.FileSystemObject")
sPrefix = .OpenTextFile(sFile, ForReading, False, False).Read(3)
End With
If Left(sPrefix, 3) <> Chr(&HEF) & Chr(&HBB) & Chr(&HBF) Then
With CreateObject("Scripting.FileSystemObject")
pvReadFile = .OpenTextFile(sFile, ForReading, False, Left(sPrefix, 2) = Chr(&HFF) & Chr(&HFE)).ReadAll()
End With
Else
With CreateObject("ADODB.Stream")
.Open
If Left(sPrefix, 2) = Chr(&HFF) & Chr(&HFE) Then
.Charset = "Unicode"
ElseIf Left(sPrefix, 3) = Chr(&HEF) & Chr(&HBB) & Chr(&HBF) Then
.Charset = "UTF-8"
Else
.Charset = "_autodetect"
End If
.LoadFromFile sFile
pvReadFile = .ReadText
End With
End If
End Function
Private Function pvWriteFile(sFile, sText, lType)
Const adSaveCreateOverWrite = 2
With CreateObject("ADODB.Stream")
.Open
If lType = 2 Then
.Charset = "Unicode"
ElseIf lType = 3 Then
.Charset = "UTF-8"
Else
.Charset = "_autodetect"
End If
.WriteText sText
.SaveToFile sFile, adSaveCreateOverWrite
End With
End Function
I found out that "native" FileSystemObject reading of ANSI and UTF-16/UCS-2 files is much faster that ADODB.Stream hack.
I'm using this script to convert any character set or code page (that i'm aware of).
This script can also handle large files (over one gigabytes), because it streams one line at a time.
' - ConvertCharset.vbs -
'
' Inspired by:
' http://www.vbforums.com/showthread.php?533879-Generate-text-files-in-IBM-850-encoding
' http://stackoverflow.com/questions/5182102/vb6-vbscript-change-file-encoding-to-ansii/5186170#5186170
' http://stackoverflow.com/questions/13130214/how-to-convert-a-batch-file-stored-in-utf-8-to-something-that-works-via-another
'
' Start Main
Dim objArguments
Dim strSyntaxtext, strInputCharset, strOutputCharset, strInputFile, strOutputFile
Dim intReadPosition, intWritePosition
Dim arrCharsets
Const adReadAll = -1
Const adReadLine = -2
Const adSaveCreateOverWrite = 2
Const adSaveCreateNotExist = 1
Const adTypeBinary = 1
Const adTypeText = 2
Const adWriteChar = 0
Const adWriteLine = 1
strSyntaxtext = strSyntaxtext & "Converts the charset of the input text file to output file." & vbCrLf
strSyntaxtext = strSyntaxtext & "Syntax: " & vbCrLf
strSyntaxtext = strSyntaxtext & WScript.ScriptName & " /InputCharset:utf-8|windows-1252|ibm850|..." & vbCrLf
strSyntaxtext = strSyntaxtext & " /OutputCharset:utf-8|windows-1252|ibm850|..." & vbCrLf
strSyntaxtext = strSyntaxtext & " /InputFile:\\path\to\inputfile.ext" & vbCrLf
strSyntaxtext = strSyntaxtext & " /OutputFile:\\path\to\outputfile.ext" & vbCrLf
strSyntaxtext = strSyntaxtext & " [/ShowAllCharSets]" & vbCrLf & vbCrLf
strSyntaxtext = strSyntaxtext & "Example:" & vbCrLf
strSyntaxtext = strSyntaxtext & WScript.ScriptName & " /InputCharset:ibm850 /OutputCharset:utf-8 /InputFile:my_dos.txt /OutputFile:my_utf-8.txt" & vbCrLf
Set objArgumentsNamed = WScript.Arguments.Named
If objArgumentsNamed.Count = 0 Then
WScript.Echo strSyntaxtext
WScript.Quit(99)
End If
arrCharsets = Split("big5,big5-hkscs,euc-jp,euc-kr,gb18030,gb2312,gbk,ibm-thai," &_
"ibm00858,ibm01140,ibm01141,ibm01142,ibm01143,ibm01144," &_
"ibm01145,ibm01146,ibm01147,ibm01148,ibm01149,ibm037," &_
"ibm1026,ibm273,ibm277,ibm278,ibm280,ibm284,ibm285,ibm297," &_
"ibm420,ibm424,ibm437,ibm500,ibm775,ibm850,ibm852,ibm855," &_
"ibm857,ibm860,ibm861,ibm862,ibm863,ibm864,ibm865,ibm866," &_
"ibm869,ibm870,ibm871,iso-2022-jp,iso-2022-kr,iso-8859-1," &_
"iso-8859-13,iso-8859-15,iso-8859-2,iso-8859-3,iso-8859-4," &_
"iso-8859-5,iso-8859-6,iso-8859-7,iso-8859-8,iso-8859-9," &_
"koi8-r,koi8-u,shift_jis,tis-620,us-ascii,utf-16,utf-16be," &_
"utf-16le,utf-7,utf-8,windows-1250,windows-1251,windows-1252," &_
"windows-1253,windows-1254,windows-1255,windows-1256," &_
"windows-1257,windows-1258,unicode", ",")
Set objFileSystem = CreateObject("Scripting.FileSystemObject")
For Each objArgumentNamed in objArgumentsNamed
Select Case Lcase(objArgumentNamed)
Case "inputcharset"
strInputCharset = LCase(objArgumentsNamed(objArgumentNamed))
If Not IsCharset(strInputCharset) Then
WScript.Echo "The InputCharset (" & strInputCharset & ") is not valid, quitting. The valid charsets are:" & vbCrLf
x = ShowCharsets()
WScript.Quit(1)
End If
Case "outputcharset"
strOutputCharset = LCase(objArgumentsNamed(objArgumentNamed))
If Not IsCharset(strOutputCharset) Then
WScript.Echo "The strOutputCharset (" & strOutputCharset & ") is not valid, quitting. The valid charsets are:" & vbCrLf
x = ShowCharsets()
WScript.Quit(2)
End If
Case "inputfile"
strInputFile = LCase(objArgumentsNamed(objArgumentNamed))
If Not objFileSystem.FileExists(strInputFile) Then
WScript.Echo "The InputFile (" & strInputFile & ") does not exist, quitting." & vbCrLf
WScript.Quit(3)
End If
Case "outputfile"
strOutputFile = LCase(objArgumentsNamed(objArgumentNamed))
If objFileSystem.FileExists(strOutputFile) Then
WScript.Echo "The OutputFile (" & strOutputFile & ") exists, quitting." & vbCrLf
WScript.Quit(4)
End If
Case "showallcharsets"
x = ShowCharsets()
Case Else
WScript.Echo "Unknown parameter, quitting: /" & objArgumentNamed & ":" & objArgumentsNamed(objArgumentNamed)
WScript.Echo strSyntaxtext
End Select
Next
If Len(strInputCharset) > 0 And Len(strOutputCharset) > 0 And Len(strInputFile) > 0 And Len(strOutputFile) Then
Set objInputStream = CreateObject("ADODB.Stream")
Set objOutputStream = CreateObject("ADODB.Stream")
With objInputStream
.Open
.Type = adTypeBinary
.LoadFromFile strInputFile
.Type = adTypeText
.Charset = strInputCharset
intWritePosition = 0
objOutputStream.Open
objOutputStream.Charset = strOutputCharset
Do While .EOS <> True
strText = .ReadText(adReadLine)
objOutputStream.WriteText strText, adWriteLine
Loop
.Close
End With
objOutputStream.SaveToFile strOutputFile , adSaveCreateNotExist
objOutputStream.Close
WScript.Echo "The " & objFileSystem.GetFileName(strInputFile) & " was converted to " & objFileSystem.GetFileName(strOutputFile) & " OK."
End If
' End Main
' Start Functions
Function IsCharset(strMyCharset)
IsCharset = False
For Each strCharset in arrCharsets
If strCharset = strMyCharset Then
IsCharset = True
Exit For
End If
Next
End Function
Function ShowCharsets()
strDisplayCharsets = ""
intCounter = 0
For Each strcharset in arrCharsets
intCounter = intCounter + Len(strcharset) + 1
strDisplayCharsets = strDisplayCharsets & strcharset & ","
If intCounter > 67 Then
intCounter = 0
strDisplayCharsets = strDisplayCharsets & vbCrLf
End If
Next
strDisplayCharsets = Mid(strDisplayCharsets, 1, Len(strDisplayCharsets)-1)
WScript.Echo strDisplayCharsets
End Function
' End Functions
#Bob77's answer did not work for me, so I converted #Ciove's answer to a simple sub routine and it works fine.
' Usage:
' EncodeFile strInFile, "UTF-8", strOutFile, "Windows-1254", 2
Sub EncodeFile(strInputFile, strInputCharset, strOutputFile, strOutputCharset, intOverwriteMode)
'5th parameter may take the following values:
'Const adSaveCreateOverWrite = 2
'Const adSaveCreateNotExist = 1
Const adReadLine = -2
Const adTypeBinary = 1
Const adTypeText = 2
Const adWriteLine = 1
Set objInputStream = CreateObject("ADODB.Stream")
Set objOutputStream = CreateObject("ADODB.Stream")
With objInputStream
.Open
.Type = adTypeBinary
.LoadFromFile strInputFile
.Type = adTypeText
.Charset = strInputCharset
objOutputStream.Open
objOutputStream.Charset = strOutputCharset
Do While .EOS <> True
strText = .ReadText(adReadLine)
objOutputStream.WriteText strText, adWriteLine
Loop
.Close
End With
objOutputStream.SaveToFile strOutputFile, intOverwriteMode
objOutputStream.Close
End Sub