I am using a VBA sub which works inconsistently. The sub is based on a previous Stack Overflow thread answer I found which when it works is perfect. Copy Data from Excel to Notepad.
Sub CopyEventtoNotepad()
'Dim rngData As Range
Dim strData As String
Dim strTempFile As String
Dim strPath As String
strPath = Environ("USERPROFILE") & "\Desktop\HBT.txt"
Set Meeting = Worksheets("Patient").Range("CN21:CO55")
Set MeetingComments = Worksheets("Patient").Range("CN21:CO58")
Set Phone = Worksheets("Patient").Range("CS21:CT33")
Set PhoneComments = Worksheets("Patient").Range("CS21:CT36")
If Worksheets("Patient").Range("BB9").Value = 1 Then MeetingComments.Copy
If Worksheets("Patient").Range("BB9").Value = 2 Then Meeting.Copy
If Worksheets("Patient").Range("BB9").Value = 3 Then PhoneComments.Copy
If Worksheets("Patient").Range("BB9").Value = 4 Then Phone.Copy
' get the clipboard data
' magic code for is for early binding to MSForms.DataObject
With CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
.GetFromClipboard
strData = .GetText
End With
' write to temp file
strTempFile = strPath
With CreateObject("Scripting.FileSystemObject")
' true to overwrite existing temp file
.CreateTextFile(strTempFile, True).Write strData
End With
' open notepad with tempfile
Shell "cmd /c ""notepad.exe """ & strTempFile & """", vbHide
End Sub
The runtime error occurs at the following line:
.CreateTextFile(strTempFile, True).Write strData
I have been trying to identify what the variable factor is that triggers the runtime error 5 for weeks. I can't find a pattern.
Thanks
Copy Range to String
The other day, someone mentioned in the comments that Dao is not working supposedly due to a Windows or Office update.
Anyways, here's a simple workaround that may serve you well for such small ranges.
Option Explicit
Sub CopyEventToNotepad()
Dim rgAddresses As Variant
rgAddresses = VBA.Array("CN21:CO55", "CN21:CO58", "CS21:CT33", "CS21:CT36")
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets("Patient")
Dim rg As Range: Set rg = ws.Range(rgAddresses(ws.Range("BB9").Value - 1))
Dim FilePath As String
FilePath = Environ("USERPROFILE") & "\Desktop\HBT.txt"
Dim RangeString As String: RangeString = StringRangeRows(rg)
With CreateObject("Scripting.FileSystemObject")
.CreateTextFile(FilePath, True).Write RangeString
End With
Shell "cmd /c ""notepad.exe """ & FilePath & """", vbHide
End Sub
Function StringRangeRows( _
ByVal rg As Range, _
Optional ByVal CellDelimiter As String = vbTab, _
Optional ByVal LineDelimiter As String = vbLf) _
As String
Dim cLen As Long: cLen = Len(CellDelimiter)
Dim arg As Range, rrg As Range, rCell As Range, RangeString As String
For Each arg In rg.Areas
For Each rrg In arg.Rows
For Each rCell In rrg.Cells
RangeString = RangeString & CStr(rCell.Value) & CellDelimiter
Next rCell
RangeString = Left(RangeString, Len(RangeString) - cLen) _
& LineDelimiter
Next rrg
Next arg
StringRangeRows = Left(RangeString, Len(RangeString) - Len(LineDelimiter))
End Function
Related
hi i'm trying to create a list of folders from an excel sheet and in each folder, it should be a txt file named let's say name.txt and in each of these files it should write wats in column b
pic1
I used this code to create the folders but I need help about creating the txt files
Sub MakeFolders()
Dim Rng As Range
Dim maxRows, maxCols, r, c As Integer
Set Rng = Selection
maxRows = Rng.Rows.Count
maxCols = Rng.Columns.Count
For c = 1 To maxCols
r = 1
Do While r <= maxRows
If Len(Dir(ActiveWorkbook.Path & "\" & Rng(r, c), vbDirectory)) = 0 Then
MkDir (ActiveWorkbook.Path & "\" & Rng(r, c))
On Error Resume Next
End If
r = r + 1
Loop
Next c
End Sub
I need help generating the text file in each folder
Create Text Files From Worksheet Data
Sub MakeFolders()
Const fRow As Long = 2
Const SubFolderColumn As String = "A"
Const TextColumn As String = "B"
Const TextFileNameCellAddress As String = "B1"
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim wbPath As String: wbPath = ws.Parent.Path & "\"
Dim TextFileName As String
TextFileName = CStr(ws.Range(TextFileNameCellAddress).Value)
Dim lRow As Long
lRow = ws.Cells(ws.Rows.Count, SubFolderColumn).End(xlUp).Row
Dim srg As Range: Set srg = ws.Range(ws.Cells(fRow, SubFolderColumn), _
ws.Cells(lRow, SubFolderColumn))
Dim sCell As Range
Dim TextFile As Long
Dim FolderPath As String
Dim SubFolderName As String
Dim FilePath As String
Dim FileText As String
For Each sCell In srg.Cells
SubFolderName = CStr(sCell.Value)
If Len(SubFolderName) > 0 Then
FolderPath = wbPath & SubFolderName & "\"
If Len(Dir(FolderPath, vbDirectory)) = 0 Then
MkDir FolderPath
End If
FilePath = FolderPath & TextFileName
FileText = CStr(sCell.EntireRow.Columns(TextColumn).Value)
' Or (the same):
'FileText = CStr(ws.Cells(sCell.Row, TextColumn).Value)
TextFile = FreeFile
Open FilePath For Output As #TextFile
Print #TextFile, FileText
Close TextFile
End If
Next sCell
MsgBox "Files created.", vbInformation
End Sub
try to use FSO.CreateTextFile:
Sub Macro1()
'
' Macro1 Macro
'
'
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim strPath As String
strPath = "d:\name.txt"
Dim oFile As Object
Set oFile = fso.CreateTextFile(strPath)
oFile.WriteLine "test"
oFile.Close
Set fso = Nothing
Set oFile = Nothing
End Sub
I have made the following code where the aim is to save two ranges into a CSV file:
Sub Export_range_to_CSV()
Dim myCSVFileName As String
Dim myWB As Workbook
Dim tempWB As Workbook
Dim range1 As Range
Dim range2 As Range
Set range1 = Sheets("sheet1").Range("G2:G4")
Set range2 = Sheets("sheet1").Range("G5:H53")
Application.DisplayAlerts = False
On Error GoTo err
Set myWB = ThisWorkbook
myCSVFileName = "filepath" & "\" & "name" & VBA.Format(VBA.Now, "yyyymmdd_hhmm") & ".csv"
range1.Copy
Set tempWB = Application.Workbooks.Add(1)
With tempWB
.Sheets(1).Range("A1").PasteSpecial xlPasteValues
range2.Copy
.Sheets(1).Range("A4").PasteSpecial xlPasteValues
.SaveAs Filename:=myCSVFileName, FileFormat:=xlCSV, CreateBackup:=False
.Close
End With
err:
Application.DisplayAlerts = True
End Sub
The code above does the job, but for range1 it has commas at the end of the string when saved as CSV. I need to remove these in order for a job downstream to work. How do I get rid of the commas at the end of range1?
This is how it looks once saved as the CSV file:
range1
- # X=Y, <- need to remove these commas
- # Z=U,
- # M=Q,
range2
- datetime,quantity
- 2021-03-05 23:00:00+00:00,17
- 2021-03-05 23:30:00+00:00,17
- 2021-03-06 00:00:00+00:00,17
- 2021-03-06 00:30:00+00:00,17
I think the problem comes from range1 only having a single column and as soon as range2 comes into play it assumes range1 should be two columns as well.
The last column is calculated by checking the last column of both the ranges. Whichever is higher will be taken. Let me explain it.
Let's say the data is till column J
Set range1 = Sheets("sheet1").Range("G2:G4")
Set range2 = Sheets("sheet1").Range("G5:J53")
Then in this scenario, there will be 3 commas added. Similarly if the last column is K in range2 and last column is H in range1 then there will be 3 commas added to the 1st range.
The same holds true when you reverse the range
Set range1 = Sheets("sheet1").Range("G5:J53")
Set range2 = Sheets("sheet1").Range("G2:G4")
Now the 2nd range will have extra commas
Solution
Read the data in an array and then remove the last comma. So once your Csv file is written, pass the file to this procedure and it will take care of the rest
The below code reads the csv in an array in one go and then checks every line if it has a , on the right. And if it has then it removes it. Finally it deletes the old csv and writes the new file by putting the array in the text file in one go. I have commented the code so you should not have a problem understanding it. But if you do then simply ask.
'~~> Example usage
Sub Sample()
CleanCsv "C:\Users\Siddharth Rout\Desktop\aaa.txt"
End Sub
'~~> Cleans csv
Sub CleanCsv(fl As String)
Dim MyData As String, strData() As String
Dim i As Long
'~~> Read the file in one go into an array
Open fl For Binary As #1
MyData = Space$(LOF(1))
Get #1, , MyData
Close #1
strData() = Split(MyData, vbCrLf)
'~~> Check for "," and remove
For i = LBound(strData) To UBound(strData)
If Right(strData(i), 1) = "," Then
Do While Right(strData(i), 1) = ","
strData(i) = Left(strData(i), Len(strData(i)) - 1)
Loop
End If
Next i
'~~> Kill old file
Kill fl
'~~> Output the array in one go into a text file
Dim ff As Long
ff = FreeFile
Open fl For Binary As #ff
Put #ff, , Join(strData, vbCrLf)
Close #ff
End Sub
Remove Trailing Comma
You run exportRangesToCSV, while removeTrailingCommaInTextFile is being called near the end, and removeTrailingComma is being called by removeTrailingCommaInTextFile.
I tested it and it works, but keep in mind that I know very little about manipulating text files (2nd procedure) and that this is more or less the first Regex I've ever written (3rd procedure). It took me 'ages' to write them (not complaining). The 1st procedure is where I'm 'at home'.
Note the example of a classic error-handling routine in the 2nd procedure (yours is unacceptable: you're missing the Resume part). You could easily apply it to the 1st procedure.
Don't forget to adjust the values in the constants section.
The Code
Option Explicit
Sub exportRangesToCSV()
Const sName As String = "Sheet1"
Const sAddr As String = "G2:G4,G5:H53"
Const dFolderPath As String = "C:\Test"
Const dLeftBaseName As String = "Name"
Const dTimeFormat As String = "yyyymmdd_hhmm"
Const dFileExtension As String = ".csv"
Const dAddr As String = "A1"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim rg As Range: Set rg = wb.Worksheets(sName).Range(sAddr)
Dim dFilePath As String
dFilePath = dFolderPath & "\" & dLeftBaseName _
& VBA.Format(VBA.Now, dTimeFormat) & dFileExtension
Application.ScreenUpdating = False
With Workbooks.Add()
Dim dCell As Range: Set dCell = .Worksheets(1).Range(dAddr)
Dim srg As Range
For Each srg In rg.Areas
dCell.Resize(srg.Rows.Count, srg.Columns.Count).Value = srg.Value
Set dCell = dCell.Offset(srg.Rows.Count)
Next srg
Application.DisplayAlerts = False
.SaveAs dFilePath, xlCSV
Application.DisplayAlerts = True
.Close False
End With
Application.ScreenUpdating = True
removeTrailingCommaInTextFile dFilePath, True
'wb.FollowHyperlink dFolderPath
End Sub
Sub removeTrailingCommaInTextFile( _
ByVal FilePath As String, _
Optional ByVal removeAllOccurrences As Boolean = False)
Const ProcName As String = "removeTrailingCommaInTextFile"
On Error GoTo clearError
Dim TextFile As Long: TextFile = FreeFile
Dim TempString As String
Open FilePath For Input As TextFile
TempString = Input(LOF(TextFile), TextFile)
Close TextFile
Open FilePath For Output As TextFile
Print #TextFile, removeTrailingComma(TempString, removeAllOccurrences)
Close TextFile
ProcExit:
Exit Sub
clearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& " " & "Run-time error '" & err.Number & "':" & vbLf _
& " " & err.Description
Resume ProcExit
End Sub
Function removeTrailingComma( _
ByVal SearchString As String, _
Optional ByVal removeAllOccurrences As Boolean = False) _
As String
With CreateObject("VBScript.RegExp")
.Global = True
.MultiLine = True
If removeAllOccurrences Then
.Pattern = ",+$"
Else
.Pattern = ",$"
End If
removeTrailingComma = .Replace(SearchString, "")
End With
End Function
Edit
This solution will write directly to the text file without exporting. It may become slow if there are too many cells.
Arrays
Sub exportRangesToCSVArrays()
Const sName As String = "Sheet1"
Const sAddr As String = "G2:G4,G5:H53"
Const dFolderPath As String = "C:\Test"
Const dLeftBaseName As String = "Name"
Const dTimeFormat As String = "yyyymmdd_hhmm"
Const dFileExtension As String = ".csv"
Const dAddr As String = "A1"
Const Delimiter As String = ","
Dim wb As Workbook: Set wb = ThisWorkbook
Dim rg As Range: Set rg = wb.Worksheets(sName).Range(sAddr)
Dim aCount As Long: aCount = rg.Areas.Count
Dim Data As Variant: ReDim Data(1 To aCount)
Dim rData() As Long: ReDim rData(1 To aCount)
Dim cData() As Long: ReDim cData(1 To aCount)
Dim OneCell As Variant: ReDim OneCell(1 To 1, 1 To 1)
Dim srg As Range
Dim srCount As Long, scCount As Long
Dim drCount As Long, dcCount As Long
Dim n As Long
For Each srg In rg.Areas
n = n + 1
srCount = srg.Rows.Count: scCount = srg.Columns.Count
rData(n) = srCount: cData(n) = scCount
If srCount > 1 Or scCount > 1 Then
Data(n) = srg.Value
Else
Data(n) = OneCell: Data(1, 1) = srg.Value
End If
drCount = drCount + srCount
If scCount > dcCount Then
dcCount = scCount
End If
Next srg
Dim Result() As String: ReDim Result(1 To drCount)
Dim r As Long, i As Long, j As Long
For n = 1 To aCount
For i = 1 To rData(n)
r = r + 1
For j = 1 To cData(n)
Result(r) = Result(r) & CStr(Data(n)(i, j)) & Delimiter
Next j
Result(r) = removeTrailingComma(Result(r), True)
Next i
Next n
Dim dFilePath As String
dFilePath = dFolderPath & "\" & dLeftBaseName _
& VBA.Format(VBA.Now, dTimeFormat) & dFileExtension
Dim TextFile As Long: TextFile = FreeFile
Dim TempString As String
Open dFilePath For Output As TextFile
Print #TextFile, Join(Result, vbLf)
Close TextFile
'wb.FollowHyperlink dFolderPath
End Sub
I have complied some data and I want to move one text file at one time to another folder using (*.txt). Is it possible?
I would like only that function with (*.txt) because it is complicated for me to use any other function and would suit my code best.
What I am trying to do is loop the Move.File function to 7 text files only in which one file only move at one time then the next file moves and so on. While moving one text file, another Naming function to extract the next text name. Hopefully that makes sense.
Dim FSO As Object
Dim SourceFileName As String, DestinFileName As String
k = 0
Do While k < 19
ActiveCell.Offset(-2, k).MergeArea.ClearContents
ActiveCell.Offset(-2, k).Value = Dir(FolderName & "*.txt*")
Set FSO = CreateObject("Scripting.Filesystemobject")
SourceFileName = "Y:\Engineering\*.txt"
DestinFileName = "Y:\Engineering\Completed\"
FSO.MoveFile Source:=SourceFileName, Destination:=DestinFileName
k = k + 3
Loop
Dim sht As Worksheet
Dim fnd As Variant
Dim rplc As Variant
fnd = ".txt"
rplc = ""
For Each sht In ActiveWorkbook.Worksheets
sht.Cells.Replace what:=fnd, replacement:=rplc
Next sht
End Sub
What it does when I use this code it moves all the text files at once to that folder. So when I loop to name headings to text files it gives an error.
If I understood your goal correctly then may try (tested to successfully perform according to my understanding of the goal)
Sub test()
Dim FSO As Object
Dim SourceFileName As String, DestinFileName As String
Dim FolderName As String
FolderName = "Y:\Engineering\"
FolderName = "C:\users\user\Desktop\Folder1\" 'modify to your requirement
Set FSO = CreateObject("Scripting.Filesystemobject")
k = 0
SourceFileName = Dir(FolderName & "*.txt")
Do While k < 19 And SourceFileName <> ""
Debug.Print SourceFileName
ActiveCell.Offset(-2, k).MergeArea.ClearContents
ActiveCell.Offset(-2, k).Value = SourceFileName
DestinFileName = FolderName & "Completed\" & SourceFileName
SourceFileName = FolderName & SourceFileName
FSO.MoveFile Source:=SourceFileName, Destination:=DestinFileName
k = k + 3 ' Why K is being incremented by 3? It will only move seven files
SourceFileName = Dir
Loop
Dim sht As Worksheet
Dim fnd As Variant
Dim rplc As Variant
fnd = ".txt"
rplc = ""
For Each sht In ActiveWorkbook.Worksheets
sht.Cells.Replace what:=fnd, replacement:=rplc
Next sht
End Sub
I have a csv file which I want to transform. The problem is that the columns contain integers lower than 5000. In the columns are also identifiers, e.g. IE0034230957 and BLANK values. They should not change when applying the code.
The csv should open and produce a new file.
Could someone help me with a change in the code that works?
I read topics about this and could come to this code, however it doesn't work:
Sub RemoveSmallValues()
Dim myfilename As String
Dim myfilepath As String
Dim newfilename As String
Dim N As Long
Dim i As Long
Dim cellvalue As Long
Dim rng As Range, r As Range, lm As Double
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
myfilepath = "Q:\Pre trade"
myfilename = "Snapshot_of_Model.csv"
Workbooks.Open (myfilepath)
Workbooks(myfilename).Activate 'Makes SnapShot.csv the active workbook
Set rng = Range("D:F")
lm = 5000
For Each r In rng
If r.Value < lm Then
r.Clear
Next r
newfilename = "Q:\Snapshot_final.csv" 'new file path and file name without extension.
Workbooks(myfilename).SaveAs newfilename, FileFormat:=xlCSV 'Save the file with extension CSV
ActiveWorkbook.Close False 'Close the workbook without saving, as you have already saved the workbook with line before.
End Sub
Off your question, I would code similarly like so
Sub t()
Dim r As Excel.Range
Dim c As Excel.Range
Set r = Range("a1").Resize(Cells(Rows.Count, 1).End(xlUp).Row, 1)
For Each c In r.Cells
If IsNumeric(c.Value) Then
If CDbl(c.Value) < 5000 Then c.Clear
End If
Next c
Set r = Nothing
End Sub
It can also be done using SQL and ADO.
Sub x()
Dim cnCSVConnection As ADODB.Connection
Dim rstResults As ADODB.Recordset
Set cnCSVConnection = New ADODB.Connection
cnCSVConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\Workspace\SW Pensions\RUFUS\;" & _
"Extended Properties=""text;HDR=Yes;FMT=Delimited"";"
'"C:\Workspace\"
cnCSVConnection.Open
Set rstResults = New ADODB.Recordset
rstResults.Open "Select [Entry-date],[Current value of policy]," & _
"iif([Current value of policy]<100,1,0) from " & _
"[Bonds Claims_WIP_TESTING.csv]", cnCSVConnection, adOpenKeyset
Range("a1").CopyFromRecordset rstResults
rstResults.Close
cnCSVConnection.Close
Set rstResults = Nothing
Set cnCSVConnection = Nothing
End Sub
I am glad to be here with great programmers and hope I will learn a lot. I am also new in this kind of programming so I am sorry for any inconvenience.
I am using the vba code below to transfer my files from XLS into CSV. After it translates the xls file into csv format, it saves automatically my newly created csv file in the same directory as my original xls file.
I would like to have a Save As option for my csv filename
Thank you in advance.
' ---------------------- Directory Choosing Helper Functions -----------------------
' Excel and VBA do not provide any convenient directory chooser or file chooser
' dialogs, but these functions will provide a reference to a system DLL
' with the necessary capabilities
Private Type BROWSEINFO ' used by the function GetFolderName
hOwner As Long
pidlRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfn As Long
lParam As Long
iImage As Long
End Type
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" _
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long
Private Declare Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long
Function GetFolderName(Msg As String) As String
' returns the name of the folder selected by the user
Dim bInfo As BROWSEINFO, path As String, r As Long
Dim X As Long, pos As Integer
bInfo.pidlRoot = 0& ' Root folder = Desktop
If IsMissing(Msg) Then
bInfo.lpszTitle = "Select a folder."
' the dialog title
Else
bInfo.lpszTitle = Msg ' the dialog title
End If
bInfo.ulFlags = &H1 ' Type of directory to return
X = SHBrowseForFolder(bInfo) ' display the dialog
' Parse the result
path = Space$(512)
r = SHGetPathFromIDList(ByVal X, ByVal path)
If r Then
pos = InStr(path, Chr$(0))
GetFolderName = Left(path, pos - 1)
Else
GetFolderName = ""
End If
End Function
'---------------------- END Directory Chooser Helper Functions ----------------------
Public Sub DoTheExport()
Dim FName As Variant
Dim Sep As String
Dim wsSheet As Worksheet
Dim nFileNum As Integer
Dim csvPath As String
Sep = ";"
csvPath = Application.ActiveWorkbook.path
Dim brojac As Integer
brojac = 0
For Each wsSheet In Worksheets
If brojac > 0 Then Exit For
wsSheet.Activate
nFileNum = FreeFile
Open csvPath & "\" & _
Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 5) & ".csv" For Output As #nFileNum ' wsSheet.Name
ExportToTextFile CStr(nFileNum), Sep, False
Close nFileNum
brojac = brojac + 1
Next wsSheet
End Sub
Public Sub ExportToTextFile(nFileNum As Integer, _
Sep As String, SelectionOnly As Boolean)
Dim WholeLine As String
Dim RowNdx As Long
Dim ColNdx As Integer
Dim StartRow As Long
Dim EndRow As Long
Dim StartCol As Integer
Dim EndCol As Integer
Dim CellValue As String
Application.ScreenUpdating = False
On Error GoTo EndMacro:
If SelectionOnly = True Then
With Selection
StartRow = .Cells(1).Row
StartCol = .Cells(1).Column
EndRow = .Cells(.Cells.Count).Row
EndCol = .Cells(.Cells.Count).Column
End With
Else
With ActiveSheet.UsedRange
StartRow = .Cells(1).Row
StartCol = .Cells(1).Column
EndRow = .Cells(.Cells.Count).Row
EndCol = .Cells(.Cells.Count).Column
End With
End If
For RowNdx = StartRow To EndRow
WholeLine = ""
For ColNdx = StartCol To EndCol
If Cells(RowNdx, ColNdx).Value = "" Then
CellValue = ""
Else
CellValue = Cells(RowNdx, ColNdx).Value
End If
WholeLine = WholeLine & CellValue & Sep
Next ColNdx
WholeLine = Left(WholeLine, Len(WholeLine) - Len(Sep))
Print #nFileNum, WholeLine
Next RowNdx
EndMacro:
On Error GoTo 0
Application.ScreenUpdating = True
End Sub
Probably the problem is here. This part of code has to be re-writen or corrected.
This is the main function which calls other ones.
Public Sub DoTheExport()
Dim FName As Variant
Dim Sep As String
Dim wsSheet As Worksheet
Dim nFileNum As Integer
Dim csvPath As String
Sep = ";"
csvPath = Application.ActiveWorkbook.path
Dim brojac As Integer
brojac = 0
For Each wsSheet In Worksheets
If brojac > 0 Then Exit For
wsSheet.Activate
nFileNum = FreeFile
Open csvPath & "\" & _
Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 5) & ".csv" For Output As #nFileNum ' wsSheet.Name
ExportToTextFile CStr(nFileNum), Sep, False
Close nFileNum
brojac = brojac + 1
Next wsSheet
End Sub
This updated code gives you a SaveAs name option (with a default as WorkbookName.csv)
More efficient code using variant arrays to make your csv below.
These are the three key updated lines:
strFileName = Application.GetSaveAsFilename(Left$(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 5), "CSV (Comma delimited) (*.csv), *.csv")
If strFileName = "False" Then Exit Sub
Open strFileName For Output As #nFileNum
updated code
Public Sub DoTheExport()
Dim FName As Variant
Dim Sep As String
Dim wsSheet As Worksheet
Dim nFileNum As Integer
Dim csvPath As String
Dim strFileName As String
Sep = ";"
csvPath = Application.ActiveWorkbook.path
Dim brojac As Long
brojac = 0
For Each wsSheet In Worksheets
If brojac > 0 Then Exit For
wsSheet.Activate
nFileNum = FreeFile
strFileName = Application.GetSaveAsFilename(Left$(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 5), "CSV (Comma delimited) (*.csv), *.csv")
If strFileName = "False" Then Exit Sub
Open strFileName For Output As #nFileNum
ExportToTextFile CStr(nFileNum), Sep, False
Close nFileNum
brojac = brojac + 1
Next wsSheet
End Sub
more efficient csv code
From Creating and Writing to a CSV File Using Excel VBA
This code must be run from a regular VBA Code Module. Otherwise the code will cause an error if users try to run it from the ThisWorkbook or Sheet Code panes given the usage of Const.
It is worth noting that the ThisWorkbook and Sheet code sections should be reserved for Event coding only, "normal" VBA should be run from standard Code Modules.
Please note that for purposes of the sample code, the file path of the CSV output file is "hard-coded" as: C:\test\myfile.csv at the top of the code. You will probably want to set the output file programmatically, for instance as a function parameter.
As mentioned earlier; For example purposes, this code TRANSPOSES COLUMNS AND ROWS; that is, the output file contains one CSV row for each column in the selected range. Normally, CSV output would be row-by-row, echoing the layout visible on screen, but I wanted to demonstrate that generating the output by using VBA code provides options beyond what is available by, for instance, using the Save As... CSV Text menu option.
code
Const sFilePath = "C:\test\myfile.csv"
Const strDelim = ","
Sub CreateCSV_Output()
Dim ws As Worksheet
Dim rng1 As Range
Dim X
Dim lRow As Long
Dim lCol As Long
Dim strTmp As String
Dim lFnum As Long
lFnum = FreeFile
Open sFilePath For Output As lFnum
For Each ws In ActiveWorkbook.Worksheets
'test that sheet has been used
Set rng1 = ws.UsedRange
If Not rng1 Is Nothing Then
'only multi-cell ranges can be written to a 2D array
If rng1.Cells.Count > 1 Then
X = ws.UsedRange.Value2
'The code TRANSPOSES COLUMNS AND ROWS by writing strings column by column
For lCol = 1 To UBound(X, 2)
'write initial value outside the loop
strTmp = IIf(InStr(X(1, lCol), strDelim) > 0, """" & X(1, lCol) & """", X(1, lCol))
For lRow = 2 To UBound(X, 1)
'concatenate long string & (short string with short string)
strTmp = strTmp & (strDelim & IIf(InStr(X(lRow, lCol), strDelim) > 0, """" & X(lRow, lCol) & """", X(lRow, lCol)))
Next lRow
'write each line to CSV
Print #lFnum, strTmp
Next lCol
Else
Print #lFnum, IIf(InStr(ws.UsedRange.Value, strDelim) > 0, """" & ws.UsedRange.Value & """", ws.UsedRange.Value)
End If
End If
Next ws
Close lFnum
MsgBox "Done!", vbOKOnly
End Sub
Sub CreateCSV_FSO()
Dim objFSO
Dim objTF
Dim ws As Worksheet
Dim lRow As Long
Dim lCol As Long
Dim strTmp As String
Dim lFnum As Long
Set objFSO = CreateObject("scripting.filesystemobject")
Set objTF = objFSO.createtextfile(sFilePath, True, False)
For Each ws In ActiveWorkbook.Worksheets
'test that sheet has been used
Set rng1 = ws.UsedRange
If Not rng1 Is Nothing Then
'only multi-cell ranges can be written to a 2D array
If rng1.Cells.Count > 1 Then
X = ws.UsedRange.Value2
'The code TRANSPOSES COLUMNS AND ROWS by writing strings column by column
For lCol = 1 To UBound(X, 2)
'write initial value outside the loop
strTmp = IIf(InStr(X(1, lCol), strDelim) > 0, """" & X(1, lCol) & """", X(1, lCol))
For lRow = 2 To UBound(X, 1)
'concatenate long string & (short string with short string)
strTmp = strTmp & (strDelim & IIf(InStr(X(lRow, lCol), strDelim) > 0, """" & X(lRow, lCol) & """", X(lRow, lCol)))
Next lRow
'write each line to CSV
objTF.writeline strTmp
Next lCol
Else
objTF.writeline IIf(InStr(ws.UsedRange.Value, strDelim) > 0, """" & ws.UsedRange.Value & """", ws.UsedRange.Value)
End If
End If
Next ws
objTF.Close
Set objFSO = Nothing
MsgBox "Done!", vbOKOnly
End Sub