0

What is an efficient way to export a particular range of cells with data from Excel 2010 to CSV using VBA? The data always starts at cell A3. The end of the range depends on the dataset (always column Q but row end may vary). It should only export data from sheet 2 called 'Content' and the cells need to contain only 'real' data like text or numbers, not empty values with formulas.

The reason cells have formulas is because they reference cells from sheet 1 and 3. Formulas use normal reference and also vertical searches.

Using the UsedRange will export all the cells which are used by Excel. This works, but it also ends up exporting all the empty cells containing formulas but no data leading to lots (510 to be precise) of unnecessary semicolons in the output .csv.

Sub SavetoCSV()
    Dim Fname As String
 Sheets("Content").UsedRange.Select
 Selection.Copy
 Fname = "C:\Test\test.csv"
    Workbooks.Add
    ActiveSheet.Paste
    ActiveWorkbook.SaveAs Filename:=Fname, _
    FileFormat:=xlCSV, CreateBackup:=False, local:=True
    Application.DisplayAlerts = False
    ActiveWorkbook.Close
    Application.DisplayAlerts = True
End Sub

One solution might be to change the UsedRange in the VB code with Offset or Resize. Another might be to create a RealRange variable and then selectcopy that.

Similar kind of questions have been asked more than once, like here, here and here, and I've also looked at SpecialCells, but somehow I cannot get it to work the way I want it to.

I have tried the below code, but it ends up adding rows from sheet 3 as well.

 Sub ExportToCSV()
 Dim Fname As String
 Dim RealRange As String
 Dim Startrow As Integer
 Dim Lastrow As Integer
 Dim RowNr As Integer

 Startrow = 3
 RowNr = Worksheets("Content").Cells(1, 1).Value 'this cells has a MAX function returning highest row nr
 Lastrow = RowNr + 3
 RealRange = "A" & Startrow & ":" & "Q" & Lastrow

 Sheets("Content").Range(RealRange).Select
 Selection.Copy
 Fname = "C:\Test\test.csv"
    Workbooks.Add
    ActiveSheet.Paste
    ActiveWorkbook.SaveAs Filename:=Fname, _
    FileFormat:=xlCSV, CreateBackup:=False, local:=True
    Application.DisplayAlerts = False
    'ActiveWorkbook.Close
    Application.DisplayAlerts = True
End Sub

If I'm looking in the wrong direction, please refer to other options.

Community
  • 1
  • 1
J3FFK
  • 664
  • 3
  • 14
  • 32

1 Answers1

1

If I understand, you only want to export the cell if it has a value in it. This is going to lead to a csv with different numbers of columns in it. If that's truly what you are trying to do then the fastest way I think is writing your results to a file as below. This ran in about 1 second for 20,000 rows

Dim Lastrow As Integer
Dim RowNr As Integer
Dim SourceSheet As Worksheet
Const Fname As String = "C:\Test\test.csv"
Const StartRow As Integer = 3
Sub ExportToCSV()
On Error GoTo errorhandler
Set SourceSheet = Worksheets("Content")
    TargetFileNumber = FreeFile()
    Open Fname For Output As #TargetFileNumber 'create the file for writing
    Lastrow = SourceSheet.Cells(1, 1).Value + 3 'I would just use the used range to count the rows but whatever
    For r = StartRow To Lastrow 'set up two loops to go through the rows column by column
        Line = ""
        If SourceSheet.Cells(r, 1).Value <> "" Then 'check if there is a value in the cell, if so export whole row
            For c = 1 To 17 'Columns A through Q                
                Line = Line & SourceSheet.Cells(r, c).Value & "," 'build the line                
            Next c
        Line = Left(Line, Len(Line) - 1) 'strip off last comma
        Print #TargetFileNumber, Line 'write the line to the file
    End If
    Next r
 GoTo cleanup
errorhandler:
MsgBox Err.Number & " --> " & Err.Description, vbCritical, "There was a problem!"
cleanup:
Close #TargetFileNumber
End Sub
neuralgroove
  • 580
  • 4
  • 12
  • Thanks, I got an error 5--> invalid procedure call or invalid argument, but it does produce an output csv. There is a small comment sign ' to be added in the first loop also. I really like the result, it is actually more than expected, but I still have two questions: 1) in the comment you prefer to use usedrange for row count. Can you show how? 2) I'd like to keep the whole row if it contains data. Column A is actually a rownumber, so if column A has data then export whole row (column A - Q). How can this be done? – J3FFK Nov 03 '15 at 19:39
  • 1. I always just use something like LastRow=Cells(65536,1).End(xlUp).Row .. thats not best practice I guess, because your range can go beyond that, with excel able to handle over a million rows just pick a number thats way over that you'd ever use in the sheet..you can also use Worksheet.UsedRange.Rows.Count (i think), but I don't use it because it will pick up ghost rows past the end of your actual data if you haven't deleted those rows. 2. I'll edit the post to check for a value in column a and export the whole row – neuralgroove Nov 03 '15 at 20:17
  • In my case, lastrow cannot be more than about 520 rows of data, it's actually quite small so LastRow=Cells(520,1).End(xlUp).Row works excellent. Thanks for the edit in the loop. I still get the 5 --> invalid procedure call or argument though, trying to find which line causes it, any idea on that? – J3FFK Nov 03 '15 at 20:37
  • comment out (put a single quote before) the On Error GoTo errorhandler line and run, then debug to find the line that's causing the error – neuralgroove Nov 04 '15 at 11:59
  • Found the line causing the problem, it is: Line = Left(Line, Len(Line) - 1) 'strip off last comma. I commented it out and it still works, but shows the last separator at the end of the line. I think this is ok for me now. Thanks for all the help! – J3FFK Nov 05 '15 at 13:52