Using VBScript to delete a column from CSV file - csv

I need to use VBScript to delete various columns from CSV file.
The columns to be eliminated are from number 101 to number 106.
My code below it does not delete any columns:
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fso, strLine, dataArray, clippedArray()
InputFile="C:\input.csv"
OutputFile="C:\input_n_1.csv"
Set fso = CreateObject("Scripting.FileSystemObject")
Set InFile = fso.OpenTextFile(InputFile, ForReading)
Set OutFile = fso.OpenTextFile(OutputFile, ForWriting, True)
Do While InFile.AtEndOfStream <> True
strLine = InFile.ReadLine
ReDim Preserve clippedArray(x)
clippedArray(x) = Split(strLine,";")
intCount = 0
newLine = ""
For Each Element In clippedArray(x)
If intCount <> (101 OR 102 OR 103 OR 104 OR 105 OR 106) Then
EndChar = "|"
newLine = newLine & Element & EndChar
End If
intCount = intCount + 1
Next
OutFile.WriteLine newLine
Loop
InFile.Close
OutFile.Close
WScript.Echo "Done"

The code inside your loop has a few issues. For example, no value is specified for x when trying to ReDim your clippedArray array. There would be no need to Preserve what's in the array either since you're placing new data in it.
The interior of the loop can be simplified and put into a function like this:
Function GetUpdatedLine(p_sLine)
Dim arrColumns
Dim sNewLine
Dim sEndChar
Dim iCounter
' Split line into columns
arrColumns = Split(p_sLine, ";")
' Initialize variables
sNewLine = ""
sEndChar = "|"
For iCounter = 1 To UBound(arrColumns) + 1
Select Case iCounter
Case 101, 102, 103, 104, 105, 106
' Skip these columns
Case Else
' Add to new line
If sNewLine <> "" Then sNewLine = sNewLine & sEndChar ' Add separator
sNewLine = sNewLine & arrColumns(iCounter - 1) ' arrColumns is a zero-based array
End Select
Next
GetUpdatedLine = sNewLine
End Function
You loop can now be updated to this:
Do While InFile.AtEndOfStream <> True
OutFile.WriteLine GetUpdatedLine(InFile.ReadLine)
Loop

Related

Parsing txt file in Access VBA

I have never used Access VBA, but I need to create a module that parses a txt file and then immediately imports it into a table.
A dumbed-down of the txt is this:
15686541
468469
48978965
456287
48666545
45684651
456788
I need to parse it in order to
Remove all the line/rows that are not six characters long
Add commas after the third and fifth characters
The final result being something like:
468,46,9
456,28,7
456,78,8
All this must be done in an Access VBA module so that the importing process becomes seamless.
Thanks a lot!
Sorry to bother
This function will do that - and very fast:
Public Function ImportLog(ByVal Filename As String) As Long
Dim rs As DAO.Recordset
Dim File As Integer
Dim Data As String
Dim Data6 As String
Dim Records As Long
Set rs = CurrentDb.OpenRecordset("Select Top 1 * From YourTableName")
File = FreeFile()
Open Filename For Input As #File
While Not EOF(File)
Line Input #File, Data
If Len(Data) = 6 Then
Data6 = Space(6 + 2) ' Space for six digits and two commas.
' Build field value.
Mid(Data6, 1, 3) = Mid(Data, 1, 3)
Mid(Data6, 4, 1) = ","
Mid(Data6, 5, 2) = Mid(Data, 4, 2)
Mid(Data6, 7, 1) = ","
Mid(Data6, 8, 1) = Mid(Data, 6, 1)
rs.AddNew
' Adjust "Data" to your field name.
rs.Fields("Data").Value = Data6
rs.Update
Records = Records + 1
End If
Wend
Close #File
rs.Close
Set rs = Nothing
ImportLog = Records
End Function
The return value is the count of added records.
Try this:
Sub Import()
Dim fileNum As Integer
Dim dataLine As String
Dim column1 As String
Dim column2 As String
Dim column3 As String
fileNum = FreeFile()
Open "Filename.txt" For Input As #fileNum
While Not EOF(fileNum)
Line Input #fileNum, dataLine
If Len(dataLine) = 6 Then
column1 = Mid(dataLine, 1, 3)
column2 = Mid(dataLine, 4, 2)
column3 = Mid(dataLine, 6, 1)
CurrentDb.Execute "INSERT INTO YourTable(Column1, Column2, Column3) VALUES('" & column1 & "', '" & column2 & "', '" & column3 & "')"
End If
Wend
Close #fileNum
End Sub

VBscript - Transpose CSV File

Does anyone have a short script in VBscript for transposing a Matrix (given as CSV (comma separated values) file)?
A, 1, 2, 3
B, 7, 5, 6
->
A, B
1, 7
2, 5
3, 6
Many Thanks in advance
Tom
So by creating dynamic arrays and auto-increment their growth in parallel with discovering new columns of the original matrix, you can auto build the new data structure quite quickly.
Const OutputCSV = "C:\op.csv"
Dim dt_start, WriteOutput : dt_start = Now
Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
Dim file : Set file = fso.OpenTextFile("C:\test.csv", 1, True)
Set WriteOutput = fso.OpenTextFile(OutputCSV, 8, True)
Dim fc : fc = file.ReadAll : file.close : Dim fcArray : fcArray = Split(fc, vbCrLf)
WScript.echo "Before Transpose"
WScript.echo "----------------"
WScript.echo fc
WScript.echo "----------------"
Dim opArray() : ReDim opArray(0)
For Each row In fcArray
Dim tmp: tmp = Split(row, ",")
For ent=0 To UBound(tmp)
If ent > UBound(opArray) Then
ReDim Preserve opArray(UBound(opArray)+1)
opArray(ent) = Trim(tmp(ent))
Else
If Len(opArray(ent)) > 0 Then
opArray(ent) = opArray(ent) & "," & Trim(tmp(ent))
Else
opArray(ent) = Trim(tmp(ent))
End If
End If
Next
Next
Dim dt_end : dt_end = Now
WScript.echo "After Transpose"
WScript.echo "----------------"
WScript.echo Join(opArray, vbCrLf)
WScript.echo "----------------"
WScript.echo "Script Execution Time (sec): " & DateDiff("s", dt_start, dt_end)
WriteOutput.Write Join(opArray, vbCrLf) : WriteOutput.Close
If it's just two lines with an equal number of values, you can read both into arrays using the Split function:
a1 = Split(FileIn.ReadLine, ",")
a2 = Split(FileIn.ReadLine, ",")
Then, iterate the arrays and write each element:
For i = 0 To UBound(a1)
FileOut.WriteLine a1(i) & ", " & a2(i)
Next
I'm assuming you know how to open files for reading and writing?
Edit: It sounds like you may have an unknown number of rows to read. In that case, you can use an array of arrays:
Dim a(255) ' Hold up to 255 rows. Adjust as needed. Or use ReDim Preserve to grow dynamically.
Do Until FileIn.AtEndOfStream
a(i) = Split(FileIn.ReadLine, ",")
i = i + 1
Loop
Then, to write:
For j = 0 To UBound(a(0))
' Concatenate the elements into a single string...
s = ""
For k = 0 To i - 1
s = s & a(k)(j) & ","
Next
' Write the string without the final comma...
FileOut.WriteLine Left(s, Len(s) - 1)
Next

Getting random characters when writing SMS message to .CSV (VBScript)

I am using the the program FrontlineSMS and some code written in VBScript to take incoming SMS messages and log them to a CSV file. However, random characters such as percents and numbers are ending up in the CSV file even though they are not in the SMS. Below is an example of what I mean:
I send an SMS with my phone to the modem connected to the computer reading
"07/12/2013 11:29:56 25 Happy Holidays"
The modem then receives the message and passes it on the script, which outputs it to a .CSV file. However when I open the file it reads:
"07%2F12%2F2013 | 11%3A29%3A56 | 25 | Happy | Holidays |
Where each word is in its own cell. I need help in figuring out how to get rid of the extra characters that show up (like "%2F"), my guess is that it has to do with the encryption/decryption of the characters when converting to .CSV but I don't know where to start looking to solve this.
Edit: I found out that it has to do with the ASCII coding. "%2F" is Hex for a slash "/", but I still don't know how to prevent this from happening.
Thanks!
Here is the entire script:
Option Explicit
Dim first, secnd
Dim fso, outFile
Dim strFile, strValues, strLine, strInfo
Dim stamp, num, i, identify
Const ForAppending = 8
'error handling/format
'Settings
identify = WScript.Arguments(1)
CStr(identify)
stamp = MyDate()
CStr(stamp)
strFile = "C:\SMScomm\Log\" &identify &" " &stamp & " log.csv"
'Create the file system object
Set fso = CreateObject("Scripting.FileSystemObject")
'Check whether argument were passed
If WScript.Arguments.Count <> 1 Then
WScript.Echo "No arguments were passed"
End If
strInfo = WScript.Arguments(0)
'Replace(strInfo, "%2C", ",")
'Split the argument from FSMS so it reads normally
strValues = Split(strInfo, "+")
'Open to append
Set outFile = fso.OpenTextFile(strFile, ForAppending, True)
num = UBound(strValues)
If num = 0 then
WScript.Echo "Formatting error"
End If
Do while i < num + 1
strValues(i) = strValues(i) & ","
i = i + 1
Loop
'Write to the .csv
i = 0
Do while i < num + 1
outFile.Write(strValues(i) + " ")
i = i + 1
Loop
outFile.WriteBlankLines(1)
'Close the file
outFile.Close
'Clean up
Set outFile = Nothing
Set fso = Nothing
Function MyDate()
Dim dteCurrent, dteDay, dteMonth, dteYear
dteCurrent = Date()
dteDay = Day(dteCurrent)
dteMonth = Month(dteCurrent)
dteYear = Year(dteCurrent)
MyDate = dteMonth & "-" & dteDay & "-" & dteYear
End Function
It looks like either your script or the modem is converting special characters such as "/" into their Hex format.
Can you post the script that dumps this information into CSV format?
Option Explicit
Dim first, secnd
Dim fso, outFile
Dim strFile, strValues, strLine, strInfo
Dim stamp, num, i, identify
Const ForAppending = 8
'error handling/format
'Settings
identify = WScript.Arguments(1)
CStr(identify)
stamp = MyDate()
CStr(stamp)
strFile = "C:\SMScomm\Log\" &identify &" " &stamp & " log.csv"
'Create the file system object
Set fso = CreateObject("Scripting.FileSystemObject")
'Check whether argument were passed
If WScript.Arguments.Count <> 1 Then
WScript.Echo "No arguments were passed"
End If
strInfo = WScript.Arguments(0)
'Replace(strInfo, "%2C", ",")
'Split the argument from FSMS so it reads normally
strValues = Split(strInfo, "+")
'Open to append
Set outFile = fso.OpenTextFile(strFile, ForAppending, True)
num = UBound(strValues)
If num = 0 then
WScript.Echo "Formatting error"
End If
Do while i < num + 1
strValues(i) = strValues(i) & ","
i = i + 1
Loop
'Write to the .csv
i = 0
Do while i < num + 1
Replace(strValues(i), '%2F', '/')
Replace(strValues(i), '%3A', ':')
outFile.Write(strValues(i) + " ")
i = i + 1
Loop
outFile.WriteBlankLines(1)
'Close the file
outFile.Close
'Clean up
Set outFile = Nothing
Set fso = Nothing
Function MyDate()
Dim dteCurrent, dteDay, dteMonth, dteYear
dteCurrent = Date()
dteDay = Day(dteCurrent)
dteMonth = Month(dteCurrent)
dteYear = Year(dteCurrent)
MyDate = dteMonth & "-" & dteDay & "-" & dteYear
End Function
I am sure there is a more elegant way of doing this but it should solve your problem.

VBScript - Find specific term in between commas in .csv and append columns based on values found

I am trying to append additional columns to an existing .csv file called Original.csv, but the values to be appended should vary base on whether an N or a J is part of the value between the 4th comma and the 5th comma in Original.csv (technically the 5th column if the file were opened in Excel). Below are the codes I wrote. They don't work, so it's for your reference only. Thanks in advance for your help.
rowCounter = 1
Do Until objOriginal.AtEndofStream
strOriginal = objOriginal.ReadLine
arrOriginal = Split(strOriginal, ",")
arrType = Split(arrOriginal(5),",")
strType = arrType(1)
If IsTrue(InStr(strType,"N")) Then
strOriginal = objOriginal.ReadLine & ",Type N,USD"
objPosition.WriteLine(strOriginal)
Else
strOriginal = objOriginal.ReadLine & ",Type J,USD"
objPosition.WriteLine(strOriginal)
End If
rowCounter = rowCounter + 1
Loop
The proper tool for .csv files is ADO. All you need to create a new (text) table by appending columns to an existing table is an SQL statement like:
SELECT S.*, 'whatever' & (IIF([B]='J','-j', '-n')) As [NewCol] INTO [dst.csv] FROM [src.csv] S
and - in general - a schema.ini file like
[src.csv]
ColNameHeader=True
Format=Delimited(;)
Col1=A Integer
Col2=B Char Width 15
[dst.csv]
ColNameHeader=True
Format=Delimited(;)
Col1=A Integer
Col2=B Char Width 15
Col3=NewCol Char Width 15
to specify your table structures unequivocally.
In code:
' Absolute path to .CSV folder
Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject")
Dim sDS : sDS = oFS.GetAbsolutePathName("..\Data\txt")
' Connectionstring
Dim sCS : sCS = Join(Array( _
"Provider=Microsoft.Jet.OLEDB.4.0" _
, "Data Source=" & sDS _
, "Extended Properties=""" & Join(Array( _
"Text" _
, "HDR=Yes" _
), ";") & """" _
), ";")
' Database/Connection
Dim oDb : Set oDb = CreateObject("ADODB.Connection")
Dim sSQL
oDb.Open sCS
' show src
sSQL = "SELECT * FROM [src.csv]"
WScript.Echo sSQL
WScript.Echo oDb.Execute(sSQL).GetString(adClipString, , vbTab, vbCrLf, "null")
' copy/append col to new dst
If oFS.FileExists(oFS.BuildPath(sDS, "dst.csv")) Then oFS.DeleteFile oFS.BuildPath(sDS, "dst.csv")
sSQL = "SELECT S.*, 'whatever' & (IIF([B]='J','-j', '-n')) As [NewCol] INTO [dst.csv] FROM [src.csv] S"
WScript.Echo "--------------"
WScript.Echo "Exec:", sSQL
oDb.Execute sSQL
' show dst
sSQL = "SELECT * FROM [dst.csv]"
WScript.Echo "--------------"
WScript.Echo sSQL
WScript.Echo oDb.Execute(sSQL).GetString(adClipString, , vbTab, vbCrLf, "null")
output:
SELECT * FROM [src.csv]
1 J
2 N
3 J
4 N
--------------
Exec: SELECT S.*, 'whatever' & (IIF([B]='J','-j', '-n')) As [NewCol] INTO [dst.csv] FROM [src.csv] S
--------------
SELECT * FROM [dst.csv]
1 J whatever-j
2 N whatever-n
3 J whatever-j
4 N whatever-n
That way you reduce the risk of blunders like
polluting your code with un-used (und un-usable) variables (rowcounter)
trying to split an element from an array created by split on the same separator
accessing the next/wrong line by .ReadLine() twice
to zero
If you are looking for a simple down and dirty method...
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Path\Original.csv", ForReading, False)
arrLines = Split(objFile.ReadAll, vbCrLf)
objFile.Close
Set objFile = objFSO.CreateTextFile("C:\Path\Appended.csv", True)
For Each strLine In arrLines
strType = Split(strLine, ",")(4)
Select Case True
Case InStr(1, strType, "N", 1) > 0
objFile.WriteLine strLine & ",Type N,USD"
Case InStr(1, strType, "J", 1) > 0
objFile.WriteLine strLine & ",Type J,USD"
Case Else
objFile.WriteLine strLine
End Select
Next
objFile.Close
First you will want to open and read the file to a variable, you can split each line in the process. Close the file
Create a New file to write to and loop through each line.
You can pull out the 5th column by doing a split and using the (#) can return only the value for that place in the array.
Do a select case checking for the string value and rewrite the line plus your two column values to the new file
close the new file when your done with the loop...
Like I said its down and dirty and may need some adjustments and modifications depending on the actual file and values being used, but it should work for your purpose.

Split large CSV file with header into multiple CSV files for every nth row with a header

I have a large CSV file that I would like to split into multiple CSV files. I've tried numerous VBS scripts, but I cannot seem to get this.
This script does some of what I want but does not save them as CSV files:
Sub Split()
Dim rLastCell As Range
Dim rCells As Range
Dim strName As String
Dim lLoop As Long, lCopy As Long
Dim wbNew As Workbook
With ThisWorkbook.Sheets(1)
Set rLastCell = .Cells.Find(What:="*", After:=[A1], SearchDirection:=xlPrevious)
For lLoop = 1 To rLastCell.Row Step 35
lCopy = lCopy + 1
Set wbNew = Workbooks.Add
.Range(.Cells(lLoop, 1), .Cells(lLoop + 35, .Columns.Count)).EntireRow.Copy _
Destination:=wbNew.Sheets(1).Range("A1")
wbNew.Close SaveChanges:=True, Filename:="Inventory_" & lLoop + 34
Next lLoop
End With
End Sub
Added a saveas line to your code to specify the file format, you should be all set
Sub Split()
Dim rLastCell As range
Dim rCells As range
Dim strName As String
Dim lLoop As Long, lCopy As Long
Dim wbNew As Workbook
With ThisWorkbook.Sheets(1)
Set rLastCell = .Cells.Find(What:="*", After:=[A1], SearchDirection:=xlPrevious)
For lLoop = 2 To rLastCell.Row Step 35
lCopy = lCopy + 1
Set wbNew = Workbooks.Add
.Cells(1, 1).EntireRow.Copy _
Destination:=wbNew.Sheets(1).range("A1")
.range(.Cells(lLoop, 1), .Cells(lLoop + 35, .Columns.Count)).EntireRow.Copy _
Destination:=wbNew.Sheets(1).range("A2")
wbNew.SaveAs FileName:="Inventory_" & format(lLoop + 34,"0000") & ".csv", FileFormat:=xlCSV, Local:=True
wbNew.Close SaveChanges:=False
Next lLoop
End With
End Sub
Off the top of my head:
Const ForReading = 1
Const ForWriting = 2
Set fso = CreateObject("Scripting.FileSystemObject")
maxRows = 35
i = 0
n = 0
Set out = Nothing
Set csv = fso.OpenTextFile("C:\PATH\TO\your.csv", ForReading)
header = csv.ReadLine
Do Until csv.AtEndOfStream
If i = 0 Then
If Not out Is Nothing Then out.Close
Set out = fso.OpenTextFile("out_" & Right("00" & n, 2) & ".csv", ForWriting)
out.WriteLine(header)
n = n + 1
End If
out.WriteLine(csv.ReadLine)
i = (i + 1) Mod maxRows
Loop
csv.Close
If Not out Is Nothing Then out.Close