VBS Creating CSV file then adding extra rows to it - csv

Below is my VBS code. I will admit, I am extremely new to this since I was give this as a job at work. I need to create a logon/logoff script that will capture certain information and store it in a csv file. I am able to get the information and store it in the csv file, but when I try to do it again, I want it to create another row and store the updated information there. I keep getting these asian characters. What seems to be the problem.
This is what I get on the second time I click my log off script:
਍潙牵琠硥⁴潧獥栠牥⹥਍
' ******************** Log Off Script **********************************
'Script to write Logoff Data Username, Computername to eventlog.
Dim objShell, WshNetwork, PCName, UserName, strMessage, strContents, logDate, logTime
Dim strQuery, objWMIService, colItems, strIP, rowCount
' Constants for type of event log entry
const EVENTLOG_AUDIT_SUCCESS = 8
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Set WshNetwork = WScript.CreateObject("WScript.Network")
logDate = Date()
logTime = Time()
PCName = WshNetwork.ComputerName
UserName = WshNetwork.UserName
strMessage = "Logoff Event Data" & "PC Name: " & PCName & "Username: " & UserName & "Date: " & logDate & "Time: " & logTime
If (objFSO.FileExists("test.csv")) Then
WScript.Echo("File exists!")
dim filesys, filetxt
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Set filesys = CreateObject("Scripting.FileSystemObject")
Set filetxt = filesys.OpenTextFile("test.csv", ForAppending, True)
filetxt.WriteLine(vbNewline & "Your text goes here.")
filetxt.Close
Else
rowCount = rowCount + 1
WScript.Echo("File does not exist! File Created!")
Set csvFile = objFSO.CreateTextFile("test.csv", _
ForWriting, True)
objShell.LogEvent EVENTLOG_AUDIT_SUCCESS, strMessage
csvFile.Write strMessage
csvFile.Writeline
End If
WScript.Quit

When in doubt, read the documentation. You're creating the file in Unicode format (3rd argument of CreateTextFile set to True):
Set csvFile = objFSO.CreateTextFile("test.csv", _
ForWriting, True)
but you open an existing (Unicode) file in ASCII format (4th argument of OpenTextFile not specified):
Set filetxt = filesys.OpenTextFile("test.csv", ForAppending, True)
Either open a file in Unicode format all of the time, or never.
Also, it's unnecessary to create more than one FileSystemObject instance. Just use the one you created at the beginning throughout the entire script. You can also use the same variable for the text stream object.
If you want to use Unicode format you need to change the above two lines into this:
Set csvFile = objFSO.CreateTextFile("test.csv", False, True)
...
Set csvFile = objFSO.OpenTextFile("test.csv", ForAppending, False, True)
otherwise into this:
Set csvFile = objFSO.CreateTextFile("test.csv")
...
Set csvFile = objFSO.OpenTextFile("test.csv", ForAppending)

Related

VB Script to count the number of columns [duplicate]

I am trying to convert a text file into an excel sheet. This is what the format looks like.
I have tried writing a script but currently all it does is overwrites my current text file adding my column headers. It does not add any of the data from my text file. Could anyone help me understand what I am doing wrong.
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
strInput=InputBox("Enter name of File in C:\Users\spencerr\Desktop\MyProject\bin\")
'ask user for file name
Set wb = objExcel.Workbooks.Open("C:\Users\bob\Desktop\MyProject\bin\" & strInput)
'Delete labels in log
For i = 1 To 5
Set objRange = objExcel.Cells(1, i).EntireColumn
objRange.Delete
Next
Set activeCell = objExcel.Cells(1, 2)
Dim intVal
Dim comVal
Dim primeRow
Dim largestRow
Dim largestDec
Dim row
primeRow = 0
'filter out one measurement per second
Do Until IsEmpty(activeCell)
primeRow = primeRow + 1
'get base integer of first value by chopping off decimal
intVal = Fix(activeCell.Value)
comVal = intVal
'get all consecutive rows that have same base integer
Do While intVal = comVal
row = activeCell.Row
Set activeCell = objExcel.Cells((row + 1), 2)
comVal = Fix(activeCell.Value)
Loop
'highest row number that contains the base integer
largestRow = row
'delete all the rows up to the largest row
j = primeRow
Do While j < largestRow
Set deleteRow = objExcel.Cells(primeRow, 2).EntireRow
deleteRow.Delete
j = j + 1
Loop
'compare the value right below the exact second and the value right above to see
'which is closer to the exact second
Set activeCell = objExcel.Cells(primeRow, 2)
largestDec = activeCell.Value
Set activeCell = objExcel.Cells((primeRow + 1), 2)
comVal = activeCell.Value
if (((intVal + 1) - largestDec) > (comVal - (intVal + 1))) Then
objExcel.Cells(primeRow, 2).EntireRow.Delete
End If
Loop
'round all the seconds that are left to the nearesr second
Set activeCell = objExcel.Cells(1, 2)
Do Until IsEmpty(ActiveCell)
row = activeCell.row
objExcel.Cells(row, 2) = Round(activeCell.Value)
Set activeCell = objExcel.Cells(row + 1, 2)
Loop
'add labels for KML conversion
objExcel.Cells(1,1).EntireRow.Insert
objExcel.Cells(1, 2).Value = "Description"
objExcel.Cells(1, 3).Value = "Latitude"
objExcel.Cells(1, 4). Value = "Longitude"
wb.Save
wb.Close
objExcel.Quit
I'd use a regular expression to transform the data into CSV format:
Set fso = CreateObject("Scripting.FileSystemObject")
Set inFile = fso.OpenTextFile("C:\path\to\input.txt")
Set outFile = fso.OpenTextFile("C:\path\to\output.csv", 2, True)
Set re = New RegExp
re.Pattern = "^week: (\d+) seconds: (\d+\.\d+) x: (\d+\.\d+) " & _
"y: (-\d+\.\d+) heading: (\d+)$"
re.IgnoreCase = True
outFile.WriteLine "Week,Seconds,X,Y,Heading"
Do Until inFile.AtEndOfStream
For Each m In re.Execute(inFile.ReadLine)
outFile.WriteLine m.Submatches(0) & "," & m.Submatches(1) & "," & _
m.Submatches(2) & "," & m.Submatches(3) & "," & m.Submatches(4)
Next
Loop
inFile.Close
outFile.Close
Then you can open the CSV file with Excel and save it as a workbook.
I'll throw out another solution. Just use Excel's TextToColumns() function. Tell it to use Space (8th argument = True) as a delimiter and to Treat consecutive delimiters as one (4th argument = True).
Const xlDelimited = 1
Const xlDoubleQuote = 1
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
objExcel.Workbooks.Open "c:\path\to\text.txt"
With objExcel.ActiveSheet
.Columns("A:A").TextToColumns .Range("A1"), xlDelimited, xlDoubleQuote, True, , , , True
End With
Or, in long form:
With objExcel.ActiveSheet
.Columns("A:A").TextToColumns _
.Range("A1"), _ ' Destination
xlDelimited, _ ' Data Type
xlDoubleQuote, _ ' Text Qualifier
True, _ ' Consecutive Delimiters?
, _ ' Use Tab for Delimiter?
, _ ' Use Semicolon for Delimiter?
, _ ' Use Comma for Delimiter?
True ' Use Space for Delimiter?
End With
That will get your data into proper columns. Then just delete the "label" columns:
.Range("A:A,C:C,E:E,G:G,I:I").Delete
and save it as a CSV.
From the comments, I think it might be easier to skip VBA, change the .txt file extension into .csv. Then, when you open this in Excel, you'll get a column with all of your data.
Along the top, under the "Data" tab, you'll see "Text to Columns". Highlight column A, choose "Text to Columns", then choose "Delimited", and hit "Next", then choose "Space". You'll see a preview of how the data will be split up below it. If that looks good, you can click "Finish" to overwrite Col. A with the new split up data, or click "Next" to choose a specific cell to start in.
That should get you pretty far, and it may not be perfect, so let me know what it looks like after this (or if you have any questions).
A faster way: convert the file to csv.
Since your source is fixed width the easiest way is to just copy the bits you need to a new line.
sep = ";" 'or , (depends on your language settings)'
header = "week" & sep & "seconds" & sep
line = "WEEK: 1799 SECONDS: 251731.358 X:32.896391 Y:-117.200281 Heading: 178"
csvLine = mid(line,7,4) & sep & mid(line,22,10) & sep 'etc..'
'write to your csv file, here I only echo to the screen
Wscript.echo header
Wscript.echo csvLine
'week;seconds;
'1799;251731.358;
Using this method is faster end you don't need Excel installed on the pc

Set cell value with VBA

I scan and save images with Wia using VBA in Microsoft Access.
The filepath to the saved image should be set as the value of the current cell.
I can't figure out how to do this but it seems like an easy task after learning how to use Wia.
Here is my current code that scans a document.
Function scanImage() As String
Dim imagePath As String
Dim folder As String
folder = "C:\Users\username\Pictures\scans\"
Dim tempName, obj
Set obj = CreateObject("Scripting.FileSystemObject")
tempName = obj.GetTempName
Dim filename
filename = Now
filename = Replace(filename, ".", "_")
filename = Replace(filename, " ", "_")
filename = Replace(filename, ":", "_")
imagePath = folder & filename & ".jpg"
Dim dev As Device
Dim wiaDialog As New WIA.CommonDialog
Dim wiaImage As WIA.ImageFile
Set dev = wiaDialog.ShowSelectDevice
Set wiaImage = wiaDialog.ShowAcquireImage
wiaImage.SaveFile (imagePath)
scanImage = imagePath
End Function
As comments have said - there's no cells in Access, and definitely no active cell.
You can add a record to a database using either of the methods below, but how do you plan on extracting that information again?
In Excel you just ask for the data in cell A1 for example, but in a database you generally ask for the data from a field or fields where another field on that same record is equal to some other values (either by supplying the 'other value' directly or by referencing other tables within the database).
So, for example, in your database you'd ask for the file paths of all files scanned on a certain date, or have some kind of description field to identify the file.
This would be written something like:
SELECT FilePath FROM Table2 WHERE DescriptionField = 'MyPhoto'
Anyway, the answer to get that single text string (imagepath) into a new record in a table is:
Sub InsertValueToTable()
Dim imagepath As String
imagepath = "<file path>"
'NB: The table name is 'Table2', the field (column) within the table is called 'FilePath'.
'One way to do it:
'DoCmd.RunSQL "INSERT INTO Table2(FilePath) VALUES ('" & imagepath & "')"
'Another way to do it:
Dim rst As dao.Recordset
Set rst = CurrentDb.OpenRecordset("Table2")
With rst
.AddNew
rst!FilePath = imagepath
.Update
.Close
End With
Set rst = Nothing
End Sub
Note - if you use a Text field in the database you'll be limited to 255 characters.

vbscript error: Name Redifiined; Line 43: ExecuteGlobal sFileContents

Question from a amatuer scripter with informal coding background:
I've researched this on stack, msdn, random scripting websites but can't seem to glean a concrete solution. So please be advised this request for help is a last resort even if the solution is simple.
To put it simply, I'm trying to call a function that parses the last modified date of a file into an array of date formats. The filepath is the function parameter. These files are .vbs files in a client-side testing environment. This will be apparent if you look at the script.
My best guess is the "name redefined" error has something to do global variables being Dim'd in some way that's throwing the error.
Anyway, here's the calling sub:
Option Explicit
'=============================
'===Unprocessed Report========
'=============================
'*****Inputs: File Path*********************
dim strFolderPath, strFilename, strReportName, strFileExt, FullFilePath
strFolderPath = "C:\Users\C37745\Desktop\"
strFilename = "UNPROCESSED_REPORT"
strReportName = "Unprocessed"
strFileExt = ".xlsx"
'************************************
FullFilePath = strFolderPath & strFilename & strFilename & strFileExt
'************************************
Sub Include(MyFile)
Dim objFSO, oFileBeingReadIn ' define Objects
Dim sFileContents ' define Strings
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oFileBeingReadIn = objFSO.OpenTextFile(MyFile, 1)
sFileContents = oFileBeingReadIn.ReadAll
oFileBeingReadIn.Close
ExecuteGlobal sFileContents
End Sub
Include "C:\Users\C37745\Desktop\VBStest\OtherTest\TEST_DLM.vbs"
''''''''''FOR TESTING''''''''''''''
Dim FilePath, varTEST
strFilePath = FullFilePath
varTEST = ParseDLMToArray(strFilePath)
msgbox varTESTtemp(0)
'''''''''''''''''''''''''''''''''
Here's the function I'm trying to call (or read, I guess):
Function ParseDLMtoArray(strFilePath)
Dim strFilePath, dlmDayD, dlmMonthM, dlmYearYY, dlmYearYYYY, DateFormatArray, dateDLM
Dim objFSO, File_Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set File_Object = objFSO.GetFile(strFilePath)
dateDLM = File_object.DateLastModified
dlmDayD = Day(dateDLM)
dlmMonthM = Month(dateDLM)
dlmYearYY = Right(Year(dateDLM),2)
dlmYearYYYY = Year(dateDLM)
'Adds a leading zero if a 1-digit month is detected
If(Len(Month(dlmDayD))=1) Then
dlmmonthMM ="0"& dlmMonthM
Else
dlmMonthMM = dlmMonthM
End If
'Adds a leading zero if a 1-digit day is detected
If(Len(Day(dlmDayD))=1) Then
dlmDayDD = "0" & dlmDayD
Else
dlmDayDD = dlmDayD
End If
varDLM_mmyyyy = dlmMonthMM & dlmYearYYYY
varDLM_mmddyy = dlmMonthMM & dlmDayDD & dlmYearYY
varDLM_mmddyyyy = dlmMonthMM & dlmDayDD & dlmYearYYYY
DateFormatArray = Array( _
varDLM_mmyyyy, _
varDLM_mmddyy, _
varDLM_mmddyyyy _
)
ParseDLMtoArray = DateFormatArray
End Function
Any advice is appreciated, including general feedback on best practices if you see an issue there. Thanks!
Your
Function ParseDLMtoArray(strFilePath)
Dim strFilePath
...
tries to declare/define strFilePath again. That obviously can't be allowed, because it would be impossible to decide whether that variable should contain Empty (because of the Dim) or the argument you passed.
At a first glance at your code, you can just delete the Dim strFilePath.

exporting a query output to a text file

I have an access query which I am trying to export to a text file using the following code:
DoCmd.TransferText acExportFixed, "Export Specification", _
"Test Query", "C:\Users\Documents\TestOutput.txt", True
The issue I am having is: The output file "TestOutput.txt" has the data displayed with fixed width but the column headers are comma delimited. I want the column headers to be fixed width too.
What would column headers not be displayed same as the rest of the data?
AFAICT, that is an unavoidable "feature" of TransferText. It seems to lack any kind of built-in intelligence to say "OK, we're exporting as acExportFixed, so let's examine the column widths defined in Export Specification and output the column headers using those same widths". Instead it just gives the column names as a comma-separated list.
As with everything else in Access, when its default behaviors are unsatisfactory, you can write VBA code to do it your way.
Const VB_FORREADING = 1
Const VB_FORWRITING = 2
Const cstrFile As String = "C:\Users\Documents\TestOutput.txt"
Const cstrHeaderRow As String = "col1 col2 etc..."
Dim oFSO As Object
Dim oFile As Object
Dim strContents As String
' do TransferText without the field names '
' (HasFieldNames default = False) '
DoCmd.TransferText acExportFixed, "Export Specification", _
"Test Query", cstrFile
Set oFSO = CreateObject("Scripting.FileSystemObject")
' read file content into strContents string variable '
Set oFile = oFSO.OpenTextFile(cstrFile, VB_FORREADING)
strContents = oFile.ReadAll
oFile.Close
' re-write file using cstrHeaderRow plus strContents '
Set oFile = oFSO.OpenTextFile(cstrFile, VB_FORWRITING)
oFile.write cstrHeaderRow & vbCrLf & strContents
oFile.Close
Set oFile = Nothing
Set oFSO = Nothing

Converting xls to csv using VBScript and separate by semicolons

I have a VBScript code snippet which converts my xls and xlsx files into csv files. However, I want each cell to be separated by a semicolon rather than a comma. On my computer, the list separator is set to semicolon instead of comma so when I open up an excel window and do save as csv, it separates by semicolon. However, my VBScript produces a csv file separated by commas. I found the code snippet online as I do not really know VBScript (I'm mainly a Java Programmer) that well. How can I change the code snippet to separate the csv files by semicolon rather than by comma?
if WScript.Arguments.Count < 2 Then
WScript.Echo "Error! Please specify the source path and the destination. Usage: XlsToCsv SourcePath.xls Destination.csv"
Wscript.Quit
End If
Dim oExcel
Set oExcel = CreateObject("Excel.Application")
Dim oBook
Set oBook = oExcel.Workbooks.Open(Wscript.Arguments.Item(0))
oBook.SaveAs WScript.Arguments.Item(1), 6
oBook.Close False
oExcel.Quit
WScript.Echo "Done"
you can keep your original script, only need to give a parameter to indicate local setting must apply. This saves my CSV with a ; separator
if WScript.Arguments.Count < 2 Then
WScript.Echo "Error! Please specify the source path and the destination. Usage: XlsToCsv SourcePath.xls Destination.csv"
Wscript.Quit
End If
Dim oExcel
Set oExcel = CreateObject("Excel.Application")
oExcel.DisplayAlerts = FALSE 'to avoid prompts
Dim oBook, local
Set oBook = oExcel.Workbooks.Open(Wscript.Arguments.Item(0))
local = true
call oBook.SaveAs(WScript.Arguments.Item(1), 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, local) 'this changed
oBook.Close False
oExcel.Quit
WScript.Echo "Done"
The use of a comma in delimited text files finds its roots in the regional settings. While the comma is standard in the US, other countries such as Germany use the semicolon instead. You can change the List Separator value in the Regional and Language settings and then choose CSV (Comma delimited) (.csv) from Excel's Save As window. The resulting file will be delimited by whatever value is in the system settings. This script changes default List Separator setting. Then it opens the specified spreadsheet and resaves it. It reverts the system setting to its previous value before finishing.
It accepts two command line parameters. The first is the input spreadsheet; the second is the output filename for the exported file.
strDelimiter = ";"
strSystemDelimiter = "" ' This will be used to store the current sytem value
Const HKEY_CURRENT_USER = &H80000001
' Get the current List Separator (Regional Settings) from the registry
strKeyPath = "Control Panel\International"
strValueName = "sList"
strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
objRegistry.GetStringValue HKEY_CURRENT_USER, strKeyPath, strValueName, strSystemDelimiter
' Set it temporarily to our custom delimiter
objRegistry.SetStringValue HKEY_CURRENT_USER, strKeyPath, strValueName, strDelimiter
' Open spreadsheet with Excel and save it in a text delimited format
Const xlCSV = 6
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open(WScript.Arguments.Item(0))
objWorkbook.SaveAs WScript.Arguments.Item(1), xlCSV
objWorkbook.Close vbFalse ' Prevent duplicate Save dialog
objExcel.Quit
' Reset the system setting to its original value
objRegistry.SetStringValue HKEY_CURRENT_USER, strKeyPath, strValueName, strSystemDelimiter
After some testing, it seems that this only works through Excel's Save As dialog and not through command-line or automation. I've changed the script a little to make the Excel window visible and use shortcuts keys to open the Save As dialog through the Excel interface. This should do the trick. It worked for me on Vista x64 with Excel 2007. I hope this works for you.
strDelimiter = ";"
strSystemDelimiter = "" ' This will be used to store the current sytem value
Const HKEY_CURRENT_USER = &H80000001
' Get the current List Separator (Regional Settings) from the registry
strKeyPath = "Control Panel\International"
strValueName = "sList"
strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
objRegistry.GetStringValue HKEY_CURRENT_USER, strKeyPath, strValueName, strSystemDelimiter
' Set it temporarily to our custom delimiter
objRegistry.SetStringValue HKEY_CURRENT_USER, strKeyPath, strValueName, strDelimiter
' Open spreadsheet with Excel and save it in a text delimited format
Const xlCSV = 6
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = vbTrue
Set objWorkbook = objExcel.Workbooks.Open(WScript.Arguments.Item(0))
WScript.Sleep 500 ' Delay to make sure the Excel workbook is open
strWorkbookName = objExcel.ActiveWorkbook.Name
strTitlebar = strWorkbookName
Set WshShell = CreateObject("WScript.Shell")
WshShell.AppActivate strTitlebar ' Make the workbook active so it receives the keystrokes
WshShell.SendKeys "%fa" ' Keyboard shortcuts for the Save As dialog
WScript.Sleep 500
WshShell.SendKeys "%tc{ENTER}" ' Change the Save As type to CSV
If WScript.Arguments.Count > 1 Then
WshShell.SendKeys "+{TAB}" & WScript.Arguments.Item(1)
WScript.Sleep 500
End If ' This If block changes the save name if one was provided
WshShell.SendKeys "{ENTER}" ' Save the file
WScript.Sleep 500
WshShell.SendKeys "{ENTER}" ' Dismiss the CSV warning dialog
Set WshShell = Nothing
objWorkbook.Close vbFalse ' Prevent duplicate Save dialog
objExcel.Quit
' Reset the system setting to its original value
objRegistry.SetStringValue HKEY_CURRENT_USER, strKeyPath, strValueName, strSystemDelimiter
The Function SaveAs is defined so :
.SaveAs(FileName, FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup, AccessMode, ConflictResolution, AddToMru, TextCodepage, TextVisualLayout, Local)
Thas is, to use the semicolon (if your regional language option are correctly set)
ExcelObj.Workbooks(1).SaveAs csvFile, 6,,,,,,,,,,True
You can reopen the file with the FSO object, then do a Replace() on the comma character.
Const OpenAsDefault = -2
Const FailIfNotExist = 0
Const ForReading = 1
Const ForWriting = 2
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set fCSVFile = _
oFSO.OpenTextFile("C:\path\file.csv", ForReading, FailIfNotExist, OpenAsDefault)
sFileContents = fCSVFile.ReadAll
fCSVFile.Close
sFileContents = Replace(sFileContents, ",",";"))
Set fCSVFile = oFSO.OpenTextFile("C:\path\file.csv", ForWriting, True)
fCSVFile.Write(sFileContents)
fCSVFile.Close
I changed the parameter to true, and worked for me.
if WScript.Arguments.Count < 2 Then
WScript.Echo "Erro! Especifique origem e destino. Exemplo: XlsToCsv SourcePath.xls Destination.csv"
Wscript.Quit
End If
Dim oExcel
Set oExcel = CreateObject("Excel.Application")
Dim oBook
Set oBook = oExcel.Workbooks.Open(Wscript.Arguments.Item(0))
call oBook.SaveAs(WScript.Arguments.Item(1), 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, true) --CHANGED
oBook.Close False
oExcel.Quit