I have a piece of VBA code written that allows user to export table to CSV format (comma separated). Unfortunately one of the columns includes commas in values what breaks the structure when user separating columns by delimiter in excel.
I would not like to write anything from scratch so I was trying and looking for some ways to incorporate text identifiers into my code, but unfortunately found nothing.
Sub save_to_csv()
'Defininf variables
Dim tbl As ListObject
Dim ws As Worksheet
Dim csvFilePath As String
Dim fNum As Integer
Dim tblArr
Dim rowArr
Dim csvVal
Dim row
Dim Fldr As String
Dim CurrTS As String
Set ws = Worksheets("Slot_booking_table")
Set objList = ws.ListObjects("Slot_booking_table")
'Current timestamp variable to identify saved CSV files
CurrTS = CStr(Format(DateTime.Now, "yyyy_MM_dd_hh_mm_ss"))
'File dialog to select location where CSV file should be saved
With Application.FileDialog(4)
.AllowMultiSelect = False
.Title = "Select location to save CSV file"
If .Show <> -1 Then Exit Sub
Fldr = .SelectedItems(1)
End With
'Generating CSV file name
csvFilePath = Fldr & "\slot_booking_" & CurrTS & ".csv"
'Loading table to two-dimensional array
tblArr = objList.Range.Value
'Loop for joining each row from array by delimiter
fNum = FreeFile()
Open csvFilePath For Output As #fNum
For i = 1 To UBound(tblArr)
rowArr = Application.Index(tblArr, i, 0)
csvVal = VBA.Join(rowArr, ",")
Print #1, csvVal
Next
Close #fNum
MsgBox "CSV file has been generated. Please check the selected location."
Set tblArr = Nothing
Set rowArr = Nothing
Set csvVal = Nothing
End Sub
I tried to add For Each loop but it does not help:
Sub save_to_csv()
'Defininf variables
Dim tbl As ListObject
Dim ws As Worksheet
Dim csvFilePath As String
Dim fNum As Integer
Dim tblArr
Dim rowArr
Dim csvVal
Dim row
Dim Fldr As String
Dim CurrTS As String
Set ws = Worksheets("Slot_booking_table")
Set objList = ws.ListObjects("Slot_booking_table")
'Current timestamp variable to identify saved CSV files
CurrTS = CStr(Format(DateTime.Now, "yyyy_MM_dd_hh_mm_ss"))
'File dialog to select location where CSV file should be saved
With Application.FileDialog(4)
.AllowMultiSelect = False
.Title = "Select location to save CSV file"
If .Show <> -1 Then Exit Sub
Fldr = .SelectedItems(1)
End With
'Generating CSV file name
csvFilePath = Fldr & "\slot_booking_" & CurrTS & ".csv"
'Loading table to two-dimensional array
tblArr = objList.Range.Value
'Loop for joining each row from array by delimiter
fNum = FreeFile()
Open csvFilePath For Output As #fNum
For i = 1 To UBound(tblArr)
rowArr = Application.Index(tblArr, i, 0)
For Each row In rowArr
row = """ & row & """
Next row
csvVal = VBA.Join(rowArr, ",")
Print #1, csvVal
Next
Close #fNum
MsgBox "CSV file has been generated. Please check the selected location."
Set tblArr = Nothing
Set rowArr = Nothing
Set csvVal = Nothing
End Sub
Is there a way to incorporate line with adding text identifier into my code without changing the part of code with joining arrays by delimiter?
It might help to use write instead of print
The documentation to write states:
Unlike the Print # statement, the Write # statement inserts commas
between items and quotation marks around strings as they are written
to the file.
Please, try replacing this part of your code:
Open csvFilePath For Output As #fNum
For i = 1 To UBound(tblArr)
rowArr = Application.Index(tblArr, i, 0)
For Each row In rowArr
row = """ & row & """
Next row
csvVal = VBA.Join(rowArr, ",")
Print #1, csvVal
Next
Close #fNum
with this one:
Dim j As Long, strLine As String, strText As String 'the other variables were declared already...
For i = 1 To UBound(tblArr)
For j = 1 To UBound(tblArr, 2)
strLine = strLine & Chr(34) & tblArr(i, j) & Chr(34) & "," 'build the line string
Next
strLine = left(strLine, Len(strLine) - 1) & vbCrLf 'replace the last comma with end of line
strText = strText & strLine 'add the line to the whole string to be used
strLine = "" 'reinitialize the line variable
Next i
strText = left(strText, Len(strText) - 1) 'replace the ending end of line
fNum = FreeFile()
Open csvFilePath For Output As #fNum
Print #fNum, strText 'place the string at once
Close #fNum
I've managed to piece together this VBA which takes data from excel and turns it into .txt flat file. It works exactly as I need, but I would like to alter it so that the end result is saved as Unicode as opposed to ANSI.
I've done some reading and the answer I keep coming back to is to use FileSystemObject. I found a VBA on here that does the job perfectly, but I can't for the life of me work out how to incorporate it into my existing code. Any chance someone could throw me some pointers?
This is my current code:
' Defines everything first. So, from B2, across and down.
LastRow = Sheets("Pricing").Range("B" & Rows.Count).End(xlUp).Row
LastColumn = Sheets("Pricing").Cells(2, Columns.Count).End(xlToLeft).Column
' File name, path to save to and delimiter.
file = Sheets("Pricing").TextBox1 & ".txt"
If TextBox1.Value = "" Then MsgBox "What we calling it genius?", vbQuestion
If TextBox1.Value = "" Then Exit Sub
Path = "C:\Users\me.me\Desktop\Files\"
Delimeter = "|"
' The magic bit.
myFileName = Path & file
FN = FreeFile
Open myFileName For Output As #FN
For Row = 2 To LastRow
For Column = 2 To LastColumn
If Column = 2 Then Record = Trim(Cells(Row, Column)) Else Record = Record & Delimeter & Trim(Cells(Row, Column))
Next Column
Print #FN, Record
Next Row
Close #FN
MsgBox "BOOM! LOOKIT ---> " & myFileName
' Opens the finished file.
Dim fso As Object
Dim sfile As String
Set fso = CreateObject("shell.application")
sfile = "C:\Users\me.me\Desktop\Files\" & Sheets("Pricing").TextBox1 & ".txt"
fso.Open (sfile)
And this is what I've been trying to incorporate (HUGE thanks to MarkJ for posting this on another question):
Dim fso As Object, MyFile As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set MyFile = fso.CreateTextFile("c:\testfile.txt", False,True) 'Unicode=True'
MyFile.WriteLine("This is a test.")
MyFile.Close
I just can't get it to work.
Please, test the next code. You did not answer my clarification question, but it works using the above comment assumptions. It take the file name, from an activeX text box situated on the sheet to be processed. The code should be faster than yours for big ranges, avoiding to iterate between all cells:
Sub SaveAsUnicode()
Dim shP As Worksheet, iRow As Long, Record As String, Delimeter As String
Dim file As String, myFileName As String, path As String, txtB As MSForms.TextBox
Dim rng As Range, lastCell As Range, arr, arrRow
Dim fso As Object, MyFile As Object, shApp As Object
Set shP = Worksheets("Pricinig")
Set txtB = shP.OLEObjects("TextBox1").Object 'it sets an activeX sheet text box
file = txtB.Text & ".txt"
If txtB.value = "" Then MsgBox "What we calling it genius?", vbQuestion: Exit Sub
Set lastCell = shP.cells.SpecialCells(xlCellTypeLastCell) 'last cell of the sheet
Set rng = shP.Range("A2", lastCell) 'create the range to be processed
arr = rng.value 'put the range in an array
path = "C:\Users\me.me\Desktop\Files\" 'take care to adjust the path!
myFileName = path & file
Delimeter = "|"
Set fso = CreateObject("Scripting.FileSystemObject")
Set MyFile = fso.CreateTextFile(myFileName, False, True) 'open the file to write Unicode:
For iRow = 1 To UBound(arr) 'itereate between the array rows
arrRow = Application.Index(arr, iRow, 0) 'make a slice of the currrent arrray row
Record = Join(arrRow, Delimeter) 'join the iD obtained array, using the set Delimiter
MyFile.WriteLine (Record) 'write the row in the Unicode file
Next iRow
MyFile.Close 'close the file
'open the obtained Unicode file:
Set shApp = CreateObject("shell.application")
shApp.Open (myFileName)
End Sub
I tested the above code on a sheet using characters not supported in ANSI and it works as expected.
Please, send some feedback after testing it, or if my assumptions after reading your question are not correct...
#FaneDuru, this is what I ended up putting together, it's working great for me. Thanks again for all of your help.
Private Sub FlatButton_Click()
'Does all the setup stuff.
Dim fso As Object, MyFile As Object
Dim MyFileName As String
Dim txtB As MSForms.TextBox
Set shP = Worksheets("Pricing")
Set txtB = shP.OLEObjects("TextBox1").Object
file = txtB.Text & ".txt"
If txtB.Value = "" Then MsgBox "What we calling it?", vbQuestion: Exit Sub
' Defines the range. So, from B2, across and down.
LastRow = Sheets("Pricing").Range("B" & Rows.Count).End(xlUp).Row
LastColumn = Sheets("Pricing").Cells(2, Columns.Count).End(xlToLeft).Column
'File details.
path = "C:\Users\me.me\Blah\Blah\"
MyFileName = path & file
Delimeter = "|"
' The magic bit.
Set fso = CreateObject("Scripting.FileSystemObject")
Set MyFile = fso.CreateTextFile(MyFileName, False, True) '<==== This defines the Unicode bit.
For Row = 2 To LastRow
For Column = 2 To LastColumn
If Column = 2 Then Record = Trim(Cells(Row, Column)) Else Record = Record & Delimeter & Trim(Cells(Row, Column))
Next Column
MyFile.WriteLine (Record)
Next Row
MyFile.Close
MsgBox "BOOM! ---> " & MyFileName
'Option to open the finished product.
If ActiveSheet.CheckBox2.Value = True Then
Set shApp = CreateObject("shell.application")
shApp.Open (MyFileName)
End If
End Sub
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am trying to make a macro that will bulk perform on all .txt files in a given directory. I would like the first line to be copied into the first cell (A1). And then I would like the rest of the contents to be pasted into B1.
The macro would perform that for all the .txt files in a directory, except it would go to A2, B2...A3,B3 etc
Can anyone help?
This should work for you:
Sub Mrig_GettxtData()
Dim strFile As String, strPath As String, MyData As String, tempStr As String
Dim filePath As Variant
Dim strData() As String
Dim lineNo As Long
Dim myCell As Range
strPath = "C:\test_folder\test" '--> write your path here (without "\")
filePath = strPath & "\"
Set myCell = ThisWorkbook.Sheets("Sheet1").Range("A1") '-->change Sheet1 as required
strFile = Dir(filePath & "*.txt")
Do While Len(strFile) > 0
Open filePath & strFile For Binary As #1
MyData = Space$(LOF(1))
Get #1, , MyData
Close #1
strData() = Split(MyData, vbCrLf)
lineNo = 0
tempStr = ""
For Each a In strData
lineNo = lineNo + 1
If lineNo = 1 Then 'tempStr = "" Then
myCell.Value = a
Set myCell = myCell.Offset(0, 1)
ElseIf lineNo = 2 Then
tempStr = a
Else
tempStr = tempStr & vbCrLf & a
End If
Next
If lineNo <> 1 Then
myCell.Value = tempStr
Set myCell = myCell.Offset(1, -1)
End If
strFile = Dir()
Loop
End Sub
Try this. This will iterate through all the ".txt" files in a folder "in this case it is "H:\data\" in alphabetical order. Any blank text files will be skipped. The first two rows will be populated of the first sheet (or tab) of the workbook where the macro is saved.
Sub readLine()
Dim FileNum As Integer
Dim DataLine As String
Dim strTXTFile As String, strFileSpec As String
strFileSpec = "*.txt"
strFilePath = "D:\data\"
'set starting rng where data will be saved
Set Rng = ThisWorkbook.Sheets(1).Range("A1")
strTXTFile = Dir(strFilePath & strFileSpec)
Do While strTXTFile <> ""
ILine = 1
FileNum = FreeFile()
Open strFilePath & strTXTFile For Input As #FileNum
If EOF(FileNum) Then GoTo skipFile
Line Input #FileNum, DataLine 'save the first line of the document into variable DataLine
Rng.Value = DataLine
Do Until EOF(FileNum)
Line Input #FileNum, DataLine 'save the first line of the document into variable DataLine
Rng.Offset(, 1).Value = Rng.Offset(, 1).Value & DataLine
Loop
Set Rng = Rng.Offset(1)
skipFile:
Close #FileNum
strTXTFile = Dir
Loop
End Sub
I'm trying to create a CSV output file in VBA but I can't seem to get it. I need to loop through a spreadsheet and pull numbers from column 'I' based on whether column D has a "1" in it or not. Then I want to paste the contents of column 'I' into column 'A' of the CSV output file. Could someone please help me complete this? I'd like to incorporate all of the following:
Sub Test()
Dim FileNum, bOutputLine, bFile As String
Dim bOUTPUT, iRow As Integer
bOUTPUT = FreeFile 'Define bOUTPUT as a FreeFile
bFile = "C:\Desktop\Test.csv" 'set the filepath equal to a string
For iRow = 2 To ActiveSheet.UsedRange.Rows.Count
If Trim(range("D" & iRow)) <> "" Then
FileNum = Trim(range("I" & iRow))
End If
Next
Open bFile For Output As bOUTPUT 'Open the file
bOutputLine = FileNum
Print #bOUTPUT, bOutputLine
Close #bOUTPUT 'Close the file
End Sub
You either need to put the file interaction inside the for-next loop and open as append instead of output, or build a string variable in the loop that will print out at the bottom. Here's the two options:
Sub Test()
Dim FileNum, bOutputLine, bFile As String
Dim bOUTPUT, iRow As Integer
bOUTPUT = FreeFile 'Define bOUTPUT as a FreeFile
bFile = "C:\Users\HPUser\Desktop\Test.csv" 'set the filepath equal to a string
Open bFile For Append As bOUTPUT 'Open the file
For iRow = 2 To ActiveSheet.UsedRange.Rows.Count
If Trim(range("D" & iRow)) <> "" Then
FileNum = Trim(range("I" & iRow))
bOutputLine = FileNum
Print #bOUTPUT, bOutputLine
End If
Next
Close #bOUTPUT 'Close the file
End Sub
or
Sub Test()
Dim FileNum, bOutputLine, bFile As String
Dim bOUTPUT, iRow As Integer
bOUTPUT = FreeFile 'Define bOUTPUT as a FreeFile
bFile = "C:\Users\HPUser\Desktop\Test.csv" 'set the filepath equal to a string
For iRow = 2 To ActiveSheet.UsedRange.Rows.Count
If Trim(range("D" & iRow)) <> "" Then
bOutputLine = bOutputLine & Trim(range("I" & iRow)) & vbcrlf
End If
Next
Open bFile For Output As bOUTPUT 'Open the file
Print #bOUTPUT, bOutputLine
Close #bOUTPUT 'Close the file
End Sub
One way is to write to it directly in the loop:
Open bFile For Output As bOUTPUT
For iRow = 2 To ActiveSheet.UsedRange.Rows.Count
If InStr(1, Range("D" & iRow), "1") <> 0 Then
Print #bOUTPUT, Trim(Range("I" & iRow))
End If
Next
Close #bOUTPUT
The InStr will look for the value "1" in Column D's cell (as by the wording of the question, it seems it could be something like "AAA1A". It returns 0 if "1" is not found.
CSV file:
#3GMACRO,,,,,,,,,,,,,,
,,,,,,,,,,,,,,
IMSI,IMEI,Date,Time,UMTS MACRO-UARFCNDL,UMTS MACRO-PrimaryScramblingCode,UMTS MACRO-CPICHTxPower,UMTS MACRO-PLMNCellId,UMTS MACRO- RNCId,UMTS MACRO-MCC,UMTS MACRO-MNC,UMTS MACRO - LAC,UMTS MACRO - RAC,UMTS MACRO - MaxUETxPower,UMTS MACRO - MeasuredRSCP
2.6275E+14,3.57539E+14,20100107,160000,10662,11,-99,268435456,0,0,0,1,0,0,-74
,,,,,,,,,,,,,,
#3GFEMTO,,,,,,,,,,,,,,
,,,,,,,,,,,,,,
IMSI,IMEI,Date,Time,UMTS FEMTOS-UARFCNDL,UMTS FEMTOS-PrimaryScramblingCode,UMTS FEMTOS-CPICHTxPower,UMTS FEMTOS-PLMNCellId,UMTS FEMTOS-RNCId,UMTS FEMTOS-MCC,UMTS FEMTOS-MNC,UMTS FEMTOS-LAC,UMTS FEMTOS-RAC,UMTS FEMTOS-MaxUETxPower,UMTS FEMTOS- MeasuredRSCP
2.6275E+14,3.57539E+14,20100107,160000,10687,252,-24,61,0,610,3956,486,11,5,-102
,,,,,,,,,,,,,,
#2GMACRO,,,,,,,,,,,,,,
,,,,,,,,,,,,,,
IMSI,IMEI,Date,Time,GSM MACRO_CellID,GSM MACRO-MCC,GSM MACRO-MNC,GSM MACRO-LAC,GSM MACRO-RAC,GSM MACRO-Max permitted UE Tx power (SIB3),GSM MACRO-Measure RSSI,,,,
2.6275E+14,3.57539E+14,20100107,160000,GSM_Cell_Id=1,2,3,4,5,6,7,,,,
i want this csv file to be loaded into an excel sheet as an individual section when I click load only once (ie each section should go to separate worksheet in excel)
CSV file contain Section name , header and data
Below are the section names in CSv file
3GMACRO
3GFEMTO
2GMACRO
Below are the Header names in CSv file
IMSI,IMEI,Date,Time,GSM MACRO_CellID,GSM MACRO-MCC,GSM MACRO-MNC............ etc
3 worksheets should have headers and data after loading CSV file.
Please help me in doing so.
Thanks in advance
hi
this is what the code i tried but its not working perfectly as needed.
Sub loadData()
'Runtime error handling
'On Error Resume Next
'Unprotect the password protected sheet for loading csv data
ActiveSheet.Unprotect Password:=pass
'Variable declaration
Dim strFilePath As String, strFilename As String, strFullPath As String
Dim lngCounter As Long
Dim oConn As Object, oRS As Object, oFSObj As Object
'Get a text file name
strFullPath = Application.GetOpenFilename("Text Files (*.csv),*.csv", , "Please select text file...")
'MsgBox "stringfullpath" & strFullPath
If strFullPath = "False" Then Exit Sub 'User pressed Cancel on the open file dialog
'This gives us a full path name e.g. C:tempfolderfile.txt
'We need to split this into path and file name
Set oFSObj = CreateObject("SCRIPTING.FILESYSTEMOBJECT")
strFilePath = oFSObj.GetFile(strFullPath).ParentFolder.Path
strFilename = oFSObj.GetFile(strFullPath).Name
'Open an ADO connection to the folder specified
Set oConn = CreateObject("ADODB.CONNECTION")
oConn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strFilePath & ";" & _
"Extended Properties=""text;HDR=Yes;FMT=Delimited"""
Set oRS = CreateObject("ADODB.RECORDSET")
'Now actually open the text file and import into Excel
'oRS.Open "SELECT * FROM " & strFilename & " , oConn"
oRS.Open "SELECT * FROM " & strFilename, oConn
While Not oRS.EOF
Sheets("Neighbour3GMacro").Range("A3").CopyFromRecordset oRS
'Sheets.Add Type:=Application.GetOpenFilename & " *.csv"
Sheets("Neighbour3GFemto").Range("A2").CopyFromRecordset oRS
Sheets("Neighbour2GMacro").Range("A2").CopyFromRecordset oRS
Wend
oRS.Close
oConn.Close
End Sub
You can use the Split function to get an array and use this array to fill a Row. Here is a simple solution.
You will need to change Sheet1, Sheet2, Sheet3 to your worksheet-names and might want to add functionality to ignore header lines. If you have a fix ColumnCount you can also replace the Ubound function with an integer variable.
Sub loadData2()
Dim strFullPath As String
Dim oFSOBj As Object 'Scripting.FileSystemObject'
Dim oFileStream As Object 'Scripting.TextStream'
Dim targetSheet As Worksheet
Dim iRow As Long
Dim startRow As Long
Dim startColumn As Integer
Dim line As String
'Please insert Error Handling etc.'
'Get a text file name '
strFullPath = Application.GetOpenFilename("Text Files (*.csv),*.csv", , "Please select text file...")
If strFullPath = "False" Then Exit Sub 'User pressed Cancel on the open file dialog'
Set oFSOBj = CreateObject("SCRIPTING.FILESYSTEMOBJECT")
Set oFileStream = oFSOBj.GetFile(strFullPath).OpenAsTextStream(ForReading)
Set targetSheet = Sheet1
iRow = 0
startRow = 3
startColumn = 1
While (Not oFileStream.AtEndOfStream)
line = oFileStream.ReadLine
If (Left(line, 1) = "#") Then
iRow = 0
If (Left(line, 8) = "#3GMACRO") Then Set targetSheet = Sheet1
If (Left(line, 8) = "#3GFEMTO") Then Set targetSheet = Sheet2
If (Left(line, 8) = "#2GMACRO") Then Set targetSheet = Sheet3
ElseIf Trim(line) <> vbNullString Then 'Else Block: line has content'
csline = Split(line, ",")
targetSheet.Range(targetSheet.Cells(startRow + iRow, startColumn), targetSheet.Cells(startRow + iRow, startColumn + UBound(csline))).Value2 = csline
iRow = iRow + 1
End If
Wend
oFileStream.Close
Set oFileStream = Nothing
Set oFSOBj = Nothing
End Sub