I am working on a project and I am writing to a file from another file, but I want a .VBS file to say it like TTS. here is the code for that... But
Dim message, sapi
Set sapi=CreateObject("This Text")
sapi.Speak message
And then the words "This Text" will come out of the speakers.
But, I don't want the words "This Text" to come out, I want it to say the words inside a .txt file (tts_text.txt)
So it needs to read a text file and store that in a variable and then the tts should read and say the variable.
Use this to read/learn about the objects and their capabilities:
Option Explicit
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim goVC : Set goVC = CreateObject("SAPI.SpVoice")
goVC.Speak goFS.OpenTextFile(WScript.ScriptFullName).ReadAll()
You can give a try for this vbscript example :
Option Explicit
Dim Contents,File,message
File = "c:\tts_text.txt"
Contents = "It didn’t work after mass shootings at a nightclub in Orlando,"&_
"college campuses in Virginia and Oregon, a church in Charleston,"&_
"or at a movie theater and high school in Colorado."&_
"Or after two lawmakers survived assassination attempts." & vbcrlf &_
"But after a gunman killed 58 people and wounded more than 500 at a Las Vegas concert," & vbcrlf &_
"Democrats are going to try again to revamp the nation’s gun laws."
' We write this contents to the file
WriteTextFile Contents, file, 0
' We read the file contents and we store it into a variable message
message = ReadFileText(File)
' Now we can speak this message with SAPI object
Speak_from_File message
'**********************************************************
Sub Speak_from_File(message)
Dim Voice
Set Voice = CreateObject("SAPI.SpVoice")
Voice.Volume = 100
Voice.Rate = 0
Voice.Speak message
End Sub
'**********************************************************
Sub WriteTextFile(sContent, sPath, lFormat)
'lFormat -2 - System default, -1 - Unicode, 0 - ASCII
With CreateObject("Scripting.FileSystemObject").OpenTextFile(sPath,2,True,lFormat)
.WriteLine sContent
.Close
End With
End Sub
'**********************************************************
Function ReadFileText(sFile)
Dim objFSO,oTS,sText
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oTS = objFSO.OpenTextFile(sFile,1)
sText = oTS.ReadAll
oTS.close
set oTS = nothing
Set objFSO = nothing
ReadFileText = sText
End Function
'**********************************************************
Related
I have a PNG picture in my SQL Server, I'm successfully getting the image and saving it to file.
rs.Open "Select pic from Table", connObj, adOpenDynamic, adLockOptimistic
If rs.RecordCount > 0 Then
If Not IsNull(rs.Fields("pic").Value) Then
Set mstream = New ADODB.Stream
mstream.Type = adTypeBinary
mstream.Open
mstream.Write rs.Fields("pic").Value
mstream.SaveToFile App.Path & "\MyPhoto.jpg", adSaveCreateOverWrite
End If
End If
rs.Close
As you can see I already have my extension as .jpg but I don't think it matters, when I use the image in my vb6 application using LoadPicture() I get an Invalid Picture error. If I open the image and re-save it as jpg or bmp, LoadPicture() works.
So how can I save the picture properly as bmp/jpg?
You might find these two functions useful
Private Function LoadPictureFromBlob(baData() As Byte) As StdPicture
With CreateObject("WIA.Vector")
.BinaryData = baData
Set LoadPictureFromBlob = .Picture
End With
End Function
Private Sub SavePictureToJpg(oPic As StdPicture, sFile As String, Optional ByVal Quality = 80)
Const wiaFormatJPEG As String = "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}"
Dim oImg As Object
SavePicture oPic, sFile
Set oImg = CreateObject("WIA.ImageFile")
oImg.LoadFile sFile
With CreateObject("WIA.ImageProcess")
.Filters.Add .FilterInfos("Convert").FilterID
.Filters.Item(1).Properties("FormatID").Value = wiaFormatJPEG
.Filters.Item(1).Properties("Quality").Value = Quality
Set oImg = .Apply(oImg)
End With
On Error Resume Next
Kill sFile
On Error GoTo 0
oImg.SaveFile sFile
End Sub
Just use Set oPic = LoadPictureFromBlob(rs.Fields("pic").Value) to read the .png and then either use built-in SavePicture oPic, App.Path & "\MyPhoto.bmp" to save to .bmp or SavePictureToJpg oPic, App.Path & "\MyPhoto.jpg" for .jpg and decide on the optional quality parameter.
I have a folder C:\test\ that has multiple .txt files which I need to append to one output text file. Using FSO and TextStream I can write the files explicitly with no problem in this manner:
Public Sub test()
Dim FSO As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
Const Path As String = "C:\test\"
Dim helloWorld As Object
Set helloWorld = FSO.CreateTextFile(FileName:=(Path & "helloworld.txt"), OverWrite:=True, Unicode:=False)
helloWorld.WriteLine FSO.GetFile("C:\test\Product_ID_update.txt").OpenAsTextStream(ForReading).ReadAll
helloWorld.WriteLine FSO.GetFile("C:\test\RPT-4475.txt").OpenAsTextStream(ForReading).ReadAll
helloWorld.Close
End Sub
It works perfectly, but I have hundreds of files to append so it would be crazy to type them all out, so I wrote some code to put all the file names into an array, then loop over each index to generate the file path. Here is the code:
Sub Combine_Text_Files2()
Dim InputDirPath As String
InputDirPath = "C:\test\"
Dim InputFileType As String
InputFileType = "*.txt"
Dim OutputDirPath As String
OutputDirPath = "C:\test\"
Dim OutputFileName As String
OutputFileName = "_CombinedOutput.txt"
Dim InputFileName As String
InputFileName = Dir$(InputDirPath & InputFileType)
Dim FileArray() As String
Dim i As Integer: i = 0
Do Until InputFileName = vbNullString
ReDim Preserve FileArray(0 To i)
FileArray(i) = InputFileName
InputFileName = Dir$
i = i + 1
Loop
Dim FSO As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
Dim Stream As Object
Set Stream = FSO.CreateTextFile((OutputDirPath & OutputFileName), OverWrite:=True, Unicode:=False)
Dim FileNameAndPath As String
For i = LBound(FileArray) To UBound(FileArray)
FileNameAndPath = (InputDirPath & FileArray(i))
Debug.Print ("Processing: " & FileNameAndPath)
Dim fileToCopy As File
Set fileToCopy = FSO.GetFile(FileNameAndPath)
Dim streamToCopy As TextStream
Set streamToCopy = fileToCopy.OpenAsTextStream(ForReading)
Dim text As String
text = streamToCopy.ReadAll
Stream.WriteLine FSO.GetFile(FileNameAndPath).OpenAsTextStream(ForReading).ReadAll
Debug.Print ("Appended to " & OutputFileName & ": " & FileNameAndPath)
Next i
Stream.Close
End Sub
The FileNameAndPath value gets updated correctly, and as it goes through the first Stream.WriteLine iteration, it appends only the first letter of the first file to the output file, then moves on to the next iteration, and on the next Stream.WriteLine it fails due to Invalid procedure call or argument.
I've been trying to debug this for quite a while but not certain what is causing this. Only thing I can think of that might be causing it is the array, because it's really the only thing that is different AFAIK... Any help would be greatly appreciated!
Additional details
If I comment out the WriteLine call it goes through the entire array, printing all file paths to immediate. As you can see I broke down the original one-liner into multiple steps for debugging.
Replicating it is easy:
Create a C:\test\ directory
Create two or more text files and add text content to each of them
Run the code in the VBE
I found the problem. The problem was not the code, it works fine (though I feel sure could be improved, I'll take it over to Code Review).
The problem was that some of the source files were actually originally Excel documents that became converted to .txt and apparently carried over some meta-data that Notepad ignored, but the VBA compiler did not know what to do with trying to put it into a String.
Lesson learned, perform a sanity check of your source data.
What I've created is a script which pulls the Dell Service code, Username, and Computername, from a computer, and compiles that information into a .csv file. This script will be implemented via Active Directory login scripts, so end users wont have to do a thing.
The problem I'm having though, is everytime a person logs on, it collects their information, and adds it to the list. This means my list could just be full of two people who log onto their computer over and over.
What I would like to happen is for the script to search the .csv file for the specific data collected, and if this data exists, to not enter it.
The code I have so far is this:
'Get Dell Service Tag Info
set ProSet = GetObject("winmgmts:").InstancesOf("Win32_BIOS")
Set ProSet1 = GetObject("winmgmts:").InstancesOf("Win32_SystemEnclosure")
For each Pro in ProSet
For each Pro1 in ProSet1
ServiceTag=Pro.SerialNumber
exit for
Next
exit for
Next
'get username and computername, could also be asked in a batch
Set oShell = WScript.CreateObject("WScript.Shell")
Set oShellEnv = oShell.Environment("Process")
sComputerName = oShellEnv("ComputerName")
sUsername = oShellEnv("username")
dim filesys, filetxt, getname, path
Set filesys = CreateObject("Scripting.FileSystemObject")
Set filetxt = filesys.OpenTextFile("\\xx.xx.xx.xx\Gathering\DataLog.csv", 8, True, -2)
path = filesys.GetAbsolutePathName("\\xx.xx.xx.xx\Gathering\DataLog.csv")
getname = filesys.GetFileName(path)
filetxt.WriteLine sUsername & ", " & sComputerName & ", " & ServiceTag
filetxt.Close
This is the basic script, without the entry checker.
As for an entry checker, this is what I have tried but it doesn't seem to work:
Set objFSO = CreateObject("Scripting.Dictionary")
Set objFile = objFSO.OpenTextFile ("\\xx.xx.xx.xx\Gathering\Dictionary.txt", 8, True)
' Make comparisons case insensitive.
objList.CompareMode = vbTextCompare
' ... code to read user name and assign to variable strNameOfUser.
If (objList.Exists(strNameOfUser) = False) Then
' Add this user to the dictionary object.
objList(strNameOfUser) = True
' Log this unique user name.
objFile.WriteLine strNameOfuser
End If
Any help is appreciated! Thanks!
(1) Your code is messed up: You store a Dictionary in objFSO and then try to invoke objFSO.OpentextFile()
(2) VBScript can't read and append to a file; so ForAppending (8) won't work; you'll have to read-open the file first, gather the info, close it, append-open and append new user info (if necessary)
(3) Using a dictionary is unnecessarily complex: to fill the dictionary you'll have to read the file from start to end, before you can ask the dictionary whether a specific user exists.
While simply reading the file line by line, you can break the reading as soon as you find the user - then close - open & append - close - done.
UPDATE
Item (3) in code:
Dim goFS : Set goFS = CreateObject( "Scripting.FileSystemObject" )
Dim tsUsers : Set tsUsers = goFS.OpenTextFile(sFSpec, ForReading, True)
Dim bFound : bFound = False
Do Until tsUsers.AtEndOfStream
If 1 = Instr(tsUsers.ReadLine(), sUser) Then
bFound = True
Exit Do
End If
Loop
tsUsers.Close
If Not bFound Then
Set tsUsers = goFS.OpenTextFile(sFSpec, ForAppending, False)
tsUsers.WriteLine sUser
tsUsers.Close
End If
Because I'm a pessimistic worrier: How do you plan to cope with more than one user logging in and write-access the file at the same time?
I am trying to send some files from a folder to a fixed email address, the files need to be sent in individual emails, the file names are random.
This topic got me started:
Send individual emails to predefined set of people with all files in a folder
I altered the code a tiny bit to suit my needs, but when I run the macro it isn't sending the files. I'm sure its a simple mistake but my knowledge is limited!
This is my code:
Option Explicit
Const SOURCE_FOLDER As String = "C:\Users\Me\Desktop\Test"
Const RECIP_A As String = "me#hotmail.com"
Const EMAIL_BODY As String = "Please find attached file. Thanks and Regards, ABC"
Sub SendPDFs()
On Error GoTo ErrorHandler
Dim fileName As String
fileName = Dir(SOURCE_FOLDER)
Do While Len(fileName) > 0
Call CreateEmail(SOURCE_FOLDER & fileName)
fileName = Dir
Loop
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub
Function CreateEmail(fileName As String)
Dim olApp As Outlook.Application
Dim msg As Outlook.MailItem
' create email
Set olApp = Outlook.Application
Set msg = olApp.CreateItem(olMailItem)
' set properties
With msg
.Body = EMAIL_BODY
.Recipients.Add (RECIP_A)
.Attachments.Add fileName
.Send
End With
End Function
Ah! The only problem with the code is
Const SOURCE_FOLDER As String = "C:\Users\Me\Desktop\Test"
Change that to
Const SOURCE_FOLDER As String = "C:\Users\Me\Desktop\Test\"
Now try it. I tried and tested it and it works.
Also ensure that you have added reference to the Outlook object library.
I have a VBS file that I am trying to use to determine what folders and files are in a certain directory. I believe I have the code written correctly, but whenever I try to write out the file or current directory I get a blank text document with nothing but the root directory written out. Any advice would be greatly appreciated.
Dim NewFile
Function GetFolders (strFolderPath)
Dim objCurrentFolder, colSubfolders, objFolder, files
Set objCurrentFolder = objFSO.GetFolder(strFolderPath)
Set colSubfolders = objCurrentFolder.SubFolders
For Each objFolder In colSubfolders
NewFile.WriteLine(" - " & objFolder.Path)
Set files = folder.Files
For each folderIdx In files
NewFile.WriteLine(" - "& folderIdx.Name)
Next
Call GetFolders (objFolder.Path)
Next
End Function
Dim fso, sFolder
Set fso = CreateObject("Scripting.FileSystemObject")
sFolder = Wscript.Arguments.Item(0)
If sFolder = "" Then
Wscript.Echo "No Folder parameter was passed"
Wscript.Quit
End If
Set NewFile = fso.CreateTextFile(sFolder&"\FileList.txt", True)
NewFile.WriteLine(sFolder)
Call GetFolders(sFolder)
NewFile.Close
You haven't payed sufficient attention to your variable naming. Your script is a good example of the reason why all VBScripts should start with the line:-
Option Explicit
This would highlight all the variables that haven't been declared which in turn will point out typos and inconsistencies in variable naming. Here is how I would write it:-
Option Explicit
Dim msFolder : msFolder = Wscript.Arguments.Item(0)
If msFolder = "" Then
Wscript.Echo "No Folder parameter was passed"
Wscript.Quit
End If
Dim mfso : Set mfso = CreateObject("Scripting.FileSystemObject")
Dim moTextStream : Set moTextStream = mfso.CreateTextFile(msFolder & "\FileList.txt", True)
moTextStream.WriteLine(msFolder)
WriteFolders mfso.GetFolder(msFolder)
moTextStream.Close
Sub WriteFolders(oParentFolder)
Dim oFolder
For Each oFolder In oParentFolder.SubFolders
moTextStream.WriteLine(" - " & oFolder.Path)
Dim oFile
For Each oFile In oFolder.Files
moTextStream.WriteLine(" - " & oFile.Name)
Next
WriteFolders oFolder
Next
End Sub