Edit a CSV Record - vbscript

How do I edit a record in a CSV file?
for example I have a .csv file named "test.csv" and inside it is:
"123","Active"
"456","Not-Active"
"999000123","Active"
How can I edit "456" and change it from Not-Active to Active
The only way I can think of it is to:
Open the .csv file. Maybe store the data inside a string?
Search for "456",".
Get the line position of "456",". How to do this?
Delete the line that we just got the position of. How to do this?
Recreate the line with what we want. How to do this?
Insert the recreated data in the line position. How to do this?
Save the .csv file.
But is there not a easier way to do this?
And if not how do I do steps # 4, 5, and 6?
Maybe to convert it onto an Array or something? But I have no idea how to do this in Classic ASP.

Based on Ekkehards answer, here is the ASP version. The .csv file needs to be located in the same directory as the .asp script. Feel free to award the points to Ekkehard
<%#LANGUAGE="VBSCRIPT"%>
<% option explicit %>
<%
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim tsIn : Set tsIn = goFS.OpenTextFile(Server.MapPath( "46734115.csv"))
Dim tsOut : Set tsOut = goFS.CreateTextFile(Server.MapPath("46734115-2.csv"))
Dim sLine
Do Until tsIn.AtEndOfStream
sLine = tsIn.ReadLine()
dim pos : pos = instr( sLine, """456"",")
Response.Write(pos)
if pos > 0 then
' to keep things simple, just replace the whole line
sLine = """456"",""Active"""
end if
tsOut.WriteLine sLine
' Just so there is something to see: print line to the browser window
Response.Write( sLine & "<br />")
Loop
tsOut.Close
tsIn.Close
%>

A simplyfied version of the script #abr mentioned:
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim tsIn : Set tsIn = goFS.OpenTextFile("..\data\46734115.csv")
Dim tsOut : Set tsOut = goFS.CreateTextFile("..\data\46734115-2.csv")
Dim sLine
Do Until tsIn.AtEndOfStream
sLine = tsIn.ReadLine()
WScript.Echo "<", sLine
If "456," = Left(sLine, 4) Then
sLine = "789,""something else"""
End If
WScript.Echo ">", sLine
tsOut.WriteLine sLine
WScript.Echo
Loop
tsOut.Close
tsIn.Close
output:
type ..\data\46734115.csv
123,"Active"
456,"Not-Active"
999000123,"Active"
cscript 46734115-3.vbs
< 123,"Active"
> 123,"Active"
< 456,"Not-Active"
> 789,"something else"
< 999000123,"Active"
> 999000123,"Active"
type ..\data\46734115-2.csv
123,"Active"
789,"something else"
999000123,"Active"

Related

VBscript Replace text with part of filename

I have a directory of files that I want to Loop through and use part of their filename to replace text in a template doc.
For example one filename may be 'NV_AD32_city.dxf'. All files in the directory follow the same filename pattern of XX_XXXX_string.dxf, using two underscores.
I need to capture the string to the right of the first "_" and to the left of the "."so for this example that would be 'AD32_city'
How do I script to use capture that text of the active file to replace text in the template? I guess I need to create an object? But what is the object to use for the current file from a directory?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Thx for the replies, guys. After several days of trying your code I am just not "getting it". I understand it is set up to take the part of the filename's string that I want but how do I tell the script to use the current file I am looping through? Here is my script so far. I have your code on line 20 under the Sub 'GetNewInputs'
Set fso = CreateObject("Scripting.FileSystemObject")
Option Explicit
Dim WritePath : WritePath = "S:\TempFolder\"
Dim OutFile : OutFile = "VEG_DXF-2-SHP_script-"
Dim WorkingFile : WorkingFile = GetFileContent(SelectFile())
Dim NewState, NewSection, NewArea
Dim OldState, OldSection, OldArea
Call GetNewInputs()
Call GetOldInputs()
Sub GetNewInputs()
NewState = UCase(InputBox("INPUT STATE:", _
"INPUT STATE", "SOCAL"))
NewSection = ("Section_" & InputBox("INPUT SECTION NUMBER:", _
"INPUT SECTION", "14"))
NewArea = "^[^_]+_(.*)\.dxf$"
End Sub
Private Sub GetOldInputs()
OldState = "XX"
OldSection = "_X"
OldArea = "ZZZZ"
End Sub
Function SelectFile()
SelectFile = vbNullString
Dim objShell : Set objShell = WScript.CreateObject("WScript.Shell")
Dim strMSHTA : strMSHTA = "mshta.exe ""about:" & "<" & "input type=file id=FILE>" _
&"<" & "script>FILE.click();new ActiveXObject('Scripting.FileSystemObject')" _
&".GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);" & "<" & "/script>"""
SelectFile = objShell.Exec(strMSHTA).StdOut.ReadLine()
If SelectFile = vbNullString Then
WScript.Echo "No file selected or not a text file."
WScript.Quit
End If
End Function
Private Function GetFileContent(filePath)
Dim objFS, objFile, objTS
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFile = objFS.GetFile(filePath)
Set objTS = objFile.OpenAsTextStream(1, 0)
GetFileContent = objTS.Read(objFile.Size)
Set objTS = Nothing
End Function
For Each FileRefIn fso.GetFolder("S:\SOCAL\Section_14\Veg DXFs\").Files
NewFile = WorkingFile
NewFile = Replace(NewFile, OldState, NewState)
NewFile = Replace(NewFile, OldSection, NewSection)
NewFile = Replace(NewFile, OldArea, NewArea)
WriteFile NewFile, WritePath & OutFile & ".gms"
WScript.Echo NewArea
Next
Private Sub WriteFile(strLine,fileName)
On Error Resume Next
Dim objFSO, objFile
Set objFSO = CreateObject("Scripting.FileSystemObject")
Do Until IsObject(objFile)
Set objFile = objFSO.OpenTextFile(fileName, 8, True)
Loop
objFile.WriteLine strLine
objFile.Close
End Sub
Well, that’s actually two questions.
To enumerate files in a directory, you can use FileSystemObject, like this (untested)
const strFolderPath = "C:\Temp\Whatever"
set objFSO = CreateObject( "Scripting.FileSystemObject" )
set objFolder = objFSO.GetFolder( strFolderPath )
set colFiles = objFolder.Files
for each objFile in colFiles
' Do whatever you want with objFile
next
Here's the reference of those objects properties/methods.
And to extract portion of file names, you could use a regular expression.
Here’s some guide how to use'em in VBScript.
The following expression should work for you, it will capture the portion of that file names you asked for:
"^[^_]+_(.*)\.dxf$"
If you need to edit the content of the .dxf files, you will need to work within the AutoCAD VBA (Visual Basic for Applications) environment.
If that is the case, you will need to start with something like below:
GetObject("AutoCAD.Application.20")
CreateObject("AutoCAD.Application.20")
https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-ActiveX/files/GUID-0225808C-8C91-407B-990C-15AB966FFFA8-htm.html
** Please take note that "VBA is no longer distributed with the AutoCAD installation; it must be downloaded and installed separately. The VBA Enabler for Autodesk AutoCAD can be downloaded here."

VBScript: I want to take the contents of a file and run an UPDATE statement using the contents of each line

I have made a connection to a database. I want to take the contents of a file and run an UPDATE statement using the contents of each line.
Database Connection
Option Explicit
Dim sDir : sDir = "\\Server1\Data"
Dim sCS : sCS = Join(Array( _
"Provider=vfpoledb" _
, "Data Source=" & sDir _
, "Collating Sequence=general" _
), ";")
Dim oCN : Set oCN = CreateObject("ADODB.CONNECTION")
oCN.Open sCS
oCN.Close
File
STAD 1
SECA 2
..
UPDATE Statement
For this line:
STAD 1
It would run:
UPDATE B_SNAME.DBF SET SN_ANALSYS = 1 WHERE SN_ACCOUNT = STAD
I am extremely new to VBScript and DBF. I would have no problem writing a little Bash script to do this on our Linux side but here I am lost.
Please can someone provide some information on how I could do it, or even an example (that would be awesome)? :-)
If you separate the fields with one space or any single character (called a delimiter) you can use the split function to separate the fields. You will end up with something like this (I have not tested this)
Dim strSQL
Dim strFilename
Dim sConnString
Dim scs
Dim oCN
Dim oCmd
Dim fso
Dim f
strFilename = "C:\Temp\MyFile.txt"
sConnString = "Provider=vfpoledb;Data Source=\\Server1\Data;Collating Sequence=general;"
strSQL = "UPDATE B_SNAME.DBF SET SN_ANALSYS = p1 WHERE SN_ACCOUNT = p2"
Set oCN = CreateObject("ADODB.CONNECTION")
oCN.Open sConnString
Dim oCmd
Set oCmd = CreateObject("ADODB.Command")
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(strFilename)
Do Until f.AtEndOfStream
sArray = Split(f.ReadLine, " ")
oCmd.Parameters.Append oCmd.CreateParameter("p1", adChar, adParamInput, 4, sArray(1))
oCmd.Parameters.Append oCmd.CreateParameter("p2", adChar, adParamInput, 8, sArray(0))
oCmd.CommandText = strSQL
oCmd.Execute
Loop
f.Close
If oCN.State = 1 Then oCN.Close
Set oCmd = Nothing
Set oCN = Nothing
Most lines are delimited with either tabs or commas but there is no reason why you cannot use a space as long as it does not appear in your data.
Here is a simple example to read the data file and get each field into a variable. This assumes your data file contains a four character account name followed by five spaces and then a number.
Option Explicit
Const ForReading = 1
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim line
Dim sn_analsys
Dim sn_account
Dim dataFile
Set dataFile = fso.OpenTextFile("C:\SomeFolder\data.txt")
Do Until dataFile.AtEndOfStream
line = dataFile.ReadLine
sn_account = Left(line, 4)
sn_analsys = Mid(line, 10)
WScript.Echo "sn_account = " & sn_account
WScript.Echo "sn_analsys = " & sn_analsys
'
' Do whatever processing you need to do...
'
Loop
dataFile.Close
If you change the data file to separate the fields by one space, you can use Split to get each field.
Dim line
Dim fields
Dim dataFile
Set dataFile = fso.OpenTextFile("C:\SomeFolder\data.txt")
Do Until dataFile.AtEndOfStream
line = dataFile.ReadLine
fields = Split(line)
WScript.Echo "sn_account = " & fields(0)
WScript.Echo "sn_analsys = " & fields(1)
WScript.Echo
'
' Do whatever processing you need to do...
'
Loop

Read data from ini file

i have a vbscript that takes input file name
the code is
Dim tsout: Set tsout = gofs.CreateTextFile("C:\....csv")
Dim tsin: Set tsin = gofs.OpenTextFile("C:\.....csv")
how can i configure this so that path createTextFile(....) is read from config file(.ini)
the file path for creating and writing output-to, must be taken from ini file
this is my ini file
// my ini file
[Read_file]
tsout=E:.....tt.csv
tsin=E:\....gt.csv
[col]
Number1=4
Number2=5
A simple version of an .ini file parser:
Option Explicit
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
'WScript.Quit demoReadFile()
WScript.Quit demoReadIniFile()
Function demoReadFile()
demoReadFile = 0
Dim tsIn : Set tsIn = goFS.OpenTextFile(".\21825192.ini")
Do Until tsIn.AtEndOfStream
Dim sLine : sLine = tsIn.ReadLine()
WScript.Echo tsIn.Line - 1, sLine
Loop
tsIn.Close
End Function
Function demoReadIniFile()
demoReadIniFile = 0
Dim dicIni : Set dicIni = ReadIniFile(".\21825192.ini")
Dim sSec, sKV
For Each sSec In dicIni.Keys()
WScript.Echo "---", sSec
For Each sKV In dicIni(sSec).Keys()
WScript.Echo " ", sKV, "=>", dicIni(sSec)(sKV)
Next
Next
WScript.Echo dicIni("tsout")("Path")
End Function
Function ReadIniFile(sFSpec)
Dim dicTmp : Set dicTmp = CreateObject("Scripting.Dictionary")
Dim tsIn : Set tsIn = goFS.OpenTextFile(sFSpec)
Dim sLine, sSec, aKV
Do Until tsIn.AtEndOfStream
sLine = Trim(tsIn.ReadLine())
If "[" = Left(sLine, 1) Then
sSec = Mid(sLine, 2, Len(sLine) - 2)
Set dicTmp(sSEc) = CreateObject("Scripting.Dictionary")
Else
If "" <> sLine Then
aKV = Split(sLine, "=")
If 1 = UBound(aKV) Then
dicTmp(sSec)(Trim(aKV(0))) = Trim(aKV(1))
End If
End If
End If
Loop
tsIn.Close
Set ReadIniFile = dicTmp
End Function
output:
cscript 21825192.vbs
1 [pipapo]
2 Path=E:\dont\find\me.csv
3 Some = thing else
4
5 [tsout]
6 Path=E:\where\ever\output.csv
7 abc=def
cscript 21825192.vbs
--- pipapo
Path => E:\dont\find\me.csv
Some => thing else
--- tsout
Path => E:\where\ever\output.csv
abc => def
E:\where\ever\output.csv
(see this answer for background)
Update wrt comment/edit:
I added your sections to my sample .ini file:
type 21825192.ini
[pipapo]
Path=E:\dont\find\me.csv
Some = thing else
[tsout]
Path=E:\where\ever\output.csv
abc=def
[Read_file]
tsout=E:.....tt.csv
tsin=E:\....gt.csv
[col]
Number1=4
Number2=5
and - just for clarity - changed the final output line of my demoReadIniFile() function to:
WScript.Echo "tsout.Path", dicIni("tsout")("Path")
WScript.Echo "Read_file.tsin", dicIni("Read_file")("tsin")
WScript.Echo "col.Number2", dicIni("col")("Number2")
The output:
cscript 21825192.vbs
--- pipapo
Path => E:\dont\find\me.csv
Some => thing else
--- tsout
Path => E:\where\ever\output.csv
abc => def
--- Read_file
tsout => E:.....tt.csv
tsin => E:\....gt.csv
--- col
Number1 => 4
Number2 => 5
tsout.Path E:\where\ever\output.csv
Read_file.tsin E:\....gt.csv
col.Number2 5
So I don't understand at all why accessing 'the col section taking out number1=4 and Number2=5' causes any problems.
VBS do not support IniFile class. You need to create own parser of INI file. Other solution (also with creating own parsing functions, but much easy than to parse INI file): save TAB delimited data, for example: first comming OUTgoing file, than TAB char, than INcomming file.
Ekkehard's demo tweaked for Classic ASP:
Function demoReadIniFile()
demoReadIniFile = 0
Dim dicIni : Set dicIni = ReadIniFile("c:\path\to\21825192.ini")
Dim sSec, sKV
For Each sSec In dicIni.Keys()
response.write "---" & sSec & "<br>"
For Each sKV In dicIni(sSec).Keys()
response.write " " & sKV & " => " & dicIni(sSec)(sKV) & "<br>"
Next
Next
' response.write dicIni("tsout")("Path") & "<br>"
End Function
His ReadIniFile() works as written.

VBscript with lists

I am trying to write a VBScript which will read a text file and build a dictionary which contains lists. Let me explain with an example:
The input file would be a simple text file of the sort:
Male,Peter
Male,Chris
Male,Stewie
Male,Brian
Female,Lois
Female,Meg
When I run my script, I would like a dictionary with the first column as the key, and the second column as the values
{'Male':['Peter,Chris,Stewie,Brian']}
{'Female':['Lois,Meg']}
The lack of dynamic arrays or lists in VBScript is making this a real pain. Any suggestion how I might tackle this?
Cheers
VBScript can use the System.Collections.ArrayList class provided by the .NET framework.
Set d = CreateObject("Scripting.Dictionary")
d.Add "Male", CreateObject("System.Collections.ArrayList")
d.Add "Female", CreateObject("System.Collections.ArrayList")
d("Male").Add "Peter"
d("Male").Add "Chris"
'...
d("Female").Add "Lois"
d("Female").Add "Meg"
'...
For processing the input file take a look at the code provided by #Rich.
Just to say, I'm not compete with posted answers for repo-point ;)
If you can convert my post to comment, feel free to do that.
I like Ansgar's idea (+1) as it based on single Dictionary and that seems to me quite enough to get back easy what is stored inside.
The need of .Exists may come in use in 2 cases - (a) if we don't know how many genders we have, and (b) if we don't know how they looks like (pronunciation). The rest is similar to Ansgar's idea.
Option Explicit
Const cGender = 0
Const cName = 1
Dim sGender, sName, sLine
Dim oFSO, oFile, oDict
Dim arrLine
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oDict = CreateObject("Scripting.Dictionary")
Set oFile = oFSO.OpenTextFile("persons_list.txt")
Do Until oFile.AtEndOfStream
sLine = oFile.ReadLine
If Len(sLine) Then
arrLine = Split(sLine, ",")
sGender = arrLine(cGender)
sName = arrLine(cName)
If Not oDict.Exists(sGender) Then
oDict.Add sGender, CreateObject("System.Collections.ArrayList")
End If
oDict(sGender).Add sName
End If
Loop
oFile.Close
Set oFile = Nothing
Set oFSO = Nothing
WScript.Echo "Genders:" & oDict.Count, vbNewLine & Join(oDict.Keys)
Dim sKey
For Each sKey In oDict
WScript.Echo sKey, oDict(sKey).Count, vbNewLine & Join(oDict(sKey).ToArray())
Next
I'm not too familiar with the dictionary object, but this might suffice?
Set oFso = CreateObject("Scripting.FileSystemObject")
Set oDictionary = CreateObject("Scripting.Dictionary")
Const cGender = 0
Const cName = 1
Set oFile = oFso.OpenTextFile ("yourfile.txt", 1)
Do Until oFile.AtEndOfStream
sLine = oFile.Readline
If sLine <> "" Then
arrLine = split(sLine,",")
oDictionary.Add arrLine(cGender,0), arrLine(cName,0) 'hope i got these indexes the right way round
'or
oDictionary.Add arrLine(cGender), arrLine(cName) 'if its one dimentional
End If
Loop
As #Rich approach is faulty (-1) - you can't .Add a key twice and if you could, the names would be overwritten, not appended - and Ansgar's good idea (+1) is not really production ready without a hint wrt its practical use:
Const cGender = 0
Const cName = 1
Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject")
Dim dicDic : Set dicDic = CreateObject("Scripting.Dictionary")
Dim dicAl : Set dicAl = CreateObject("Scripting.Dictionary")
Dim dicCnt : Set dicCnt = CreateObject("Scripting.Dictionary")
Dim oFile, sLine, arrLine
Set oFile = oFS.OpenTextFile ("so14479571.txt")
Do Until oFile.AtEndOfStream
sLine = oFile.Readline()
If sLine <> "" Then
arrLine = Split(sLine,",")
dicCnt(arrLine(cGender)) = dicCnt(arrLine(cGender)) + 1
If Not dicDic.Exists(arrLine(cGender)) Then
Set dicDic(arrLine(cGender)) = CreateObject("Scripting.Dictionary")
End If
dicDic(arrLine(cGender))(arrLine(cName)) = Empty
If Not dicAl.Exists(arrLine(cGender)) Then
Set dicAl(arrLine(cGender)) = CreateObject("System.Collections.ArrayList")
End If
dicAl(arrLine(cGender)).Add arrLine(cName)
End If
Loop
Dim sKey, sKey2
WScript.Echo "genders:"
For Each sKey In dicCnt
WScript.Echo "", sKey, dicCnt(sKey)
Next
WScript.Echo "dic:"
For Each sKey In dicDic
WScript.Echo "", sKey
For Each sKey2 In dicDic(sKey)
WScript.Echo " ", sKey2
Next
Next
WScript.Echo "AL:"
For Each sKey In dicAl
WScript.Echo "", sKey & ":", Join(dicAl(sKey).ToArray())
Next
output:
genders:
Male 4
Female 2
dic:
Male
Peter
Chris
Stewie
Brian
Female
Lois
Meg
AL:
Male: Peter Chris Stewie Brian
Female: Lois Meg
The script should show:
How you can use assignment without .Exists for 'simple' values that can be autovivified (here a number)
That you need an .Exists check for values like Arrays, ArrayLists, or Dictionaries

ASP/VB Classic clear a line from a file

I have a file that looks like this:
Alpha,25,SomeBrand,Info
Gamma,2039,Crisps,Foobar
Epic,240,Win,Post
And I want to clear a certain line in this file, say line 2, so that it looks like this:
Alpha,25,SomeBrand,Info
Epic,240,Win,Post
How can I efficiently do this? This file has over 18000 lines, and I've tried reading in the complete file and writing back, but it was way too slow.
I don't know what is your file size but i've written a script (asp) is executed within 2.5 seconds.
Text file size is 35 million bytes and it has 35,000 lines.
Here:
<%#Language = VBScript %>
<%
Option Explicit
Dim oFso, oFile, arrLns, arrLNums, strOut, e
arrLNums = Array(15) '15th [and nnth] line(s) will be cleared
Set oFso = CreateObject("Scripting.FileSystemObject")
Set oFile = oFso.OpenTextFile("C:\old.txt", 1)
strOut = Replace(oFile.ReadAll(), vbCr, "")
arrLns = Split(strOut, vbLf)
For Each e In arrLNums : arrLns(e - 1) = "" : Next
strOut = Join(arrLns, vbCrLf)
oFso.CreateTextFile("C:\cleared.txt", True)_
.Write(strOut) 'Saved
oFile.Close
Set oFile = Nothing
Set oFso = Nothing
%>
As you can't use file pointer moving tricks to change the file 'on disk' in VBScript, you'll have to re-write it. Did you test whether using .ReadAll() and .Write is 'fast enough' for you? If yes, we could discuss a way to do the modifying efficiently. First question: Do you want to delete the offending line, or should it be replaced with an empty one?
Next Step:
This VBScript code:
Dim goFS : Set goFS = CreateObject( "Scripting.FileSystemObject" )
Dim sDir : sDir = "..\testdata\editlargefile"
Dim sSrcFSpec : sSrcFSpec = goFS.BuildPath( sDir, "lines.txt" )
Dim nLine : nLine = 5
Dim nSize : nSize = goFS.GetFile( sSrcFSpec ).Size
WScript.Echo nSize, "bytes in", sSrcFSpec
ReDim aHead( nLine - 2 )
Dim oTS, nIdx, sTail
Set oTS = goFS.OpenTextFile( sSrcFSpec )
For nidx = 0 To UBound( aHead )
aHead( nIdx ) = oTS.ReadLine()
Next
oTS.ReadLine
sTail = oTS.ReadAll()
oTS.Close
WScript.Echo Left( Join( aHead, vbCrLf ) & vbCrLf & vbCrLf & Left( sTail, 100 ), 150 )
Set oTS = goFS.CreateTextFile( sSrcFSpec, True )
oTS.Write Join( aHead, vbCrLf )
oTS.Write vbCrLf & vbCrLf
oTS.Write sTail
oTS.Close
output:
20888896 bytes in ..\testdata\editlargefile\lines.txt
This is line 1
This is line 2
This is line 3
This is line 4
This is line 6
This is line 7
This is line 8
This is line 9
This is line 10
Thi
=====================================================
xplfs.vbs: Erfolgreich beendet. (0) [11.42188 secs]
demonstrates the fastest VBScript way I can think of. The pseudo code
for a language able to do file pointer tricks would be
Open the file in read+write mode
Loop over the head lines to keep
If Delete
Skip line to delete
Reset write file pointer to end of previous line
Block write to file pointer till end
Else
Fill line to delete with spaces
End
Close the file
What language do you plan to use?

Resources