Subscript out of range VBA copying to csv - excel

While writing a piece of code I encountered the "Subscript out of range" message.
The structure of the folder is the following:
D:\Documents main directory
Inside it there are:
the xls workbook with the code
a file 1.csv to which I need to copy data
a folder WiP which contains csv files with the data
The code currently looks like this
Sub MergeData()
'
' Ìàêðîñ1 Ìàêðîñ
' Provide path to workbooks,
' there is a folder with about 100 csv books from which I should collect data into one
Dim Filename, Pathname As String
Dim wb As Workbook
Pathname = ActiveWorkbook.Path & "\WiP\"
Filename = Dir(Pathname & "*.csv")
' Open a workbook in which the data should be pasted
Workbooks.Open ("D:\Documents\1.csv")
ActiveSheet.Cells(1, 1).Value = "date"
ActiveSheet.Cells(1, 2).Value = "hour"
ActiveSheet.Cells(1, 3).Value = "num"
ActiveSheet.Cells(1, 4).Value = "p"
' Call the code
Do While Filename <> ""
Set wb = Workbooks.Open(Pathname & Filename)
IntegrateDays wb
wb.Close savechanges:=False
Filename = Dir()
Loop
' Close the workbook with data
Workbooks("D:\Documents\1.csv").Close savechanges:=True
End Sub
Sub IntegrateDays(wb As Workbook)
Dim ws As Worksheet
With wb
' Open workbooks, copy a range
Sheets(1).Activate
Dim rng As Range
Set rng = Range(Cells(1, 1), Cells(1, 1).End(xlDown))
rng.Copy
' Paste the range into 1.csv
Workbooks("D:\Documents\1.csv").Worksheets(1).Range("B" & Worksheets(1).UsedRange.Rows.Count + 1).Activate
rng.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Set NextRow = Nothing
End With
End Sub
The code runs until it has to paste the copied range rng into 1.csv and stops with an error.
The first guess is that this may be an error related to range.activate. I attempted to test it by doing the operation without loop and only selecting one cell and further by just opening 1.csv prior to even selecting any ranges. The error remains.
The second suspicion is that there is an issue opening 1.csv. By looking though searches such as "subscript out of range opening csv" I didn't find any heavily discussed issues which would help with this question.
Could you please kindly advise me what caused the error and how to rewrite the code?
Thank you very much in advance.
Evgeniya.

You shouldn't be using rng.PasteSpecial. The parent of the Range.PasteSpecial method should be the destination; not the source.
Since you are interested in getting the values over, abandon the PasteSpecial in favor of direct value transfer.
Dim rng As Range
with Sheets(1)
Set rng = .Range(Cells(1, 1), Cells(1, 1).End(xlDown))
end with
with Workbooks("D:\Documents\1.csv").Worksheets(1)
.cells(rows.count, "B").end(xlup).offset(1,0).resize(rng.rows.count, rng.columns.count) = rng.Value
end with

Are you trying to copy from a workbook into others?
Try adjust this
Application.ScreenUpdating = False
Columns("A:C").Sort Key1:=Range("C2"), _
Order1:=xlDescending, Header:=xlYes
Application.ScreenUpdating = True
Dim WBookCopy As Workbook
Dim WBookPst As Workbook
Dim Filepath As String
Dim SheetName As String
Dim sheetCopy As Worksheet
Set WBookPst = Application.ActiveWorkbook
Call DeleteCache
'B2 is the location directory of latest Excel file
Filepath = Range("B2").Value
Set WBookCopy = Workbooks.Open(Filepath)
Set sheetPst = WBookPst.Worksheets(2)
Set sheetCopy = WBookCopy.Worksheets(1)
sheetCopy.UsedRange.Copy sheetPst.Range("A:AG")
sheetCopy.UsedRange.Value = sheetCopy.UsedRange.Value
WBookCopy.Close (False)

Related

VBA passing string variable to sub

I am modifying my current code to be more user friendly. My original code had hard coded file paths. The new code below is passing the file paths from a "control" sub where they are designated by an input box. The issue I am having is that now, once in the private sub routine, the If statements are no longer working. The only difference is that the file path is being passed from another sub instead of being hardcoded into this sub. I'm not sure what I am missing. Any help would be great.
Private Sub copyGLbuildings(NewRecPath As String, GLsrcPath As String)
Dim fname1 As Variant
Dim fname2 As Variant
Dim wb1 As Workbook
Dim Wb0 As Workbook
fname1 = Dir(GLsrcPath & "*Buildings*")
fname2 = Dir(NewRecPath & "*Buildings Rec*")
If fname1 <> "" Then
Set wb1 = Workbooks.Open(GLsrcPath & fname1)
End If
If fname2 <> "" Then
Set Wb0 = Workbooks.Open(NewRecPath & fname2)
End If
Wb0.Sheets(1).Name = "Data"
Wb0.Sheets.Add.Name = "GL"
wb1.Worksheets(1).UsedRange.Copy
Wb0.Worksheets("GL").UsedRange.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Wb0.Worksheets("GL").UsedRange.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Wb0.Worksheets("GL").UsedRange.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Wb0.Worksheets(1).Activate
ActiveWorkbook.Windows(1).DisplayGridlines = False
Call CleanFAGL
wb1.Close
Wb0.Close savechanges:=True
End Sub
The code looks fine to me. I would advise you put a break point right on the first If Statement and use View > Locals to check what the values of NewRecPath and GLsrcPath are being passed into the Sub Routine as.
Copy to Another Workbook
Using the Destination (written to) before the Source (read from) as the argument is quite unusual.
fname is better written like fName.
Neither of the fNames are ever going to be "", since you have previously added the patterns.
wb0 is a horrible idea, at least start numbering with 1 in the spirit of Excel and VBA. Note that my choice of variable names is also not quite good, but only you can improve it since you fully understand what it's all about.
If it's a worksheet then call it a worksheet (readability) or at least be consistent.
After adding a worksheet without arguments, it will 'land' before the selected (active) sheet, so if you only have one sheet in the workbook, it will be the first. If it isn't, why would you gamble with it, if you can settle this explicitly?
Have a think about the order of the PasteSpecial lines e.g. you adjusted the column widths before the data was copied.
Using sheet or worksheet indexes is prone to errors and confusion which in this case leads me to not knowing which worksheet should be 'deprived' of displaying grid lines.
The rest is covered in your comments.
Don't worry, we all were at this point at one time.
Carefully read the comments and modify the code appropriately.
Option Explicit
' Note that the arguments are switched due to the 'From To' logic.
Private Sub copyGLbuildings( _
ByVal SourcePath As String, _
ByVal DestinationPath As String)
' Validate
' Destination
Dim dwbName As String: dwbName = Dir(DestinationPath & "*Buildings Rec*")
If dwbName = "" Then Exit Sub
' Source
Dim swbName As String: swbName = Dir(SourcePath & "*Buildings*")
If swbName = "" Then Exit Sub
'Application.ScreenUpdating = False
' Destination
' Workbook
If Right(dwbName, 1) <> "\" Then
dwbName = dwbName & "\"
End If
Dim dwb As Workbook: Set dwb = Workbooks.Open(DestinationPath & dwbName)
' Worksheets
Dim dws1 As Worksheet: Set dws1 = dwb.Worksheets(1)
dws1.Name = "Data"
Dim dws2 As Worksheet
' Do it explicitly, even if there is previously only one worksheet.
Set dws2 = dwb.Worksheets.Add(After:=dws1) ' ??? maybe Before:=dws1
dws2.Name = "GL"
' Source
If Right(swbName, 1) <> "\" Then
swbName = swbName & "\"
End If
Dim swb As Workbook: Set swb = Workbooks.Open(SourcePath & swbName)
' Copy
swb.Worksheets(1).UsedRange.Copy
' Destination
' Paste
With dws2.UsedRange
.PasteSpecial Paste:=xlPasteFormats
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteColumnWidths
End With
Application.CutCopyMode = False
' Dispay Gridlines
dws1.Activate ' ??? if "Data" or dws2.Activate ' if "GL": depending on After
dwb1.Windows(1).DisplayGridlines = False
CleanFAGL ' ??? Not knowing what this does, doesn't help.
Application.DisplayAlerts = False
swb.Close SaveChanges:=False
dwb.Close SaveChanges:=True
Application.DisplayAlerts = True
'Application.ScreenUpdating = True
End Sub

Loop through a range to open corresponding files

I have a list of *.xlsm file names on a sheet named "DB" in range E961 to E1010 (50 rows) and I'm trying to create a macro that runs through this list and open the corresponding files in the set directory, runs some code and close the file, moving on to the next file on the list - repeating this operation every 5 minutes.
The directory contains 400+ xlsm files, and the list in E961 will typically be less than 50 files - so I'm not trying to open all the files in the directory. That already happens once a day at a set time.
But I am trying to open these "shortlisted" files and update them every 5 minutes for example. I tried different combinations of code but can't seem to get it working.
The main file containing this code is also in the same directory to allow relative linking to the other 400+ files, hence the ThisWorkbook.Path code.
Edited code below:
Sub UPDATE()
Application.ScreenUpdating = True
With ThisWorkbook.Worksheets("DB")
Dim inputRange As Range
Set inputRange = .Range("E961", .Cells(.Rows.Count, 5).End(xlUp))
End With
Dim directory As String: directory = ThisWorkbook.Path & "\"
Dim fileName As String
Dim r As Range
Dim xlwb As Workbook
For Each r In inputRange
If r <> vbNullString Then
fileName = Dir(directory & r & ".xl??*")
Set xlwb = Workbooks.Open(directory & fileName)
Application.DisplayAlerts = False
ActiveWorkbook.RefreshAll
If Range("A4") > Sheets("DB").Cells(Rows.Count, "A").End(xlUp).Offset(0) Then
Worksheets("DB").Range("A4:L4").Select
Worksheets("DB").Range("A4").Activate
Selection.Copy
Sheets("DB").Select
Sheets("DB").Cells(Rows.Count, "A").End(xlUp).Offset(1). _
PasteSpecial Paste:=xlPasteValues, _
SkipBlanks:=True, Transpose:=False
Application.CutCopyMode = False
Else
End If
If Range("A4") = Sheets("DB").Cells(Rows.Count, "A").End(xlUp).Offset(0) Then
Worksheets("DB").Range("A4:L4").Select
Worksheets("DB").Range("A4").Activate
Selection.Copy
Sheets("DB").Select
Sheets("DB").Cells(Rows.Count, "A").End(xlUp).Offset(0). _
PasteSpecial Paste:=xlPasteValues, _
SkipBlanks:=True, Transpose:=False
Application.CutCopyMode = False
End If
xlwb.Close True
End If
Next r
Application.ScreenUpdating = True
End Sub
The error comes from "Set xlwb = (sht.Cells(Row, 1).Value)" because it is trying to open a sheet as a workbook, but I have no idea how to fix it... or everything is wrong ...
Thanks for the help!
Try this piece it should work thought it will only open and close workbooks until you give it some code to work them:
Option Explicit
Sub UPDATE()
Application.ScreenUpdating = False
'if you are only using here your wb and sht variables, use a With, there is no need to use variables
With ThisWorkbook.Worksheets("DB")
Dim inputRange As Range
'It is preferable to do xlUp because you could find some empty cells in between.
Set inputRange = .Range("E961", .Cells(.Rows.Count, 5).End(xlUp))
End With
Dim directory As String: directory = ThisWorkbook.Path & "\"
Dim fileName As String
Dim r As Range
Dim xlwb As Workbook
For Each r In inputRange
If r <> vbNullString Then
fileName = Dir(directory & r & ".xl??*") 'don't know if your cell has the extension
Set xlwb = Workbooks.Open(directory & fileName)
'some code
xlwb.Close False 'False won't save the workbook, use True if you want it to be saved.
End If
Next r
Application.ScreenUpdating = True
End Sub

Copying Between Workbooks with Varying Names

I am attempting to copy/paste values from one open workbook to another.
Neither of the workbooks will have static names, so there will be no name consistency.
Both of my workbooks will be open and will be the only open files.
Can someone help me fix this code to work when I don't know the file names?
Range("M7:R19").Select
Selection.Copy
Windows("new template.xlsm").Activate
Range("M7").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Windows("old template.xlsm").Activate
Range("S7:AT16").Select
Application.CutCopyMode = False
Selection.Copy
Windows("new template.xlsm").Activate
Range("U7").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Alternative method using Like operator to test for source/destination workbooks. Also provides a way to define source/destination ranges that can be looped through for ease of debugging and updating later. Code heavily commented for clarity.
Sub tgr()
Dim wb As Workbook
Dim wsSource As Worksheet
Dim wsDest As Worksheet
'Check if exactly 2 workbooks are currently open
If Application.Workbooks.Count <> 2 Then
MsgBox "ERROR - There are [" & Application.Workbooks.Count & "] workbooks open." & Chr(10) & _
"There must be two workbooks open:" & Chr(10) & _
"-The source workbook (old template)" & Chr(10) & _
"-The destination workbook"
Exit Sub
End If
For Each wb In Application.Workbooks
If wb.Name Like "*#.xls?" Then
'Workbook name ends in number(s), this is the source workbook that will be copied from
'You'll need to specify which sheet you're working with, this example code assumes the activesheet of that workbook
Set wsSource = wb.ActiveSheet
Else
'Workbook name does not end in number(s), this is the source workbook that will be pasted to
'You'll need to specify which sheet you're working with, this example code assumes the activesheet of that workbook
Set wsDest = wb.ActiveSheet
End If
Next wb
'Check if both a source and destination were assigned
If wsSource Is Nothing Then
MsgBox "ERROR - Unable to find valid source workbook to copy data from"
Exit Sub
ElseIf wsDest Is Nothing Then
MsgBox "ERROR - Unable to find valid destination workbook to paste data into"
Exit Sub
End If
'The first dimension is for how many times you need to define source and dest ranges, the second dimension should always be 1 to 2
Dim aFromTo(1 To 2, 1 To 2) As Range
'Add source copy ranges here: 'Add destination paste ranges here
Set aFromTo(1, 1) = wsSource.Range("M7:R19"): Set aFromTo(1, 2) = wsDest.Range("M7")
Set aFromTo(2, 1) = wsSource.Range("S7:AT16"): Set aFromTo(2, 2) = wsDest.Range("U7")
'Set aFromTo(3, 1) = wsSource.Range("M21:R33"): Set aFromTo(3, 2) = wsDest.Range("M21") 'Example of a third copy/paste range - Dim aFromTo(1 to 3, 1 to 2)
'Set aFromTo(4, 1) = wsSource.Range("S21:AT30"): Set aFromTo(4, 2) = wsDest.Range("U21") 'Example of a fourth copy/paste range - Dim aFromTo(1 to 4, 1 to 2)
'This will loop through the array of specified FromTo ranges and will ensure that only values are brought over
Dim i As Long
For i = LBound(aFromTo, 1) To UBound(aFromTo, 1)
aFromTo(i, 2).Resize(aFromTo(i, 1).Rows.Count, aFromTo(i, 1).Columns.Count).Value = aFromTo(i, 1).Value
Next i
End Sub
You'll have to create two Workbook variables, to distinquish between the one that you want to copy from and where you want to paste to. So something to get you started would be (since these are the only two workbooks open at run-time):
Sub Test()
Dim ws As Workbook, wbCopy As Workbook, wsPaste As Workbook
For Each wb In Application.Workbooks
If IsNumeric(Right(wb.Name, 1)) Then
Set wbCopy = wb
Else
Set wbPaste = wb
End If
Next wb
'Continue coding... Below is just an option:
wbPaste.Worksheets(1).Range("U7:AV16").Value = wbCopy.Worksheets(1).Range("S7:AT16").Value
'Same thing for other ranges....
End Sub
The second part of the code is for you to consider. I do not know which sheet you refer to on either workbook, nor do I know if you really need to copy/paste. In my example I went with the Worksheet with index 1 and I assumed a simple Value transfer may be what you actually want.
But these last two things are for you to consider.

Run-time Error 1004, Application defined or object-defined error

I've searched everywhere to see why I'm getting this error. Basically once I get to the last line the "Selection.AutoFill Destination:=Range("G2:M" & LR)" I get the error. The code works if in a separate sub, by itself. Therefore I'm assuming the code above it is somehow affecting it?
Sub Certainsheets()
Dim Wb1 As Workbook, wb2 As Workbook, wb3 As Workbook
Dim LR As Long
Dim rTable As Range
Dim strCellREF2Txt As String
Dim strFILEname As String
Dim WS As Worksheet
'copy from ThisWorkbook
'Set wb2 = Workbooks(2)
Set wb2 = Workbooks.Open("C:\Users\asharma\Desktop\Loan Application\Loan
Data.xls")
'To this
Set Wb1 = ThisWorkbook
'Copying data from Loan Data file
Set tbl = wb2.Sheets(1).Range("A1").CurrentRegion
tbl.Offset(1, 0).Resize(tbl.Rows.Count - 1, tbl.Columns.Count).Copy
'wb2.Sheets(1).Range("A1").CurrentRegion.Copy
'Pasting data into AOL DATA Tab
Wb1.Activate
Sheets("AOL DATA").Range("A10000").End(xlUp).Offset(1, 0).PasteSpecial
xlValues
'Wb1.Sheets(1).Range("A1").Select.PasteSpecial Paste:=xlPasteValues,
'Operation:=xlNone, SkipBlanks _
':=False, Transpose:=False
Application.CutCopyMode = False
wb2.Close
'REMOVING DUPLICATES
'Sheets("AOL DATA").Range("$A:$E").RemoveDuplicates Columns:=1, Header:=xlNo
'This part Autofills the formulas till the last row.
LR = Range("A" & Rows.Count).End(xlUp).Row
Sheets("AOL DATA").Range("G2:M2").Select
Application.CutCopyMode = False
Selection.AutoFill Destination:=Range("G2:M" & LR)
End sub'
Any help would be appreciated
You need to qualify your ranges with the actual sheet, otherwise VBA will default to the ActiveSheet object which may not be what you're expecting in your code.
You can re-write your code as follows:
Sub Certainsheets()
Dim loanWorkbook As Excel.Workbook
Dim aolSheet As Excel.Worksheet
Dim dataTable As Excel.Range
Set loanWorkbook = Workbooks.Open("C:\Users\asharma\Desktop\Loan Application\Loan Data.xls")
Set aolSheet = ThisWorkbook.Sheets("AOL DATA")
Set dataTable = loanWorkbook.Sheets(1).Range("A1").CurrentRegion
With dataTable.Offset(1, 0)
aolData.Range("A" & aolData.Rows.Count).End(xlUp).Offset(1, 0).Value = _
.Resize(.Rows.Count - 1, .Columns.Count).Value
End With
loanWorkbook.Close
With aolSheet
.Range("G2:M2").AutoFill .Range("G2:M" & .Cells(.Rows.Count, 1).End(xlUp).Row)
End With
End Sub
The AutoFill() method requires the source range to be included as part of the destination range. I suspect because of your code's reliance on ActiveSheet object that you're unknowingly specifying two ranges on different sheets, hence the code fails.

Excel VBA: Transpose data from columns in one Workbook to rows in another workbook

I am new to VBA.
Transposing data from columns in one Workbook to another as rows is throwing errors. Tried suggestions from Stack Overflow and elsewhere but no success.
Error Runtime Error 1004 -> PasteSpecial method of Range class failed
Code:
Sub Button1_Click()
Dim MyFile As String
Dim erow
Dim FilePath As String
FilePath = "C:\trial\"
MyFile = Dir(FilePath)
Do While Len(MyFile) > 0
If MyFile = "here.xlsm" Then
Exit Sub
End If
'Opening data.xls to pull data from one column with 2 values (E6 and E7)
Workbooks.Open (FilePath & MyFile), Editable:=True
Dim SourceRange As Range
Set SourceRange = ActiveSheet.Range("E6:E7")
SourceRange.Copy
ActiveWorkbook.Close SaveChanges:=True
'Back to calling file - here.xlsm and pasting both values in single row (for e.g. A2 and B2)
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Dim targetRange As Range
Set targetRange = ActiveSheet.Cells(erow, 1)
targetRange.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
MyFile = Dir
Loop
End Sub
It is because you cannot do both values only and transpose at the same time.
Try this:
Sub Button1_Click()
Dim MyFile As String
Dim erow
Dim FilePath As String
Dim swb As Workbook
Dim twb As Workbook
Set twb = ThisWorkbook
FilePath = "C:\trial\"
MyFile = Dir(FilePath)
Do While Len(MyFile) > 0
If MyFile = "here.xlsm" Then
Exit Sub
End If
'Change "Sheet1" below to the actual name of the sheet
erow = twb.Sheets("Sheet1").Cells(twb.Sheets("Sheet1").Rows.Count, 1).End(xlUp).Offset(1, 0).Row
'Opening data.xls to pull data from one column with 2 values (E6 and E7)
Set swb = Workbooks.Open(FilePath & MyFile)
'assign values
twb.Sheets("Sheet1").Cells(erow, 1).Resize(, 2).Value = Application.Transpose(swb.ActiveSheet.Range("E6:E7").Value)
'close
swb.Close SaveChanges:=True
MyFile = Dir
Loop
End Sub
This seems to work:
Its a simpler example that does same thing
copy/paste method applies only to active objects (like, sheets, ranges, etc)
so you need to activate one, then the other,
Sub tst1()
Dim inbook, outbook As Workbook
Dim inSheet, outSheet As Worksheet
Dim inRange, outRange As Range
Set inbook = Application.Workbooks("temp1.xlsx")
Set outbook = Application.Workbooks("temp2.xlsx")
Set inSheet = inbook.Worksheets("sheet1")
Set outSheet = outbook.Worksheets("sheet1")
inSheet.Activate
Set inRange = ActiveSheet.Range("a1:b4")
inRange.Copy
outSheet.Activate
Set outRange = ActiveSheet.Range("a1:d2")
outRange.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
End Sub

Resources