I am importing a series of CSV files into Access tables. I have the following line that imports each file:
DoCmd.TransferText acImportDelim, , FN, F.Path, True
This import statement works and creates the necessary table. However, it creates the field types from the data, and depending on the first few rows of the data it may create a field as numeric that should be text - and then causes an error when it encounters a text value later in the file.
How can I force the field type to Text for every field in the input file? I've used Import Specifications before, but first the file format (provided by others outside my control) may change from time to time, and second it's a very "wide" file with 200+ column, so this isn't a practical answer.
This is not a great workaround, but I had to go through the process anyway to get around the 255 field limit in tables. In short, the import steps I ended up with are
Read the 1st line of the file as an inputstream
Split the line to get the field names, put them in a data dictionary table and then manually mark the ones I want to import
Use CREATE TABLE to create a new data table (selected fields only) with all of the fields set to TEXT
Read each line of the file as an inputstream
Split the line to get the data for each field
Use INSERT INTO to add the selected fields to the data table
Cumbersome, but it solves both problems - I'm not limited to 255 fields in the input files and I can control the data type of the fields as I create them.
The code, if anyone cares, is
Function Layout()
Set db = CurrentDb()
Folder = DLookup("[data folder]", "folder")
Dim FSO As New FileSystemObject
Set flist = FSO.GetFolder(Folder).Files
db.Execute ("delete * from [data dictionary]")
For Each F In flist
FN = Left(F.Name, InStr(F.Name, ".") - 1)
FT = Mid(F.Name, InStr(F.Name, ".") + 1)
If FT <> "csv" Then GoTo Skip
If TestFile(F.path) = "ASCII" Then
Set instream = FSO.OpenTextFile(F.path, ForReading, , 0)
Else: Set instream = FSO.OpenTextFile(F.path, ForReading, , -1)
End If
header = instream.ReadLine
Data = Split(header, ",")
For i = LBound(Data) To UBound(Data)
SQL = "insert into [data dictionary] ([table], [field], [index]) select "
SQL = SQL & "'" & FN & "','" & Data(i) & "','" & i & "'"
db.Execute SQL
Next i
Skip: Next F
End Function
Function TestFile(ByVal path As String)
Dim buffer As String
Dim InFileNum As Integer
Dim firstByte As Integer
Dim secondByte As Integer
Dim thirdByte As Integer
buffer = String(100, " ")
InFileNum = FreeFile
Open path For Binary Access Read As InFileNum
Get InFileNum, , buffer
Close InFileNum
firstByte = Asc(Mid(buffer, 1, 1))
secondByte = Asc(Mid(buffer, 2, 1))
thirdByte = Asc(Mid(buffer, 3, 1))
If (firstByte = 255 And secondByte = 254) Then
TestFile = "Unicode"
ElseIf (firstByte = 254 And secondByte = 255) Then
TestFile = "Unicode"
ElseIf (firstByte = 239 And secondByte = 187 And thirdByte = 191) Then
TestFile = "Unicode"
Else
TestFile = "ASCII"
End If
End Function
Function import()
Folder = DLookup("[data folder]", "folder")
Set db = CurrentDb()
Dim FSO As New FileSystemObject
Set Tlist = db.OpenRecordset("select [table] from [data dictionary] where ([required]<>'') group by [table]")
Tlist.MoveFirst
Do While Not Tlist.EOF
TN = Tlist.Fields("table").Value
Delete_table (TN)
Set flist = db.OpenRecordset("select * from [data dictionary] where [required]<>'' and [table]='" & TN & "'")
flist.MoveFirst
Text = ""
Do While Not flist.EOF
FN = flist.Fields("Field")
Text = Text & "," & FN & " " & IIf(InStr(FN, "Date") > 0 Or InStr(FN, "_DT") > 0, "DATETIME", "TEXT")
flist.MoveNext
Loop
SQL = "CREATE TABLE " & TN & "(" & Mid(Text, 2) & ")"
db.Execute SQL
path = Folder & "\" & TN & ".csv"
If TestFile(path) = "ASCII" Then
Set instream = FSO.OpenTextFile(path, ForReading, , 0)
Else: Set instream = FSO.OpenTextFile(path, ForReading, , -1)
End If
header = instream.ReadLine
Do While Not instream.AtEndOfStream
Line = parser(instream.ReadLine)
Data = Split(Line, ",")
flist.MoveFirst
Text = ""
Do While Not flist.EOF
n = flist.Fields("index").Value
Text = Text & ",'" & Data(n) & "'"
flist.MoveNext
Loop
SQL = "insert into [" & TN & "] values(" & Mid(Text, 2) & ")"
db.Execute SQL
Loop
Tlist.MoveNext
Loop
x = MultipleCodes()
MsgBox ("done")
End Function
Function parser(S)
parser = S
i = InStr(S, Chr(34))
If i = 0 Then
parser = S
Else
j = InStr(i + 1, S, Chr(34))
T = Mid(S, i + 1, j - i - 1)
T = Replace(T, ",", ";")
parser = Left(S, i - 1) & T & parser(Mid(S, j + 1))
End If
End Function
Related
I'm currently enhancing a system using vb.net. My issue is, i need to display a column name 'WONOTE' (datatype TEXT) from SQL Server into div in html front screen. The maximum length of characters for this column is up to 22 000 characters. I retrieved the data from SQL server into div by using sql command in code behind. I manage to display the data but only up to 110 characters by using this statement 1:
REPLACE(REPLACE(cast(WONOTE as varchar(110)), CHAR(13), ''), CHAR(10), '')
and up to 10 characters using this statement 2:
CONVERT(VARCHAR(10), b.WONOTE) as WONOTE
but I need it to display full text. If i change into varchar(max) or anything greater than 110 for statement 1 and 10 for statement 2 it display nothing.
I wish someone can help me with it.
Thank you in advance.
How i retrieved data from SQL server:
Public Sub GETWHATSRUNNING()
Dim paraWC As SqlParameter
Dim SQL As String
Dim myArray, myArray1, myArray2, myArray3,
myArray4, myArray5, myArray6, myArray7,
myArray8, myArray9, myArray10 As String
TempDT.Columns.Add("WO", GetType(String))
TempDT.Columns.Add("WOQTY", GetType(String))
TempDT.Columns.Add("PartNum", GetType(String))
TempDT.Columns.Add("Desc", GetType(String))
TempDT.Columns.Add("WIPQTY", GetType(String))
TempDT.Columns.Add("WIPDAYS", GetType(String))
TempDT.Columns.Add("WOAGING", GetType(String))
TempDT.Columns.Add("AGINGATWC", GetType(Double))
TempDT.Columns.Add("COLOR", GetType(String))
'TempDT.Columns.Add("WO_NOTE", GetType(String))
WCLimit = 5
SQL = "select distinct A.WONO, B.BLDQTY , C.PART_NO , C.DESCRIPT, B.Start_Date, REPLACE(REPLACE(cast(WONOTE as varchar(110)), CHAR(13), ''), CHAR(10), '') " & _
"from Transfer A " & _
"left join WOENTRY B on A.wono = B.wono " & _
"left join INVENTOR C on B.UNIQ_KEY = C.UNIQ_KEY " & _
"where FR_DEPT_ID = #WC and start_date is not null " & _
"and B.BLDQTY <> B.COMPLETE "
GetConnection()
oConnSql = New SqlConnection(connString.ToString)
oCmdSql = New SqlCommand(SQL, oConnSql)
paraWC = New SqlParameter("#WC", SqlDbType.VarChar, 5)
paraWC.Value = lblWC.Text
oCmdSql.Parameters.Add(paraWC)
oCmdSql.CommandTimeout = 7200
Try
If oConnSql.State = ConnectionState.Closed Then
oConnSql.Open()
End If
' Adapter and Dataset
oAdptSql.SelectCommand = oCmdSql
oAdptSql.Fill(oDS, "dtList")
oAdptSql.Fill(dt)
If dt.Rows.Count > 0 Then
Dim ProgessQty, WIPQty, WOQuantity As String
Dim AgingWC, WOAging As Double
'Dim WCAge, WoAge As TimeSpan
Dim LeadTime As Double
Dim Holiday As Integer
Dim counter As Integer = 1
Dim count As Integer = dt.Rows.Count - 1
For i = 0 To count - 1
ProgessQty = GETProgressWOQuantity(Trim(dt.Rows(i)(0).ToString))
WOQuantity = Trim(dt.Rows(i)(1).ToString)
WIPQty = CInt(ProgessQty)
LeadTime = GetLeadTime(Trim(dt.Rows(i)(2).ToString), lblWC.Text)
Holiday = CheckForHolidays(CDate(dt.Rows(i)(4).ToString), Now())
WOAging = Format((DateDiff(DateInterval.Minute, CDate(dt.Rows(i)(4).ToString), Now())) / 60 / 24, "0.0") - Holiday
AgingWC = WOAging - LeadTime
If AgingWC >= 5 And WIPQty > 0 Then
TempDT.Rows.Add(Trim(dt.Rows(i)(0).ToString), WOQuantity, Trim(dt.Rows(i)(2).ToString), Trim(dt.Rows(i)(3).ToString), WIPQty, Trim(dt.Rows(i)(5).ToString), Math.Round(CDbl(WOAging), 2), Math.Round(CDbl(AgingWC), 2), IIf(Math.Round(CDbl(AgingWC), 2) >= WCLimit, "Red", "Black"))
'
counter += 1
Else
End If
Next
Dim dataView As New DataView(TempDT)
dataView.Sort = " AGINGATWC DESC"
SortDT = dataView.ToTable()
For j = 0 To SortDT.Rows.Count - 1
myArray = myArray & "|" & j + 1
myArray1 = myArray1 & "|" & Trim(SortDT.Rows(j)(0).ToString) 'WO
myArray2 = myArray2 & "|" & Trim(SortDT.Rows(j)(1).ToString) 'WO QTY
myArray3 = myArray3 & "|" & Trim(SortDT.Rows(j)(2).ToString) 'Part Number
myArray4 = myArray4 & "|" & Trim(SortDT.Rows(j)(3).ToString) 'Description
myArray5 = myArray5 & "|" & Trim(SortDT.Rows(j)(4).ToString) 'WIP QTY
myArray6 = myArray6 & "|" & Trim(SortDT.Rows(j)(5).ToString) 'WIP DAYS
myArray7 = myArray7 & "|" & Trim(SortDT.Rows(j)(6).ToString) 'WO Aging
myArray8 = myArray8 & "|" & Trim(SortDT.Rows(j)(7).ToString) 'Aging at WC
myArray9 = myArray9 & "|" & Trim(SortDT.Rows(j)(8).ToString) 'Color
myArray10 = myArray10 & "|" & Trim(SortDT.Rows(j)(5).ToString) 'WONOTE
Next
dt.Clear()
dt.Dispose()
oCmdSql.Dispose()
oConnSql.Close()
ViewState.Clear()
ViewState("JArray") = myArray
ViewState("JArray1") = myArray1
ViewState("JArray2") = myArray2
ViewState("JArray3") = myArray3
ViewState("JArray4") = myArray4
ViewState("JArray5") = myArray5
'ViewState("JArray6") = myArray6
ViewState("JArray7") = myArray7
ViewState("JArray8") = myArray8
ViewState("JArray9") = myArray9
ViewState("JArray10") = myArray10
End If
Catch ex As Exception
lblResult.Text = "Exception Message: " + ex.Message
Finally
End Try
End Sub
Now I realised if I run in Internet Explorer with varchar(max) it says
I am using VBA in Access to modify a excel sheet using Macro 1 and input it in a table using Macro 2. When I run both of these consecutively, my system gets stuck in a loop, but works fine if I restart the Microsoft access application after running one Macro and run Macro 2. Also at times, the excel file on which I am running my code gets a pop-up box to enable read/write access.. Can someone help me with it?
Macro1
Function Clean()
Dim CurrFilePath, PathName, Week As String
Dim Filename
Dim OpenExcel As Object
Set OpenExcel = CreateObject("Excel.Application")
OpenExcel.Visible = False
Dim OpenWorkbook, WS As Object
Dim i, j As Integer
Dim Count_WS As Integer
OpenExcel.Quit
CurrFilePath = Application.CurrentProject.path
StartTime = Timer
Week = InputBox("Enter the week for the data import e.g. 34")
PathName = CurrFilePath & "\Direct Deliveries\Week " & Week & "\"
Example = CurrFilePath & "\Direct Deliveries\Week " & Week
Confirm:
Confirm_Folder = MsgBox("Does the Direct Deliveries info exist in " & PathName & " path", vbYesNo)
If Confirm_Folder = vbNo Then
path = InputBox("Locate Direct Deliveries .xlsx on your System and Copy the Dir path here e.g." & Example)
PathName = path & "\"
GoTo Confirm
End If
Filename = Dir(PathName & "*.xlsx")
Do While Len(Filename) > 0
Set OpenExcel = CreateObject("Excel.Application")
OpenExcel.Visible = False
OpenExcel.EnableEvents = False
OpenExcel.ScreenUpdating = False
'Variables to track first cell
i = 0
j = 0
PathFile = PathName & Filename
Set OpenWorkbook = OpenExcel.Workbooks.Open(PathFile)
For Each WS In OpenWorkbook.Worksheets
'If condition to check correct worksheets
On Error Resume Next
If Range("A1").Value = "Carrier SCAC" And Range("D1").Value = "Trip ID" Then
'Loop to fill blank TripIDs
For Each Cell In WS.UsedRange.Columns(4).Cells
' For blank cells, set them to equal the cell above
If WS.Cells(Cell.Row, 1) <> "ABCD" And Not IsEmpty(WS.Cells(Cell.Row, 9)) Then
If i <> 0 Then
If (Len(Cell.Text) = 0) And PreviousCell <> "Trip ID" And Cell.Row Then
Cell.Value = PreviousCell
End If
End If
PreviousCell = Cell
i = i + 1
End If
Next Cell
'Loop to fill blank SCAC Codes
For Each CarrierCell In WS.UsedRange.Columns(1).Cells
' For blank cells, set them to equal the cell above
If j <> 0 Then
If (Len(CarrierCell.Text) = 0) And PreviousCell <> "Carrier SCAC" And PreviousCell <> "ABCD" And Not IsEmpty(WS.Cells(CarrierCell.Row, 4)) Then
CarrierCell.Value = PreviousCell
End If
End If
PreviousCell = CarrierCell
j = j + 1
Next CarrierCell
End If
Count_WS = Count_WS + 1
Next WS
Filename = Dir()
OpenWorkbook.Close SaveChanges:=True
Set OpenWorkbook = Nothing
OpenExcel.Quit
Set OpenExcel = Nothing
Loop
'Display the end status
TotalTime = Format((Timer - StartTime) / 86400, "hh:mm:ss")
Application.Echo True
DeleteImportErrTables
End Function
Macro 2
'--------------------------------------------------------
' Author: Akanksha Goel
' The code imports Direct Deliveries erroneous excel templates to Access Database
'------------------------------------------------------------
'
'------------------------------------------------------------
Function ListErrBeforeImports()
Dim OpenExcel As Object
Set OpenExcel = CreateObject("Excel.Application")
OpenExcel.Visible = False
Dim PathFile As String, Filename As String, PathName As String
Dim TableName As String
Dim HasFieldNames As Boolean
Dim OpenWorkbookED As Object
Dim SQL, CurrFilePath As String
Dim SQLcreate, SQLAlter, SQLSet As String
Dim SQL2, SQL3 As String
Dim Count_Templates As Integer
StartTime = Timer
OpenExcel.Quit
'Turn Off the warnings and screen updating
DoCmd.SetWarnings False
Application.Echo False
OpenExcel.EnableEvents = False
OpenExcel.ScreenUpdating = False
CurrFilePath = Application.CurrentProject.path
Week = InputBox("Enter the week for the data import e.g. 34")
PathName = CurrFilePath & "\Direct Deliveries\Week " & Week & "\"
Example = CurrFilePath & "\Direct Deliveries\Week " & Week
Confirm:
Confirm_Folder = MsgBox("Does the Direct Deliveries info exist in " & PathName & " path", vbYesNo)
If Confirm_Folder = vbNo Then
path = InputBox("Locate Direct Deliveries .xlsx on your System and Copy the Dir path here e.g." & Example)
PathName = path & "\"
GoTo Confirm
End If
HasFieldNames = True
TableName = "TempTable"
Filename = Dir(PathName & "*.xlsx")
PathFile = PathName & Filename
'Arguments for function AssignTablesToGroup()
Dim Arg1 As String
Dim Arg2 As Integer
Arg1 = "EmptyDeliveryDates_TripsWeek" & Week
Call DeleteTable(Arg1)
Arg2 = 383
SQLcreate = "Create Table EmptyDeliveryDates_TripsWeek" & Week & " ( TripID Text, ShipToZip Text, ArriveDelivery Text, Carrier Text, SourceWorkbook Text);"
DoCmd.RunSQL SQLcreate
'Assign Error Table to 'Errors in DirectDeliveries Excels' Group
Call AssignToGroup(Arg1, Arg2)
'Arguments for function AssignTablesToGroup()
Dim Arg3 As String
Arg3 = "InvalidZip_TripsWeek" & Week
DeleteTable Arg3
Arg2 = 383
SQLcreate = "Create Table InvalidZip_TripsWeek" & Week & " ( TripID Text, ShipToZip Text, ArriveDelivery Text, Carrier Text, SourceWorkbook Text);"
DoCmd.RunSQL SQLcreate
'Assign Error Table to 'Errors in DirectDeliveries Excels' Group
Call AssignToGroup(Arg3, Arg2)
'Arguments for function AssignTablesToGroup()
Dim Arg4 As String
Arg4 = "InvalidTrip_TripsWeek" & Week
DeleteTable Arg4
Arg2 = 383
SQLcreate = "Create Table InvalidTrip_TripsWeek" & Week & " ( TripID Text, ShipToZip Text, ArriveDelivery Text, Carrier Text, SourceWorkbook Text);"
DoCmd.RunSQL SQLcreate
'Assign Error Table to 'Errors in DirectDeliveries Excels' Group
Call AssignToGroup(Arg4, Arg2)
Do While Len(Filename) > 0
Set OpenExcel = CreateObject("Excel.Application")
OpenExcel.Visible = False
OpenExcel.EnableEvents = False
OpenExcel.ScreenUpdating = False
PathFile = PathName & Filename
Set OpenWorkbookED = OpenExcel.Workbooks.Open(PathFile, ReadOnly)
Set WS_Book = OpenWorkbookED.Worksheets
DeleteTable "TempTable"
'Loop through Worksheets in each template workbook
For Each WS In WS_Book
WorksheetName = WS.Name
x = WS.Range("A1")
If WS.Range("A1") = "Carrier SCAC" Then
'Get the used records in worksheet
GetUsedRange = WS.UsedRange.Address(0, 0)
'Import records from worksheet into Access Database table
DoCmd.TransferSpreadsheet acImport, 10, "TempTable", PathFile, HasFieldNames, WorksheetName & "!" & GetUsedRange
SQLAlter = "ALTER TABLE TempTable ADD COLUMN SourceBook TEXT(100)"
DoCmd.RunSQL SQLAlter
SQLSet = "UPDATE TempTable SET TempTable.SourceBook = '" & Filename & "' where ([Arrive Delivery]) is NULL or len([Arrive Delivery])<2 or len([Trip ID])<8 or len([Ship to Zip])<5;"
DoCmd.RunSQL SQLSet
SQL = "INSERT INTO " & Arg4 & "(TripID, ShipToZip, ArriveDelivery, Carrier, SourceWorkbook) Select Distinct [Trip ID], [Ship to Zip], [Arrive Delivery], [Carrier SCAC], SourceBook FROM TempTable WHERE len([Trip ID])<8 and len([Ship To Zip])>0 and len([Arrive Delivery])>0;"
DoCmd.RunSQL SQL
SQL2 = "INSERT INTO " & Arg3 & "(TripID, ShipToZip, ArriveDelivery, Carrier, SourceWorkbook) Select Distinct [Trip ID], [Ship to Zip], [Arrive Delivery], [Carrier SCAC], SourceBook FROM TempTable WHERE len([Ship To Zip])<5 and len([Arrive Delivery])>0 and len([Trip ID])>0;"
DoCmd.RunSQL SQL2
SQL3 = "INSERT INTO " & Arg1 & "(TripID, ShipToZip, ArriveDelivery, Carrier, SourceWorkbook) Select Distinct [Trip ID], [Ship to Zip], [Arrive Delivery], [Carrier SCAC], SourceBook FROM TempTable WHERE ([Arrive Delivery] is NULL or len([Arrive Delivery])<2) and len([Ship To Zip])>0 and len([Trip ID])>0 ;"
DoCmd.RunSQL SQL3
DoCmd.DeleteObject acTable, "TempTable"
Count_Templates = Count_Templates + 1
End If
Next WS
OpenWorkbookED.Saved = True
OpenWorkbookED.Close
Filename = Dir()
Set OpenWorkbookED = Nothing
OpenExcel.Quit
Set OpenExcel = Nothing
Loop
'Display the end status
TotalTime = Format((Timer - StartTime) / 86400, "hh:mm:ss")
MsgBox "Done! Error tables updated in 'Errors in DirectDeliveries Excels' group in with " & Count_Templates & " Templates " & TotalTime & " minutes", vbInformation
Application.Echo True
'CallFunction Delete Import Tables
DeleteImportErrTables
End Function
Merge the two functions so you only open one instance (your OpenExcel object) of Excel.
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
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.
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.