CSV¶
WB.SaveAS issues¶
will drop first empty line
will save only Range.Text (not value/value2)
Excel to CSV: numerical data precision¶
When saving excel to csv, to keep numerical data precision, we need to use text format!
csv to sheet¶
Sub CSVToSheet()
strrngfr = "A1"
filename = "my.csv"
Dim csvRows As Variant: csvRows = ReadCsvRows(filename)
Dim i0 As Long: i0 = LBound(csvRows)
Dim nrow As Long: nrow = UBound(csvRows) - i0 ' last row is empty, separated by crlf, also include header
Dim ncol As Long: ncol = ArrLen(Split(csvRows(LBound(csvRows)), ","))
Dim i As Long
Dim j As Long
Dim vals As Variant
ReDim arr(0 To nrow - 1, 0 To ncol - 1) As Variant
For i = 0 To nrow - 1
vals = Split(csvRows(i - i0), ",") '0-based index
For j = 0 To ncol - 1
arr(i, j) = vals(j)
Next
Next
Dim rg As Range
Set rg = Range(strrngfr).Offset(RowOffset:=0).Resize(RowSize:=nrow, ColumnSize:=ncol)
rg.Value = arr
End Sub
sheet to csv¶
Sub SheetsToCSV()
csv_dir = "C:\csv"
xl_file = "C:/tmp/my_excel.xlsx"
sheet_names = "sheet1:sheet2:sheet3"
Set xl = CreateObject("Excel.Application")
Set wb = xl.Workbooks.Open(xl_file)
Set fs = CreateObject("Scripting.FileSystemObject")
csv_file = csv_dir & "/" & fs.GetFileName(xl_file)
For Each sheet_name In Split(sheet_names, ":")
wb.Sheets(sheet_name).Activate
csv_filepath = csv_file & sheet_name & ".csv"
Debug.Print "Saving csv file: " & csv_filepath
wb.SaveAs csv_filepath, 6 'csv_format = 6
Next
wb.Close False
xl.Quit
End Sub
to_csv advanced¶
Sub SheetsToCSV()
dir = ThisWorkbook.Path
xl_file = "my.xlsx"
sheet_names = "a:b:c"
Set xl = CreateObject("Excel.Application")
Debug.Print "Opening Excel file: " & xl_file
Set wb = xl.Workbooks.Open(dir & "\" & xl_file)
Dim rng As Range
csv_file = dir & "\" & xl_file
For Each sheet_name In Split(sheet_names, ":")
With wb.Sheets(sheet_name).UsedRange
nrow = .Rows.Count + .Row - 1
ncol = .Columns.Count + .Column - 1
Set rng = wb.Sheets(sheet_name).Range("A1").Resize(RowSize:=nrow, ColumnSize:=ncol)
arr = rng.Value
arr2 = rng.Value2
End With
csv_filepath = csv_file & sheet_name & ".csv"
ArrValToCSV arr, arr2, csv_filepath
Debug.Print "Saved csv file: " & csv_filepath
Next
wb.Close SaveChanges:=False
xl.Quit
Debug.Print "Done"
End Sub
Sub ArrValToCSV(arr As Variant, arr2 As Variant, ByVal filename As String)
Set fs = CreateObject("Scripting.FileSystemObject")
If fs.FileExists(fielname) Then
Kill filename
End If
Open filename For Output As #1
Dim Line As String
s = ArrShape(arr)
If s(0) = 0 Then
If VarType(arr) = vbDate Then
Line = CStr(arr)
ElseIf VarType(arr) = vbString Then
Line = """" & CStr(arr2) & """"
Else
Line = CStr(arr2)
End If
Print #1, Line
ElseIf s(0) = 1 Then
Line = ""
For i = s(1) To s(2)
If VarType(arr(i)) = vbDate Then
Line = Line & CStr(arr(i))
ElseIf VarType(arr(i)) = vbString Then
Line = Line & """" & CStr(arr2(i)) & """"
Else
Line = Line & CStr(arr2(i))
End If
If i < s(2) Then
Line = Line & ","
End If
Next
Print #1, Line
Else
For i = s(1) To s(2)
Line = ""
For j = s(3) To s(4)
If VarType(arr(i, j)) = vbDate Then
Line = Line & CStr(arr(i, j))
ElseIf VarType(arr(i, j)) = vbString Then
Line = Line & """" & CStr(arr2(i, j)) & """"
Else
Line = Line & CStr(arr2(i, j))
End If
If j < s(4) Then
Line = Line & ","
End If
Next
Print #1, Line
Next
End If
Close #1
End Sub
Function ArrShape(arr As Variant) As Variant()
d = ArrDim(arr)
If d = 0 Then
ArrShape = Array(0, 1, 1, 1, 1)
ElseIf d = 1 Then
ArrShape = Array(1, LBound(arr), UBound(arr), 1, 1)
Else
ArrShape = Array(2, LBound(arr), UBound(arr), LBound(arr, 2), UBound(arr, 2))
End If
End Function
Function ArrDim(arr As Variant) As Long
On Error GoTo Err
Dim i As Long
Dim tmp As Long
i = 0
Do While True
i = i + 1
tmp = UBound(arr, i)
Loop
Err:
ArrDim = i - 1
End Function
to_csv filtered only¶
Sub ToCSV(rng as Range, csvPath as String, optional visibleOnly as Boolean = True, optional wb As Workbook = Nothing)
Application.DisplayAlerts = False
Application.ScreenUpdating = False
If visibleOnly Then
Set rng = rng.SpecialCells(xlCellTypeVisible)
End If
rng.Copy
Dim wsName as String
If wb = Nothing Then
wsName = Nothing
Set wb = Application.Workbooks.Add
Else
wsName = "tmp.ws-" & TimestampID
wb.Sheets.Add.Name = wsName
End If
wb.ActiveSheet.Paste
wb.SaveAs Filename:=csvPath FileFormat:=xlCSV, CreateBackup:=False
If wsName = Nothing
wb.Close SaveChanges:=False
Else
wb.Sheets(wsName).Delete
End If
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub