Why the below code doesn't work in excel sheet? This code is covert an excel file to text file based on user selection, the selection can be export full excel sheet or selected range and user also can choose delimiter of the text file. I've tested this code in excel sheet form and it works well however if change the userform to embedded in excel sheet, it doesn't work completely. It does generate text file but all value are blank, any idea ?
Public Sub ExportToTextFile(FName As String, SourceFile As String, _
Sep As String, SelectionOnly As Boolean, _
AppendData As Boolean)
Dim wb As Workbook
Dim ws As Worksheet
Dim WholeLine As String
Dim FNum As Integer
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
StarRange = StrCol & StrRow
EndRange = EndCols & endrows
Application.ScreenUpdating = False
On Error GoTo EndMacro:
FNum = FreeFile
Set wb = Workbooks.Open(SourceFile)
Set ws = wb.Sheets("Sheet1")
If SelectionOnly = True Then
With ActiveSheet.UsedRange
StartRow = .Cells(1).Row
StartCol = .Cells(1).Column
EndRow = .Cells(.Cells.Count).Row
EndCol = .Cells(.Cells.Count).Column
End With
Else
With ActiveSheet.Range(StarRange & ":" & EndRange)
StartRow = .Cells(1).Row
StartCol = .Cells(1).Column
EndRow = .Cells(.Cells.Count).Row
EndCol = .Cells(.Cells.Count).Column
End With
End If
If AppendData = True Then
Open FName For Append Access Write As #FNum
Else
Open FName For Output Access Write As #FNum
End If
For RowNdx = StartRow To EndRow
WholeLine = ""
For ColNdx = StartCol To EndCol
If Cells(RowNdx, ColNdx).Value = "" Then
CellValue = Chr(34) & Chr(34)
Else
CellValue = Cells(RowNdx, ColNdx).Value
End If
WholeLine = WholeLine & CellValue & Sep
Next ColNdx
WholeLine = Left(WholeLine, Len(WholeLine) - Len(Sep))
Print #FNum, WholeLine
Next RowNdx
EndMacro:
On Error GoTo 0
Application.ScreenUpdating = True
Close #FNum
MsgBox "Completed.", vbInformation
ActiveWorkbook.Close
End Sub
Looking at your code:
Dim StartRow As Long
Dim EndRow As Long
Dim StartCol As Integer
Dim EndCol As Integer
Dim CellValue As String
StarRange = StrCol & StrRow
EndRange = EndCols & endrows
I suspect you have some typos in your variable names. Is it StartRow or StrRow, for example?
Without using a fine-toothed comb to do your debugging for you, I would highly recommend that you always use
Option Explicit
at the start of every module. This tells VBA "don't let me use any variables I did not explicitly declare" - which in practice means (most of the time) "warn me if I misspelled a variable".
I also noticed that you set a variable ws in the line
Set ws = wb.Sheets("Sheet1")
Then proceed not to use it. Portland Runner posted a good suggestion for how to make use of such a variable - although without seeing the rest of your code / form, it's not clear if that does a better job for you. Typically "ActiveSheet" is a bad idea - it is usually a relic from recording a macro, but not the most efficient or portable thing to do.
It looks like you took code from a couple of different places and repurposed it. I recommend that you go through line by line and make sure that every line is needed, and does what you want.
Finally, as part of the debugging process I would put a breakpoint (F9) in the line
WholeLine = ""
then step through to see whether lines are being formed as you think they are (input range is right, formatting is right, and line is written correctly). My suspicion lies with the way you define your input range. Are StartRow, StartCol etc. actually what you want them to be?
Finally (and possible most importantly) in the lines
For ColNdx = StartCol To EndCol
If Cells(RowNdx, ColNdx).Value = "" Then
CellValue = Chr(34) & Chr(34)
Else
CellValue = Cells(RowNdx, ColNdx).Value
End If
WholeLine = WholeLine & CellValue & Sep
Next ColNdx
You refer to Cells - but don't reference the workbook / sheet that these cells belong to. I suspect that VBA is referencing a difference sheet than you intended. Again - if you properly create the ws variable, then these lines should be changed to
For ColNdx = StartCol To EndCol
If ws.Cells(RowNdx, ColNdx).Value = "" Then
CellValue = Chr(34) & Chr(34)
Else
CellValue = ws,Cells(RowNdx, ColNdx).Value
End If
WholeLine = WholeLine & CellValue & Sep
Next ColNdx
and that may well solve your problem.
Related
It seems that the Workbook.SaveAs method does not support appending to file (otherwise I could slightly modify one of the common solutions).
I know I can use the Open statement and write line by line, but I prefer a more high-level solution.
Based on this answer, here is a line-by-line solution with vbTab as delimiter:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim wsSheet As Worksheet
Dim nFileNum As Integer
Dim txtPath As String
Dim FirstSheet As Boolean
Application.ScreenUpdating = False
txtPath = ActiveWorkbook.FullName
txtPath = Replace(txtPath, "xlsm", "txt")
nFileNum = FreeFile
FirstSheet = True
For Each wsSheet In Worksheets
If FirstSheet = True Then
' Overwrite
Open txtPath For Output As #nFileNum
Else
' Append
Open txtPath For Append As #nFileNum
End If
wsSheet.Activate
ExportToTextFile CStr(nFileNum), vbTab, False, Not (FirstSheet)
Close #nFileNum
FirstSheet = False
Next wsSheet
Application.ScreenUpdating = True
End Sub
Public Sub ExportToTextFile(nFileNum As Integer, _
Sep As String, SelectionOnly As Boolean, _
SkipHeader 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
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
If SkipHeader = True Then
StartRow = StartRow + 1
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
End Sub
The following code is VBA code for an Excel macros. The objective is to read input from the file Impeller_hub.dat and to write it into copy_hub.dat. The error message I received stated that there's a type mismatch, Run-time error '13'. Where is the error and how can it be rectified?
Private Sub fn_write_to_text_Click()
Dim FilePath As String
Dim CellData As String
Dim LastCol As Long
Dim LastRow As Long
Dim fso As FileSystemObject
Set fso = New FileSystemObject
Dim stream As TextStream
Dim stream2 As String
LastCol = ActiveSheet.UsedRange.Columns.Count
LastRow = ActiveSheet.UsedRange.Rows.Count
stream2 = "C:\Users\devanandd\Desktop\copy_hub.dat"
Set stream = fso.OpenTextFile("C:\Users\devanandd\Desktop\Files\NUMECA\Impeller_Hub.dat", stream2, True)
CellData = ""
For i = 1 To LastRow
For j = 1 To LastCol
CellData = Trim(ActiveCell(i, j).Value)
stream.WriteLine "The Value at location (" & i & "," & j & ")" & CellData
Next j
Next i
stream.Close
MsgBox ("Job Done")
End Sub
Something like this works for me (using as much from your code as possible):
Option Explicit
Option Private Module
Private Sub fn_write_to_text_Click()
Dim FilePath As String
Dim CellData As String
Dim LastCol As Long
Dim LastRow As Long
Dim fso As Object
Dim stream As Object
Dim stream2 As String
Dim i As Long
Dim j As Long
Set fso = CreateObject("Scripting.FileSystemObject")
LastCol = ActiveSheet.UsedRange.Columns.Count
LastRow = ActiveSheet.UsedRange.Rows.Count
stream2 = "C:\YOURPATH\Desktop\aaa.txt"
'Uncomment the next line if you do not have the file
'Set stream = fso.CreateTextFile(stream2, True)
Set stream = fso.OpenTextFile(stream2, 8) '8 is ForAppending
CellData = ""
For i = 1 To LastRow
For j = 1 To LastCol
CellData = Trim(ActiveCell(i, j).value)
stream.WriteLine "The Value at location (" & i & "," & j & ")" & CellData
Next j
Next i
stream.Close
MsgBox ("Job Done")
End Sub
The code below would work if you have the file aaa.txt on your desktop. If you do not have it write:
Set stream = fso.CreateTextFile(stream2, True) to create it and delete the line Set stream = fso.OpenTextFile(stream2,8).
If you want to read from file Impeller_hub.dat and to write to file copy_hub.dat, then you need two TextStream variables, and two separate calls of fso.OpenTextFile: one with second argument ForReading, the other with second argument ForWriting.
Or, if you want to add data to the end of file Impeller_hub.dat, then - as CLR already wrote - the second argument for fso.OpenTextFile should be ForAppending.
I'm trying to export an Excel page to a .txt file. Row one has a header. This is not being exported, but I need to do.
Here is my code so far. It does everything I need but include the row of column headers, such as Name, Address, Age, etc.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ExportToTextFile
' This exports a sheet or range to a text file, using a
' user-defined separator character.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Sub ExportToTextFile(FName As String, _
Sep As String, SelectionOnly As Boolean, _
AppendData As Boolean)
Dim WholeLine As String
Dim FNum As Integer
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
Sheets("Export").Visible = True
Sheets("Export").Select
Dim Firstrow As Long
Dim Lastrow As Long
Dim Lrow As Long
Dim CalcMode As Long
Dim ViewMode As Long
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'We use the ActiveSheet but you can replace this with
'Sheets("MySheet")if you want
With ActiveSheet
'We select the sheet so we can change the window view
.Select
'If you are in Page Break Preview Or Page Layout view go
'back to normal view, we do this for speed
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
'Turn off Page Breaks, we do this for speed
.DisplayPageBreaks = False
'Set the first and last row to loop through
Firstrow = .UsedRange.Cells(1).Row
Lastrow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
'We loop from Lastrow to Firstrow (bottom to top)
For Lrow = Lastrow To Firstrow Step -1
'We check the values in the A column in this example
With .Cells(Lrow, "A")
If Not IsError(.Value) Then
If .Value <> "GEN" Then .EntireRow.Delete
'This will delete each row with the Value "ron"
'in Column A, case sensitive.
End If
End With
Next Lrow
End With
ActiveWindow.View = ViewMode
With Application
.ScreenUpdating = True
.Calculation = CalcMode
End With
Application.ScreenUpdating = False
On Error GoTo EndMacro:
FNum = FreeFile
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
If AppendData = True Then
Open FName For Append Access Write As #FNum
Else
Open FName For Output Access Write As #FNum
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 #FNum, WholeLine
Next RowNdx
EndMacro:
On Error GoTo 0
Application.ScreenUpdating = True
Close #FNum
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' END ExportTextFile
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' DoTheExport
' This prompts the user for the FileName and the separtor
' character and then calls the ExportToTextFile procedure.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub DoTheExport()
Dim FileName As Variant
Dim Sep As String
FileName = Application.GetSaveAsFilename(InitialFileName:=vbNullString, FileFilter:="Text Files (*.txt),*.txt")
If FileName = False Then
''''''''''''''''''''''''''
' user cancelled, get out
''''''''''''''''''''''''''
Exit Sub
End If
Sep = "|"
Debug.Print "FileName: " & FileName, "Separator: " & Sep
ExportToTextFile FName:=CStr(FileName), Sep:=CStr(Sep), _
SelectionOnly:=False, AppendData:=True
Sheets("Export").Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.AutoFill Destination:=Range("A1:M500")
Range("A1:M500").Select
Range("A1").Select
ActiveWindow.SelectedSheets.Visible = False
End Sub
Perhaps you are deleting the headings row because "Name" <> "GEN"
If .Value = "ron" Then .EntireRow.Delete
'This will delete each row with the Value "ron"
'in Column A, case sensitive.
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
I have an Excel 2010 workbook. I need to save the used range of each of its worksheets as a tab-delimited text file with no quotes, with the same filename as the workbook and with an extension given by the worksheet name.
Note that Excel stupidly surrounds a value by quotes whenever it sees a comma, even though the delimiter is a tab; other than that, the normal "Save As" / "Text (Tab delimited)" would be fine.
I would prefer to do that using VBA code from within Excel.
If there is a Python solution, I'd be interested too. But at this point pywin32 support for Python 3 is only experimental, so I am not sure I can use it.
Ok here is a slightly complex routine which I wrote couple of months back for one of my clients. This code exports the Excel Worksheet to a Fixed Width File without QUOTES. Screenshots also attached. I am sure this code can be made even better :)
TRIED AND TESTED
Option Explicit
'~~> Change this to relevant output filename and path
Const strOutputFile As String = "C:\Output.Csv"
Sub Sample()
Dim ws As Worksheet
Dim rng As Range
Dim MyArray() As Long, MaxLength As Long
Dim ff As Long, i As Long, lastRow As Long, LastCol As Long
Dim strOutput As String
On Error GoTo Whoa
Application.ScreenUpdating = False
'~~> Change this to the respective sheet
Set ws = Sheets("Sheet1")
LastCol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
'~~> Loop through each Column to get the max size of the field
For i = 1 To LastCol
MaxLength = getMaxLength(ws, i)
ReDim Preserve MyArray(i)
MyArray(i) = MaxLength
Next i
ff = FreeFile
'~~> output file
Open strOutputFile For Output As #ff
'~~> Write to text file
With ws
lastRow = .Range("A" & Rows.Count).End(xlUp).Row
For Each rng In .Range("A1:A" & lastRow)
With rng
For i = 1 To UBound(MyArray)
'~~> Insert a DELIMITER here if your text has spaces
strOutput = strOutput & " " & Left(.Offset(0, i-1).Text & _
String(MyArray(i), " "), MyArray(i))
Next i
Print #ff, Mid(Trim(strOutput), 1)
strOutput = Empty
End With
Next rng
End With
LetsContinue:
On Error Resume Next
Close #ff
On Error GoTo 0
Application.ScreenUpdating = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume LetsContinue
End Sub
'~~> Function to get the max size
Public Function getMaxLength(ws As Worksheet, Col As Long) As Long
Dim lastRow As Long, j As Long
getMaxLength = 0
lastRow = ws.Range("A" & ws.Rows.Count).End(-4162).Row
For j = 1 To lastRow
If Len(Trim(ws.Cells(j, Col).Value)) > getMaxLength Then _
getMaxLength = Len(Trim(ws.Cells(j, Col).Value))
Next j
End Function
Open your excel/csv/text
Perform your your required action and then You can saveas using file format as xlTextPrinter
ActiveWorkbook.SaveAs Filename:="Your File Name.txt", FileFormat:=xlTextPrinter, CreateBackup:=False
No need for extra code to replace extra quotes