Copy data from existing sheet to new csv file - excel

I'm trying to create an Excel tool to split a sheet of data into multiple .csv files, to a maximum of 200 rows per csv file.
My code:
Dim CSheet As Worksheet
Dim LastRow As Long
Dim LastCol As Long
Dim currentFilePath As String
Dim filePath As String
Dim dataDate As String
Dim n As Integer
Dim r As Integer
Dim rowStartNumber As Integer
Dim rowEndNumber As Integer
Dim numOfFiles As Integer
'*****************************************************
' Declare variables
'*****************************************************
On Error Resume Next
Application.DisplayAlerts = False
Set CSheet = Worksheets("Cleaned_Data")
Worksheets("Cleaned_Data").Activate
LastRow = CSheet.Cells(Rows.Count, 1).End(xlUp).Row
LastCol = CSheet.Cells(1, Columns.Count).End(xlToLeft).Column
Debug.Print (Application.ActiveWorkbook.Path)
currentFilePath = Application.ActiveWorkbook.Path
numOfFiles = (LastRow - 1) / 200
dataDate = Format(Worksheets("Instructions").Cells(14, 2), "DD-MMM-YYYY")
filePath = currentFilePath & "\" & dataDate
'*****************************************************
' Check if folder exists; if yes delete and recreate
'*****************************************************
'if folder does not exist
If Dir(filePath, vbDirectory) = "" Then
MkDir filePath
Else
Kill filePath & "*.*"
RmDir filePath
MkDir filePath
End If
Debug.Print ("Hello")
' Loop to create the files
For n = 1 To numOfFiles
rowStartNumber = 2 + ((n - 1) * 200)
rowEndNumber = rowStartNumber + 199
Debug.Print (rowStartNumber & " - " & rowEndNumber)
For r = rowStartNumber To rowEndNumber
Debug.Print (rowStartNumber)
'Start to get data from Csheet, up to 200 rows, and write them into a new .csv file in filePath
Next r
Next n
The loop section is what I'm struggling with. I've tried many ways of copying pasting, or going row by row to iterate and write the .csv file out. How can I do that using VBA?
' Loop to create the files
For n = 1 To numOfFiles
rowStartNumber = 2 + ((n - 1) * 200) 'first data row starts at row 2, due to headers
rowEndNumber = rowStartNumber + 199
Debug.Print (rowStartNumber & " - " & rowEndNumber)
For r = rowStartNumber To rowEndNumber
Debug.Print (rowStartNumber)
'Start to get data from Csheet, up to 200 rows, and write them into a new .csv file in filePath
Next r
Next n

As comments suggested, the code below will aggregate the data in a new worksheet, then save that as a CSV in the same directory as the original Workbook, I've also added a number to the filename to distinguish between the split files:
Sub SplitToCSV()
Dim CSheet As Worksheet: Set CSheet = Worksheets("Cleaned_Data")
Dim ws As Worksheet
Dim LastRow As Long, LastCol As Long, numOfFiles As Integer
Dim filePath As String, dataDate As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
LastRow = CSheet.Cells(Rows.Count, 1).End(xlUp).Row
LastCol = CSheet.Cells(1, Columns.Count).End(xlToLeft).Column
dataDate = Format(Worksheets("Instructions").Cells(14, 2), "DD-MMM-YYYY")
WName = Left(Application.ActiveWorkbook.Name, InStr(Application.ActiveWorkbook.Name, ".") - 1)
numOfFiles = (LastRow - 1) / 200
Set ws = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = "Temp"
'create a Temp Worksheet
For i = 1 To numOfFiles
filePath = Application.ActiveWorkbook.Path & "\" & WName & " " & dataDate & " - " & i
'Append the filenumber to the end of the filename
ws.Rows(1).Value = CSheet.Rows(1).Value
'copy headers
If i = 1 Then
CSheet.Range(CSheet.Cells(1 + (200 * (i - 1)), 1), CSheet.Cells(i * 200, LastCol)).Copy ws.Range("A1")
Else
CSheet.Range(CSheet.Cells(1 + (200 * (i - 1)), 1), CSheet.Cells(i * 200, LastCol)).Copy ws.Range("A2")
End If
'transfer data to Temp worksheet
ws.Copy
ActiveWorkbook.SaveAs Filename:=filePath, FileFormat:=xlCSV, CreateBackup:=True
ActiveWorkbook.Close
'Save worksheet as CSV
Next i
ws.Delete
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub

You could try something along these lines, i have set a constant file count, you can use your original dividing code to sort that out :
Private Const cstChunkSize As Long = 200
Sub implementation()
Dim lngFileNum As Long
Dim wbExport As Excel.Workbook
Dim wsExport As Excel.Worksheet
Dim lngCols As Long
Dim rngChunk As Excel.Range
lngCols = 20
For lngFileNum = 1 To 10
Set wbExport = Workbooks.Add
Set wsExport = wbExport.Worksheets(1)
Set rngChunk = GetChunk(ThisWorkbook.Worksheets("Sheet1").Range("a1"), _
lngCols, lngFileNum)
wsExport.Range("a1").Resize(cstChunkSize, lngCols).Value = rngChunk.Value
wsExport.SaveAs "C:\Databases\CSV\NEWEST2_EXPORT_" & lngFileNum & ".csv", xlCSV
wbExport.Close False
Next lngFileNum
Set wbExport = Nothing
Set wsExport = Nothing
Set rngChunk = Nothing
End Sub
Function GetChunk(rngStartPoint As Excel.Range, _
lngColumns As Long, _
lngChunkNumber As Long, _
Optional lngChunkSize As Long = cstChunkSize) As Excel.Range
Dim r As Excel.Range
Set r = rngStartPoint.Offset((lngChunkSize * (lngChunkNumber - 1)))
Set r = r.Resize(lngChunkSize, lngColumns)
Set GetChunk = r
End Function

Related

VBA code to copy paste data from multiple source workbooks to a master data workbook (Master data sheet) based on column headers

My code below browses through the folder and effectively picks out the required files but the copy paste codes that I have tried did not work for me. Cant use traditional copy paste as column order is not same. Column names are same though.
Sub ImportExcelfiles()
Dim strPath As String
Dim strFile As String
Dim wbSource As Workbook
Dim wsSource As Worksheet
Dim wsTarget As Worksheet
Dim bookName As Worksheet
Dim rowCountSource As Long
Dim colCountSource As Long
Dim rowOutputTarget As Long
Dim colOutputTarget As Long
'Variables for Sheet - Workbook Name
Dim nameCount As Long
Dim fileName As String
Application.DisplayAlerts = False
Application.ScreenUpdating = False
'====================================
'SET THE PATH AND FILE TO THE FOLDER
'====================================
strPath = ThisWorkbook.Worksheets("Control").Range("C4")
fileName = ThisWorkbook.Worksheets("Control").Range("C5")
If Right(strPath, 1) <> "\" Then strPath = strPath & "\"
'set the target worksheet
Set wsTarget = ThisWorkbook.Worksheets("Master Data")
Set bookName = ThisWorkbook.Worksheets("Workbook Name")
'set the initial output row and column count for master data and workbook name
rowOutputTarget = 2
nameCount = 2
'get the first file
strFile = Dir(strPath & "*.xlsx*")
'loop throught the excel files in the folder
Do While strFile <> ""
If InStr(strFile, fileName) > 0 Then
'open the workbook
Set wbSource = Workbooks.Open(strPath & strFile)
Set wsSource = wbSource.Worksheets("Details")
'get the row and column counts
With wsSource
'row count based on column 1 = A
rowCountSource = .Cells(.Rows.Count, 1).End(xlUp).Row
'column count based on row 1
colCountSource = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
-------------------------------Need help here to copy paste-------------------------------------
'copy and paste from A2
wsSource.Range("A3", "AD" & rowCountSource).Copy
wsTarget.Range("A" & rowOutputTarget).PasteSpecial
Paste:=xlPasteValues
bookName.Range("A" & nameCount).Value = wbSource.Name
nameCount = nameCount + 1
rowOutputTarget = rowOutputTarget + rowCountSource - 2
'close the opened workbook
wbSource.Close SaveChanges:=False
End If
'get the next file
strFile = Dir()
Loop
End Sub
Since the order of the columns is different you have to copy them one at a time.
Sub ImportExcelfiles()
Const ROW_COLNAME = 3
'Variables for Sheet - Workbook Name
Dim wbSource As Workbook
Dim wsTarget As Worksheet, wsName As Worksheet
Dim rowOutputTarget As Long, nameCount As Long
Dim strPath As String, strFile As String, fileName As String
With ThisWorkbook
'set the file and path to folder
strPath = .Sheets("Control").Range("C4")
fileName = .Sheets("Control").Range("C5")
If Right(strPath, 1) <> "\" Then strPath = strPath & "\"
'set the target and name worksheets
Set wsTarget = .Sheets("Master Data")
Set wsName = .Sheets("Workbook Name")
End With
' fill dictionary column name to column number from row 1
Dim dict As Object, k As String, rng As Range
Dim lastcol As Long, lastrow As Long, i As Long, n As Long
Set dict = CreateObject("Scripting.Dictionary")
With wsTarget
lastcol = .Cells(1, .Columns.Count).End(xlToLeft).Column
For i = 1 To lastcol
k = UCase(Trim(.Cells(1, i)))
dict.Add k, i
Next
End With
'set the initial output row and column count for master data and workbook nam
rowOutputTarget = 2
nameCount = 2
'get the first file
strFile = Dir(strPath & "*.xlsx*")
'loop through the excel files in the folder
Dim ar, arH, ky, bHasData
Application.ScreenUpdating = False
Do While strFile <> ""
If InStr(strFile, fileName) > 0 Then
'open the workbook
Set wbSource = Workbooks.Open(strPath & strFile, False, False)
wsName.Range("A" & nameCount).Value = wbSource.Name
nameCount = nameCount + 1
' copy values to arrays
With wbSource.Sheets("Details")
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
arH = .Range("A1:AD1").Offset(ROW_COLNAME - 1).Value2 ' col names
ar = .Range("A" & ROW_COLNAME & ":AD" & lastrow).Value2
End With
'close the opened workbook
wbSource.Close SaveChanges:=False
' copy each columns
If lastrow > ROW_COLNAME Then
bHasData = False
For n = 1 To UBound(ar, 2)
k = UCase(Trim(arH(1, n)))
' determine target column using dictonary
' as lookup with approx match
i = 0
For Each ky In dict
If InStr(1, k, ky) > 0 Then
i = dict(ky)
Exit For
End If
Next
' valid match
If i > 0 Then
bHasData = True
Set rng = wsTarget.Cells(rowOutputTarget, i).Resize(UBound(ar))
' copy column n of array to column i of target sheet
rng.Value2 = Application.Index(ar, 0, n)
ElseIf Len(k) > 0 Then
Debug.Print "Column '" & k & "' not found " & strFile
End If
Next
If bHasData Then
rowOutputTarget = rowOutputTarget + UBound(ar) + 2
End If
End If
'get the next file
strFile = Dir()
End If
Loop
Application.ScreenUpdating = True
MsgBox nameCount - 2 & " books", vbInformation
End Sub
Import Data From Files in Folder
Option Explicit
Sub ImportExcelfiles()
' Source
Const sName As String = "Details"
Const siFileExtensionPattern As String = ".xlsx" ' maybe ".xls?" ?
Const sfCol As String = "A"
Const slCol As String = "AD"
Const sfRow As Long = 3
' Destination
Const dName As String = "Master Data"
Const dfCellAddress As String = "A2"
' Destination Lookup
Const dlName As String = "Control"
Const dlsFolderPathAddress As String = "C4"
Const dlsFileNamePatternAddress As String = "C5"
' Destination Name
Const dnName As String = "Workbook Name"
Const dnfCellAddress As String = "A2"
Dim dwb As Workbook: Set dwb = ThisWorkbook
' Destination Lookup Worksheet
' (contains the folder path and the partial file name)
Dim dlws As Worksheet: Set dlws = dwb.Worksheets(dlName)
Dim sFolderPath As String: sFolderPath = dlws.Range(dlsFolderPathAddress)
If Right(sFolderPath, 1) <> "\" Then sFolderPath = sFolderPath & "\"
Dim sFileNamePattern As String ' contains i.e. leading and trailing '*'
sFileNamePattern = "*" & dlws.Range(dlsFileNamePatternAddress) & "*"
Dim sFileExtensionPattern As String
sFileExtensionPattern = siFileExtensionPattern
If Left(sFileExtensionPattern, 1) <> "." Then _
sFileExtensionPattern = "." & sFileExtensionPattern
Dim sFileName As String
sFileName = Dir(sFolderPath & sFileNamePattern & sFileExtensionPattern)
If Len(sFileName) = 0 Then
MsgBox "No files found.", vbCritical ' improve!
Exit Sub
End If
' Destination Worksheet (source data will by copied to)
Dim dws As Worksheet: Set dws = dwb.Worksheets(dName)
' Source and Destination Columns Count
Dim cCount As Long
cCount = dws.Columns(slCol).Column - dws.Columns(sfCol).Column + 1
' Destination First Row Range
Dim dfrrg As Range: Set dfrrg = dws.Range(dfCellAddress).Resize(, cCount)
' Destination Name Worksheet (source workbook names will be written to)
Dim dnws As Worksheet: Set dnws = dwb.Worksheets(dnName)
' Destination Name Cell
Dim dnCell As Range: Set dnCell = dnws.Range(dnfCellAddress)
Application.ScreenUpdating = False
' Source
Dim swb As Workbook
Dim sws As Worksheet
Dim srg As Range
Dim slRow As Long
' Destination
Dim drg As Range
' Both
Dim rCount As Long
Do While Len(sFileName) > 0
Set swb = Workbooks.Open(sFolderPath & sFileName)
' Attempt to reference the source worksheet.
On Error Resume Next
Set sws = swb.Worksheets("Details")
On Error GoTo 0
If Not sws Is Nothing Then ' worksheet exists
slRow = sws.Cells(sws.Rows.Count, sfCol).End(xlUp).Row
If slRow >= sfRow Then ' found data in column
rCount = slRow - sfRow + 1
Set srg = sws.Cells(sfRow, sfCol).Resize(rCount, cCount)
Set drg = dfrrg.Resize(rCount)
drg.Value = srg.Value
dnCell.Value = swb.Name
' Reset
Set dfrrg = dfrrg.Offset(rCount)
Set dnCell = dnCell.Offset(1)
'Else ' found no data in column; do nothing
End If
Set sws = Nothing
'Else ' worksheet doesn't exist; do nothing
End If
swb.Close SaveChanges:=False
sFileName = Dir
Loop
Application.ScreenUpdating = True
MsgBox "Data imported.", vbInformation
End Sub

Copy a Range from Multiple Sheets in a Different Workbook and Save

I regularly upload an excel file into an automated system. This system requires I use its "template" but I am limited to 1000 entries at a time. I frequently have 80k-100k entries to upload meaning I have to upload this template 80-100 times. I have managed to write a macro that splits my 80k-100k file into sheets containing 1000 enties each. What I have done up till now is then manually copy the range from each sheet into the "template", save the template with a unique name, and repeat until I copy all 80-100 sheets. I know there must be a faster way to loop through the sheets, copy to the "template", and save.
I have managed to get a loop started but it only copies the first sheet x number of times.
Sub CopytoTemp()
Dim lngJ As Long
Dim numSheets As Long
Dim name As String
Dim savePath As String
Dim saveName As String
lngJ = 0
name = "Upload_"
savePath = "Path\"
saveName = "Name_"
'Counts the number of sheets in my big list
numSheets = Workbooks("BigList.xlsx").Sheets.Count
'Loop through each sheet
While lngJ < numSheets
Workbooks("BigList.xlsx").Worksheets(lngJ).Activate
Range("A1:I1000").Select
Selection.Copy
Windows("Template.xlsx").Activate
'The first few columns are optional fields that I do not fill out
Range("E7").Select
ActiveSheet.Paste
'Fills in the upload name field in the template
Workbooks("Template.xlsx").Worksheets("Sheet1").Range("B2").Value = name & CStr(lngJ)
wbICM.SaveAs (savePath & saveName & lngJ & ".xlsx")
Workbooks.Open "Path\Template.xlsx"
lngJ = lngJ + 1
Wend
End Sub
This is what I have been using to split the data
Sub SplitWorksheet()
Dim lngLastRow As Long
Dim lngNumberOfRows As Long
Dim lngI As Long
Dim strMainSheetName As String
Dim currSheet As Worksheet
Dim prevSheet As Worksheet
'Number of rows to split among worksheets
lngNumberOfRows = 1000
'Current worksheet in workbook
Set prevSheet = ActiveWorkbook.ActiveSheet
'First worksheet name
strMainSheetName = prevSheet.Name
'Number of rows in worksheet
lngLastRow = prevSheet.Cells(Rows.count, 1).End(xlUp).Row
'Worksheet counter for added worksheets
lngI = 1
While lngLastRow > lngNumberOfRows
Set currSheet = ActiveWorkbook.Worksheets.Add
With currSheet
.Move after:=Worksheets(Worksheets.count)
.Name = strMainSheetName + "(" + CStr(lngI) + ")"
End With
With prevSheet.Rows(lngNumberOfRows + 1 & ":" & lngLastRow).EntireRow
.Cut currSheet.Range("A1")
End With
lngLastRow = currSheet.Cells(Rows.count, 1).End(xlUp).Row
Set prevSheet = currSheet
lngI = lngI + 1
Wend
End Sub
Please, test the next code and send some feedback:
Sub CopytoTemp()
Dim i As Long, name As String, savePath As String, saveName As String, lastRow As Long, arrC, arrSlice
Dim wbBL As Workbook, ws As Worksheet, wbT As Workbook, nrRows As Long, iCount As Long, strCols As String
Set wbBL = Workbooks("BigList.xlsx")
name = "Upload_": saveName = "Name_"
savePath = ThisWorkbook.Path & "\Path\" 'build here your real path
With Application 'some optimization to make the code faster:
.ScreenUpdating = False: .EnableEvents = False
.Calculation = xlCalculationManual
End With
For Each ws In wbBL.Worksheets 'iterate between all sheets of wbBL workbook
lastRow = ws.Range("A" & ws.rows.Count).End(xlUp).row
arrC = ws.Range("A1:I" & lastRow).Value 'place the whole range in an array
For i = 1 To lastRow
Set wbT = Workbooks.Open(savePath & "Template.xlsx") 'use here the Template full name
strCols = "A:I" 'a string used to determine the columns of the following sliced array
If i >= (lastRow - 1000) Then
nrRows = lastRow - 1001 'calculate number of rows for the last slice on the sheet
Else
nrRows = 999
End If
'extract a slice array of all columns and 1000 (or rest up to the sheet end) rows:
arrSlice = Application.Index(arrC, Evaluate("row(" & i & ":" & i + nrRows & ")"), Evaluate("COLUMN(" & strCols & ")"))
wbT.Worksheets("Sheet1").Range("A1").Resize(UBound(arrSlice), UBound(arrSlice, 2)).Value = arrSlice 'drop the slice array content
iCount = iCount + 1 'increment the files count number
Application.DisplayAlerts = False
wbT.saveas savePath & saveName & iCount & ".xlsx" 'save the workbook (overwriting existing, if the case)
Application.DisplayAlerts = True
wbT.Close False 'close the workbook without saving it
i = i + nrRows 'increment the rows interation variable
Next i
Next
With Application
.ScreenUpdating = True: .EnableEvents = True
.Calculation = xlCalculationAutomatic
End With
MsgBox "Ready..."
End Sub
Split by 1000 Records to New Workbooks
A Ton of Workbooks
The code is in an open workbook (e.g. Personal.xlsb).
Opens another file BigList.xlsx and prepares to copy a thousand rows at a time.
Opens another file Template.xlsx and pastes the rows.
Saves it as another file Name_?.xlsx. Closes Template.xlsx.
Repeats under 3 and 4 as needed.
Closes BigList.xlsx.
Carefully adjust the values in the constants section (especially the paths).
Option Explicit
Sub CopytoTemp()
' Source
Const swbPath As String = "C:\Test\2022\70701660\" ' ?
Const swbName As String = "BigList.xlsx"
Const swsID As Variant = 1 ' or "Sheet1" ?
Const sfRow As Long = 1
Const sCols As String = "A:I"
Const sRows As Long = 1000
' Destination
Const dPath As String = "C:\Test\2022\70701660\" ' ?
Const dExtension As String = ".xlsx"
Dim dFileFormat As XlFileFormat: dFileFormat = xlOpenXMLWorkbook
Const dwbNameLeft As String = "Name_"
Const dwsNameLeft As String = "Upload_"
' Template
Const twbPath As String = "C:\Test\2022\70701660\" ' ?
Const twbName As String = "Template.xlsx" ' usually .xltx ?
Const twsName As String = "Sheet1"
Const tfCellAddress As String = "E7"
Const tnCellAddress As String = "B2"
Application.ScreenUpdating = False
Dim swb As Workbook: Set swb = Workbooks.Open(swbPath & swbName)
Dim sws As Worksheet: Set sws = swb.Worksheets(swsID)
Dim slCell As Range: Set slCell = sws.Columns(sCols) _
.Find("*", , xlFormulas, , xlByRows, xlPrevious)
Dim srCount As Long: srCount = slCell.Row - sfRow + 1
Dim dCount As Long: dCount = Int(srCount / sRows)
If srCount Mod sRows > 0 Then
dCount = dCount + 1
End If
Dim sfrrg As Range: Set sfrrg = sws.Rows(sfRow).Columns(sCols)
Dim cCount As Long: cCount = sfrrg.Columns.Count
Dim twbFilePath As String: twbFilePath = twbPath & twbName
Dim srg As Range
Dim twb As Workbook
Dim tws As Worksheet
Dim d As Long
Dim crCount As Long
For d = 1 To dCount
If srCount < sRows Then
crCount = srCount
Else
crCount = sRows
srCount = srCount - sRows
End If
Set srg = sfrrg.Resize(crCount)
Set sfrrg = sfrrg.Offset(crCount) ' next
Set twb = Workbooks.Open(twbFilePath)
Set tws = twb.Worksheets(twsName)
tws.Range(tfCellAddress).Resize(crCount, cCount).Value = srg.Value
tws.Range(tnCellAddress).Value = dwsNameLeft & CStr(d)
Application.DisplayAlerts = False ' overwrite without confirmation
twb.SaveAs dPath & dwbNameLeft & CStr(d) & dExtension, dFileFormat
Application.DisplayAlerts = True
twb.Close SaveChanges:=False
Next d
swb.Close SaveChanges:=False
Application.ScreenUpdating = True
MsgBox "Done."
End Sub

Convert Multiple Excel Sheet Ranges as PDF VBA

The below code is take the Status of Col"E" If it is = Include then its corresponding sheets ranges will will be converted to PDF.
I have tried at my end but its not working receiving an error invalid procedure call or argument on the line
rng.ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=saveLocation
Your help will be appreciated to fix the problem.
Sub SelectSheets_Ranges()
Dim sh As Worksheet, lastR As Long, rng As Range, arr, arrSplit, i As Long, k As Long
Set sh = ActiveSheet
lastR = sh.Range("C" & sh.Rows.Count).End(xlUp).Row
ReDim arr(lastR - 1)
For i = 6 To lastR
If sh.Range("E" & i).Value = "Include" Then
arr(k) = sh.Range("C" & i).Value & "|" & sh.Range("D" & i).Value: k = k + 1
End If
Next i
ReDim Preserve arr(k - 1)
For i = 0 To UBound(arr)
arrSplit = Split(arr(i), "|")
Set rng = Worksheets(arrSplit(0)).Range(arrSplit(1))
'Create and assign variables
Dim saveLocation As String
saveLocation = "C:\Users\marks\OneDrive\Documents\myPDFFile.pdf"
'Save a range as PDF
rng.ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=saveLocation
Next
End Sub
Please, try the next code. It saves in ThisWorkbook path, naming the pdf file as "myPDFFile_sheetName.pdf". Each created file will be open in the default pdf application. If it works OK, you can appropriately change the last parameter:
Sub SelectSheets_Ranges_ExpPdf()
Dim sh As Worksheet, lastR As Long, rng As Range, arr, arrSplit, i As Long, k As Long
Set sh = ActiveSheet
lastR = sh.Range("C" & sh.Rows.Count).End(xlUp).Row
ReDim arr(lastR - 1)
For i = 6 To lastR
If sh.Range("E" & i).Value = "Include" Then
arr(k) = sh.Range("C" & i).Value & "|" & sh.Range("D" & i).Value: k = k + 1
End If
Next i
If k > 0 Then
ReDim Preserve arr(k - 1)
Else
MsgBox "No appropriate range (containing ""Include"") could be found...:exit sub"
End If
Dim boolHide As Boolean, boolProt As Boolean
ActiveWorkbook.Unprotect "4321" 'in order to unprotect he workbook structure
For i = 0 To UBound(arr)
boolHide = False: boolProt = False
arrSplit = Split(arr(i), "|")
Set rng = Worksheets(arrSplit(0)).Range(arrSplit(1))
If ActiveWorkbook.Sheets(arrSplit(0)).ProtectContents Then _
ActiveWorkbook.Sheets(arrSplit(0)).Unprotect "4321": boolProt = True
Debug.Print arrSplit(0)
If ActiveWorkbook.Sheets(arrSplit(0)).Visible <> xlSheetVisible Then _
ActiveWorkbook.Sheets(arrSplit(0)).Visible = xlSheetVisible: boolHide = True
'Create and assign variables
Dim saveLocation As String
saveLocation = ThisWorkbook.Path & "\myPDFFile_" & arrSplit(0) & ".pdf"
'Save a range as PDF
rng.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
saveLocation, Quality:=xlQualityStandard, IgnorePrintAreas:=False, OpenAfterPublish:=True
If boolHide Then ActiveWorkbook.Sheets(arrSplit(0)).Visible = xlSheetHidden
If boolProt Then ActiveWorkbook.Sheets(arrSplit(0)).Protect "4321"
Next
ActiveWorkbook.Protect "4321"
End Sub
Try this:
Sub SelectSheets_Ranges()
Dim sh As Worksheet, i As Long
Dim saveLocation As String, FirstSheet As Boolean
saveLocation = "C:\Users\marks\OneDrive\Documents\myPDFFile.pdf"
Set sh = ActiveSheet
FirstSheet = True
For i = 6 To sh.Range("C" & sh.Rows.Count).End(xlUp).Row
If sh.Cells(i, "E") = "Include" Then
'FirstSheet determines whether the sheet is added to currently-selected
' sheets or not (if not then it replaces them)
ThisWorkbook.Sheets(sh.Cells(i, "C").Value).Select FirstSheet
FirstSheet = False
End If
Next i
If Not FirstSheet Then
'at least one sheet was included
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=saveLocation
End If
End Sub
I assume you want all the ranges from the different sheets in one pdf.
Option Explicit
Sub SelectSheets_Ranges()
Const FOLDER = "C:\Users\marks\OneDrive\Documents\"
Const FILENAME = "myPDFFile.pdf"
Dim wb As Workbook, wbPDF As Workbook
Dim sh As Worksheet, wsPDF As Worksheet
Dim lastR As Long, rng As Range, r As Long, n As Integer, m As Integer
Set sh = ActiveSheet
Set wb = ActiveWorkbook
lastR = sh.Range("C" & sh.Rows.Count).End(xlUp).Row
' create temp workbook to hold ranges
Set wbPDF = Workbooks.Add
m = wbPDF.Sheets.Count
n = m
With sh
For r = 6 To lastR
If .Cells(r, "E").Value = "Include" Then
Set rng = wb.Sheets(.Cells(r, "C").Value).Range(.Cells(r, "D").Value)
Set wsPDF = wbPDF.Sheets.Add(After:=wbPDF.Sheets(n))
rng.Copy wsPDF.Range("A1")
n = n + 1
End If
Next
End With
' delete initial sheets
Application.DisplayAlerts = False
For n = m To 1 Step -1
wbPDF.Sheets(n).Delete
Next
Application.DisplayAlerts = True
'end
wbPDF.ExportAsFixedFormat Type:=xlTypePDF, FILENAME:=FOLDER & FILENAME
'wbPDF.SaveAs FOLDER & "debug.xlsx"
wbPDF.Close False
MsgBox "PDF created " & FOLDER & FILENAME, vbInformation
End Sub

How can I export all named ranges in Excel to Separate CSV files?

I am trying to loop through all named ranges in a workbook and save each object as a separate CSV file. I hacked the code below and it loops through all named ranges and it creates a bunch of CSV files, but it doesn't actuall export any data to any of those CSV files. What am I missing here?
Sub ExportAllNamedRanges()
Dim myCSVFileName As String
Dim myWB As Workbook
Dim rngToSave As Range
Dim fNum As Integer
Dim csvVal As String
Dim intCounter As Integer
Dim nmTemp As Name
Dim nm
Set myWB = ThisWorkbook
For Each nm In ThisWorkbook.Names
Debug.Print nm.Name
myCSVFileName = myWB.Path & "\" & nm.Name & ".csv"
csvVal = ""
fNum = FreeFile
Set rngToSave = Range(nm.Name)
Open myCSVFileName For Output As #fNum
For i = 1 To rngToSave.Rows.Count
For j = 1 To rngToSave.Columns.Count
csvVal = csvVal & Chr(34) & rngToSave(i, j).Value & Chr(34) & ","
Next
Print #fNum, Left(csvVal, Len(csvVal) - 2)
csvVal = ""
Next
Close #fileNumber
Next nm
End Sub
I figured it out. The code below works fine.
Sub ExportAllNamedRanges()
Dim myCSVFileName As String
Dim myWB As Workbook
Dim rngToSave As Range
Dim fNum As Integer
Dim csvVal As String
Dim intCounter As Integer
Dim nmTemp As Name
Dim nm
Set myWB = ThisWorkbook
For Each nm In ThisWorkbook.Names
Debug.Print nm.Name
Dim filename As String, lineText As String
Dim myrng As Range, i, j
filename = ThisWorkbook.Path & "\" & nm.Name & ".csv"
Open filename For Output As #1
Set myrng = Range(nm.Name)
For i = 1 To myrng.Rows.Count
For j = 1 To myrng.Columns.Count
lineText = IIf(j = 1, "", lineText & ",") & myrng.Cells(i, j)
Next j
Print #1, lineText
Next i
Close #1
Next nm
End Sub
Also, here is a nice and simple way to list all named ranges in a workbook.
Sub ListAllNamedRanges()
Dim nm As Name, n As Long, y As Range, z As Worksheet
Application.ScreenUpdating = False
Set z = ActiveSheet
n = 2
With z
.[A1:G65536].ClearContents
.[A1:C1] = [{"Name","Sheet Name","Range"}]
For Each nm In ActiveWorkbook.Names
.Cells(n, 1) = nm.Name
.Cells(n, 2) = Range(nm).Parent.Name
.Cells(n, 3) = nm.RefersToRange.Address(False, False)
n = n + 1
Next nm
End With
Set y = z.Range("C2:C" & z.[C65536].End(xlUp).Row)
y.TextToColumns Destination:=z.[C2], DataType:=xlDelimited, _
OtherChar:=":", FieldInfo:=Array(Array(1, 1), Array(2, 1))
[A:C].EntireColumn.AutoFit
Application.ScreenUpdating = True
End Sub

Combine CSV files with Excel VBA

I have some csv files in one folder. They all contain 3 specific columns. The number of total columns and the order may vary.
I want to concatenate all 3 columns with an underscore and write them in a single column in the worksheet that is running the code.
Here is what I have so far:
Option Explicit
Sub test()
Dim i As Long
Dim LastRow As Long
Dim Columns()
Columns = Array("Column1", "Column2", "Column3")
'Find Columns by Name
For i = 0 To 2
Columns(i) = Rows(1).Find(What:=Columns(i), LookIn:=xlValues, LookAt:=xlWhole, _
MatchCase:=False, SearchFormat:=False).Column
Next i
'Debug.Print Columns(0)
'Debug.Print Columns(1)
'Debug.Print Columns(2)
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i = 2 To LastRow
Cells(i, 1) = Cells(i, Columns(0)) & "_" & Cells(i, Columns(1)) & "_" & Cells(i, Columns(2))
Next i
End Sub
As you can see, this does what I want, but only for the active sheet.
I actually want to loop through all csv files in the same folder as the active sheet and write the results in the first sheet, first column of the sheet running the code (which is not a csv itself obviously).
How can I do this?
thanks!
This is a code that will loop through a folder
Sub Button1_Click()
Dim MyFile As String, Str As String, MyDir As String, Wb As Workbook
Set Wb = ThisWorkbook
'change the address to suite
MyDir = "C:\WorkBookLoop\"
MyFile = Dir(MyDir & "*.xls") 'change file extension
ChDir MyDir
Application.ScreenUpdating = 0
Application.DisplayAlerts = 0
Do While MyFile <> ""
Workbooks.Open (MyFile)
'do something here
MyFile = Dir()
Loop
End Sub
It depends how you are naming the worksheets you create from the CSV files. You could add all the worksheets to a collection and use a For...Each loop to execute the entire search and concatenate procedure within that loop. Note that you'd have to explicitly define the first sheet name as this won't change through successive loops:
Option Explicit
Sub test()
Dim i As Long
Dim LastRow As Long
Dim Columns()
Dim frontSheet as Worksheet
Dim wSheets as New Collection
Dim ws as Worksheet
Set frontSheet = Sheets("name of front sheet")
'Add all your CSV sheets to wSheets using the .Add() method.
For Each ws in wSheets
Columns = Array("Column1", "Column2", "Column3")
'Find Columns by Name
For i = 0 To 2
Columns(i) = ws.Rows(1).Find(What:=Columns(i), LookIn:=xlValues, LookAt:=xlWhole, _
MatchCase:=False, SearchFormat:=False).Column
Next i
'Debug.Print Columns(0)
'Debug.Print Columns(1)
'Debug.Print Columns(2)
LastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
For i = 2 To LastRow
frontsheet.Cells(i, 1) = ws.Cells(i, Columns(0)) & "_" & ws.Cells(i, Columns(1)) & "_" & ws.Cells(i, Columns(2))
Next i
Next ws
End Sub
It's often slow and labourious to open CSV files in excel but VBA can read them as text files using a TextStream. Furthermore, file scripting objects let you work with files and directories directly. Something like this might be a better approach if you don't need to keep the files in a worksheet afterwards:
Sub SearchFoldersForCSV()
Dim fso As Object
Dim fld As Object
Dim file As Object
Dim ts As Object
Dim strPath As String
Dim lineNumber As Integer
Dim lineArray() As String
Dim cols() As Integer
Dim i As Integer
Dim frontSheet As Worksheet
Dim frontSheetRow As Integer
Dim concatString As String
Set frontSheet = Sheets("name of front sheet")
frontSheetRow = 1
strPath = "C:\where-im-searching\"
Set fso = CreateObject("Scripting.FileSystemObject")
Set fld = fso.GetFolder(strPath)
For Each file In fld.Files
If (Right(file.Name, 3) = "csv") Then
Debug.Print file.Name
Set ts = file.OpenAsTextStream()
lineNumber = 0
Do While Not ts.AtEndOfStream
lineNumber = lineNumber + 1
lineArray = Split(ts.ReadLine, ",")
If (lineNumber = 1) Then
'We are at the first line of the .CSV so
'find index in lineArray of columns of interest
'Add extra ElseIf as required
For i = LBound(lineArray) To UBound(lineArray)
If lineArray(i) = "Column 1" Then
cols(1) = i
ElseIf lineArray(i) = "Column 2" Then
cols(2) = i
ElseIf lineArray(i) = "Column 3" Then
cols(3) = i
End If
Next i
Else
'Read and store the column of interest from this
'row by reading the lineArray indices found above.
concatString = ""
For i = LBound(cols) To UBound(cols)
concatString = concatString & lineArray(i) & "_"
Next i
concatString = Left(concatString, Len(concatString) - 1)
frontSheet.Cells(frontSheetRow, 1).Value = concatString
frontSheetRow = frontSheetRow + 1
End If
Loop
ts.Close
End If
Next file
End Sub
You can find more information on FileSystemObject and TextStream here.

Resources