Excel VBA: Loop through cells and copy values to another workbook - vba

I already spent hours on this problem, but I didn't succeed in finding a working solution.
Here is my problem description:
I want to loop through a certain range of cells in one workbook and copy values to another workbook. Depending on the current column in the first workbook, I copy the values into a different sheet in the second workbook.
When I execute my code, I always get the runtime error 439: object does not support this method or property.
My code looks more or less like this:
Sub trial()
Dim Group As Range
Dim Mat As Range
Dim CurCell_1 As Range
Dim CurCell_2 As Range
Application.ScreenUpdating = False
Set CurCell_1 = Range("B3") 'starting point in wb 1
For Each Group in Workbooks("My_WB_1").Worksheets("My_Sheet").Range("B4:P4")
Set CurCell_2 = Range("B4") 'starting point in wb 2
For Each Mat in Workbooks("My_WB_1").Worksheets("My_Sheet").Range("A5:A29")
Set CurCell_1 = Cells(Mat.Row, Group.Column) 'Set current cell in the loop
If Not IsEmpty(CurCell_1)
Workbooks("My_WB_2").Worksheets(CStr(Group.Value)).CurCell_2.Value = Workbooks("My_WB_1").Worksheets("My_Sheet").CurCell_1.Value 'Here it break with runtime error '438 object does not support this method or property
CurCell_2 = CurCell_2.Offset(1,0) 'Move one cell down
End If
Next
Next
Application.ScreenUpdating = True
End Sub
I've done extensive research and I know how to copy values from one workbook to another if you're using explicit names for your objects (sheets & ranges), but I don't know why it does not work like I implemented it using variables.
I also searched on stackoverlow and -obviously- Google, but I didn't find a similar problem which would answer my question.
So my question is:
Could you tell me where the error in my code is or if there is another easier way to accomplish the same using a different way?
This is my first question here, so I hope everything is fine with the format of my code, the question asked and the information provided. Otherwise let me know.

5 Things...
1) You don't need this line
Set CurCell_1 = Range("B3") 'starting point in wb 1
This line is pointless as you are setting it inside the loop
2) You are setting this in a loop every time
Set CurCell_2 = Range("B4")
Why would you be doing that? It will simply overwrite the values every time. Also which sheet is this range in??? (See Point 5)
3)CurCell_2 is a Range and as JohnB pointed it out, it is not a method.
Change
Workbooks("My_WB_2").Worksheets(CStr(Group.Value)).CurCell_2.Value = Workbooks("My_WB_1").Worksheets("My_Sheet").CurCell_1.Value
to
CurCell_2.Value = CurCell_1.Value
4) You cannot assign range by just setting an "=" sign
CurCell_2 = CurCell_2.Offset(1,0)
Change it to
Set CurCell_2 = CurCell_2.Offset(1,0)
5) Always specify full declarations when working with two or more objects so that there is less confusion. Your code can also be written as
Option Explicit
Sub trial()
Dim wb1 As Workbook, wb2 As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
Dim Group As Range, Mat As Range
Dim CurCell_1 As Range, CurCell_2 As Range
Application.ScreenUpdating = False
'~~> Change as applicable
Set wb1 = Workbooks("My_WB_1")
Set wb2 = Workbooks("My_WB_2")
Set ws1 = wb1.Sheets("My_Sheet")
Set ws2 = wb2.Sheets("Sheet2") '<~~ Change as required
For Each Group In ws1.Range("B4:P4")
'~~> Why this?
Set CurCell_2 = ws2.Range("B4")
For Each Mat In ws1.Range("A5:A29")
Set CurCell_1 = ws1.Cells(Mat.Row, Group.Column)
If Not IsEmpty(CurCell_1) Then
CurCell_2.Value = CurCell_1.Value
Set CurCell_2 = CurCell_2.Offset(1)
End If
Next
Next
Application.ScreenUpdating = True
End Sub

Workbooks("My_WB_2").Worksheets(CStr(Group.Value)).CurCell_2.Value
This will not work, since CurCell_2 is not a method of Worksheet, but a variable. Replace by
Workbooks("My_WB_2").Worksheets(CStr(Group.Value)).Range("B4").Value

Related

set workbooks and worksheets returns either "nothing" or 424 run-time error object required

I am desperately hoping someone can help me. I've been troubleshooting this issue for the last 3 days non-stop. I am new to VBA so I am sure it has to be something elementary. Basically I have 2 open workbooks, one holds the data, and the other is where I want to paste some of the data based on an "if, then". For some reason, I cannot set the workbooks as variables in order to easily reference/update. I know we will be changing the name of these 2 documents as soon as I am able to go live, so I wanted to just change it in one place instead of all throughout the code. Below is the code, can someone please tell me what I'm missing? The comments are included to help make the picture clear. I look forward to hearing any wisdom that you could impart?
Dim I As Integer
'NAMING AND ASSIGNING TYPE WORKBOOKS AND WORKSHEETS FOR EASIER REFERENCE
Dim wbraw As Workbook
Dim wsrawwires As Worksheet
Dim wbdest As Workbook
Dim wsdestwires As Worksheet
Dim wsdestcover As Worksheet
'SETTING LOCATION OF NAMED WORKBOOKS AND WORKSHEETS FOR CODING
Set wbraw = Workbooks("scorecard (raw data) revised.xlsx")
Set wbdest = Workbooks("scorecard revised.xlsm")
Set wsrawwires = wbraw.Sheets("wires")
Set wsdestwires = ThisWorkbook.Sheets("sheet2")
Set wsdestcover = ThisWorkbook.Sheets("cover")
'NAMING AND LOCATING VARIABLE FOR CONDITION OF IF STATEMENT
previousyear = Workbooks("scorecard revised.xlsm").Range("x10")
'NAMING AND LOCATING VARIABLE FOR SOURCE TESTED IN IF STATEMENT
rawwiresfinalrow = wsrawwires.Range("b537").End(xlUp).Row
For I = 3 To rawwiresfinalrow
'CODE FOR PULLING APPLICABLE DATA INTO DESTINATION REPORT
If wsrawwires.Range(Cells(I, 5)).Value = previousyear.Value Then
wsrawwires.Range(Cells(I, 2), Cells(I, 5)).Copy
wsdestwires.Range("a1").PasteSpecial xlPasteValues
End If
Next I
First things first, I would always recommend using Option Explicitwhich basically stops the code from running if not all variables are defined. This makes debugging easier and you will find typos straight away.
So use this instead:
Option Explicit
Sub nameOfSub()
Dim i As Long 'use Long instead of Integer.
Dim rawwiresfinalrow as Long
Dim counter As Long
'NAMING AND ASSIGNING TYPE WORKBOOKS AND WORKSHEETS FOR EASIER REFERENCE
Dim wbraw As Workbook
Dim wsrawwires As Worksheet
Dim wbdest As Workbook
Dim wsdestwires As Worksheet
Dim wsdestcover As Worksheet
Dim previousyear As Range
'SETTING LOCATION OF NAMED WORKBOOKS AND WORKSHEETS FOR CODING
Set wbraw = Workbooks("scorecard (raw data) revised.xlsx")
Set wbdest = Workbooks("scorecard revised.xlsm")
Set wsrawwires = wbraw.Sheets("wires")
Set wsdestwires = ThisWorkbook.Sheets("sheet2")
Set wsdestcover = ThisWorkbook.Sheets("cover")
'NAMING AND LOCATING VARIABLE FOR CONDITION OF IF STATEMENT
Set previousyear = wbdest.Sheets("Enter_your_sheetname_here").Range("x10")
'NAMING AND LOCATING VARIABLE FOR SOURCE TESTED IN IF STATEMENT
rawwiresfinalrow = wsrawwires.Range("b537").End(xlUp).Row
counter = 1
For i = 3 To rawwiresfinalrow
'CODE FOR PULLING APPLICABLE DATA INTO DESTINATION REPORT
If wsrawwires.Cells(I, 5).Value = previousyear.Value Then
With wsrawwires
.Range(.Cells(i, 2), .Cells(i, 5)).Copy
End With
wsdestwires.Range("A" & counter).PasteSpecial xlPasteValues
counter = counter + 1
End If
Next I
End Sub

Copying range of cells from workbooks based on sheetname

I had received help yesterday on this code, but I'm completely new to VBA so I'm having difficulties. To explain my code:
I am trying to copy a range of cells from one workbook to the same range of cells in another workbook, but the names of the worksheets have to be the same. So the code is supposed to test if the worksheets exist, then it'll find the corresponding worksheets in the two workbooks. If the names are the same, it'll take on the value, but if not, it'll keep going through all the sheets in workbook1 to find the right sheet. The code runs through, but it's not copying the cells.
I assume the issue could stem from the sheetexists line within the first loop. I was told I need to make sure that I check to see if the sheets exist before running the loops, but I'm unsure of how to do that.
Thank you!
Function SheetExists(shtName As String, Optional wb As Workbook) As Boolean
Dim sht As Worksheet
If wb Is Nothing Then Set wb = ThisWorkbook
On Error Resume Next
Set sht = wb.Sheets(shtName)
On Error GoTo 0
SheetExists = Not sht Is Nothing
End Function
Sub foo()
Dim wbk1 As Workbook
Dim wbk2 As Workbook
Dim shtName1 As String
Dim shtName2 As String
Dim i As Integer
Dim p As Integer
Set wkb1 = Workbooks.Open("C:\Users\lliao\Documents\Trad Reconciliation.xlsx")
Set wkb2 = Workbooks.Open("C:\Users\lliao\Documents\TradReconciliation.xlsx")
i = 2
p = 2
shtName2 = wkb2.Sheets(i).Name
shtName1 = wkb1.Sheets(p).Name
For i = 2 To wkb2.Worksheets.Count
If (SheetExists(shtName2) = True) And (SheetExists(shtName1) = True) Then
For p = 2 To wkb1.Worksheets.Count
If shtName2 = shtName1 Then
wkb2.Sheets(shtName2).Range("D2:G2").Value = wkb1.Sheets(shtName1).Range("D2:G2").Value
End If
Next p
End If
Next i
End Sub
You set shtName2 = wkb2.Sheets(i).Name but then never change it again. So it is always looking at one sheet only.
Your foo subroutine should be changed to:
Sub foo()
Dim wbk1 As Workbook
Dim wbk2 As Workbook
Dim i As Integer
Set wbk1 = Workbooks.Open("C:\Users\lliao\Documents\Trad Reconciliation.xlsx")
Set wbk2 = Workbooks.Open("C:\Users\lliao\Documents\TradReconciliation.xlsx")
For i = 2 To wbk2.Worksheets.Count
If SheetExists(wbk2.Worksheets(i).Name, wbk1) Then
wbk2.Worksheets(i).Range("D2:G2").Value = wbk1.Worksheets(wbk2.Worksheets(i).Name).Range("D2:G2").Value
End If
Next i
End Sub
It is also a good idea to include Option Explicit as the first line of your code module. I had typos in my answer because I had copy/pasted your original code, but you had defined variables wbk1 and wbk2 and then used wkb1 and wkb2 instead. As wkb1 and wkb2 weren't explicitly declared, they were implicitly created as Variant, which then led to problems in code which expected Workbook.
Option Explicit instructs the compiler to force you to explicitly declare all variables, thus picking up such typos.

Copy rows until the last row with value ONLY to another workbook

I was able to copy the rows to another workbook by using predefined ranges. However, I wanted to make sure that it only needs to copy those with values. I've been formulating this code but it returns an error -1004
Private Sub test()
Dim WBa As Workbook, MyPathA As String
Dim FinalRow As Long
Dim getDBsht As Worksheet
MyPathA = "sharepoint.com/Financial Tracker v8.xlsx"
ThisWorkbook.Sheets("ConTracker_DB").UsedRange.ClearContents
' Attempt to open a sharepoint file
Set WBa = Workbooks.Open(MyPathA)
'Set WBb = Workbooks.Open(MyPathB)
Set getDBsht = WBa.Sheets("ConTracker_DB")
getDBsht.UsedRange.Copy
'error starts here
ThisWorkbook.Sheets("ConTracker_DB").UsedRange.Paste
Application.CutCopyMode = False
WBa.Close
Set WBa = Nothing
End Sub
UPDATED CODE: UsedRange fixed my copy rows with value only, but pasting error still persists
You could iterate the individual cells and copy only those which have a value:
Dim sourceCell as Range
Dim targetCell as Range
Set targetCell = ThisWorkbook.Sheets("ConTracker_DB").Range("A1").
For each sourceCell in Range("theNamedRangeYouWantToCopyFrom")
'I'm not sure if you need a dynamic range to copy from, but if you don't...
'...it's much easier to use a "named range" for that.
If sourceCell.Value <> "" Then
targetCell.Value = sourceCell.Value
Set targetCell = targetCell.Offset(1,0)
End If
Next sourceCell
Try defining the final column you need copied and then defining the start and end cells in the range:
FinalCol = 23 '(or whatever you need)
getDBsht.Range(getDBsht.Cells(1, 1), getDBsht.Cells(FinalRow, FinalCol)).Copy
Also note that above I'm specifying which worksheet the cells in the range come from. This can help if you have multiple workbooks/worksheets open at once.
Defining the destination before you start copying is a good idea, too.
CopyTo = ThisWorkbook.Sheets("ConTracker_DB").Range("A1")
Answering my question :))
Basically if you're using usedRange.Copy
you should be pasting with
Cells(1, 1).PasteSpecial Paste:=xlPasteValues
Please find below for the complete code if you're using this:
Private Sub test()
Dim WBa As Workbook, MyPathA As String
Dim FinalRow As Long
Dim getDBsht As Worksheet
MyPathA = "sharepoint.com/Financial Tracker v8.xlsx"
ThisWorkbook.Sheets("ConTracker_DB").UsedRange.ClearContents
' Attempt to open a sharepoint file
Set WBa = Workbooks.Open(MyPathA)
'Set WBb = Workbooks.Open(MyPathB)
Set getDBsht = WBa.Sheets("ConTracker_DB")
getDBsht.UsedRange.Copy
ThisWorkbook.Sheets("ConTracker_DB").Cells(1, 1).PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
WBa.Close
Set WBa = Nothing
End Sub

Copy the value from a cell in a worksheet into a range of cells

I'm intending to conduct a macro which will open up a workbook from the specified path, and loop through its worksheets which has the names "Januari, Februari, Mars" specifically, to deduct the value from C34. C34 has a value recorded there every time, so it shouldn't change. However I want to copy it to the current worksheet, where the first target should be at AA73, the second at AA74 etc. My code is
Sub Test()
Dim myHeadings
Dim i As Long
Dim path As String
path = "C:\pathtofile\file.xlsx"
Dim currentWb As Workbook
Set currentWb = ActiveWorkbook
Dim openWb As Workbook
Set openWb = Workbooks.Open(path)
Dim openWs As Worksheet
myHeadings = Array("Januari", "Februari", "Mars")
For i = 0 To UBound(myHeadings)
Set openWs = openWb.Sheets("&i")
currentWb.Sheets("Indata").Range("AA73+Application.Match(i,Array,False)").Value = openWs.Range("C34").Value
Next i
End Sub
However the compiler says that the subscript is out of range at the row with
Set openWs = openWb.Sheets("&i")
Here I've tried to do "i", i, &i among other things, but it haven't changed. Also I've tried to use "ThisWorkbook" instead of "ActiveWorkbook" but it didn't help either. Does anybody have an input as to how to achieve this in a more proper way?
EDIT: Adapting to the response from Dave, it works to import the sheets. However I get an error in:
currentWb.Sheets("Indata").Range("AA73+Application.Match(i,Array,False)").Value = openWs.Range("C34").Value
Where I get Automation Error -2147221080 (800401a8) at said code snippet.
You have already put your sheet names into an array, so you can just call the sheet name from the array as:
Set openWs = openWb.Sheets(myHeadings(i))

Clear Format of All Valued cells Dim Range VBA Issue

I just started coding a few days back and am trying to use all dim variables, since that's what everyone has been saying to use. So, I am trying to clear formats using current region (basically all cells containing value or formatting). Here is my code and I get a compile error and VBA highlights the "Entire' portion of the last code. Any thoughts? I'm new and I can't figure out what I'm doing wrong.
Sub ClearFormatting()
Dim ws as Worksheet
Dim Entire As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
Set Entire = Range("A1").CurrentRegion
ws.entire.ClearFormats
End Sub
Sub ClearFormatting()
Dim ws as Worksheet
Dim Entire As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
Set Entire = ws.Range("A1").CurrentRegion
Entire.ClearFormats 'no ws.
End Sub