Copying range of cells from workbooks based on sheetname - vba

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.

Related

How to quickly switch what worksheet/workbook is being edited in VBA

Basically, I want my program to open a hyperlink to another workbook and copy a range of values onto my original workbook. The problem is, I don't know how to properly reference the workbook to "paste" onto
I've tried to replicate a lot of different internet examples. I've tried using "Set" and "With" to switch between them and I've tried to make the original workbook the active workbook before pasting and nothing has been working.
Private Sub findColumns_button_Click() 'userform code
Dim index As Integer, hyperlink_A As Variant, Wb As Worksheet, mainWorkbook As Variant
mainWorkbook = ActiveWorkbook.FullName
Worksheets("Data").Cells(2, 2) = ResultA_Combo.Value
index = findIndex(Cells(2, 2).Value)
hyperlink_A = findHyperlink(index)
Worksheets("Data").Cells(3, 2) = hyperlink_A
Workbooks.Open Filename:=hyperlink_A 'opens correctly
Dim test As Double
test = Worksheets("Data").Range("S23")
MsgBox test 'displays correct value from desired workbook
Workbooks.Activate Filename:=mainWorkbook 'not sure what to do here
End Sub
MsgBox test returns the desired value but I can't find a way to set a cell value in the original workbook equal to test
See if this helps, I've edited your code, and by comparing I hope you get in the right direction... see comments in code for more details:
Private Sub findColumns_button_Click() 'userform code
Dim index As Integer, hyperlink_A As Variant, Wb As Worksheet, mainWorkbook As Workbook
Dim wbSrc As Workbook
Set mainWorkbook = ActiveWorkbook
With mainWorkbook.Worksheets("Data")
.Cells(2, 2) = ResultA_Combo.Value
index = findIndex(.Value)
hyperlink_A = findHyperlink(index)
.Cells(3, 2) = hyperlink_A
End With
Set wbSrc = Workbooks.Open(Filename:=hyperlink_A) 'Allocate to variable and open at the same time
Dim test As Double
test = mainWorkbook.Worksheets("Data").Range("S23")
MsgBox test 'displays correct value from first workbook
mainWorkbook.Activate 'as long you fully qualify the ranges, you don't need and should avoid as much as possible to use .Activate & .Select
Dim test2 As Double
wbSrc.Worksheets(1).Range("A1") = mainWorkbook.Worksheets("Data").Range("S23") * 2
test2 = wbSrc.Worksheets(1).Range("A1")
MsgBox test2 'displays correct value from second workbook
End Sub

Can't define workheet in VBA

Going crazy here. I use this definition of worksheet all the time. Copied every string to avoid typing errors. Still, the code below produces "Nothing" when I try to set FR worksheet. Pls help!
Sub FindReplace()
Dim FRep As Worksheet
Dim c As Range
Dim cText As TextBox
Dim i As Integer
Set FRep = ThisWorkbook.Worksheets("FindReplace")
For i = 1 To 23
cText = FRep.Cells(i, 3).Text
FRep.Cells(i, 2).NumberFormat = "#"
FRep.Cells(i, 2).Value = cText
Next i
The code as is seems correct. Make sure that "FindReplace" worksheet is in ThisWorkbook.
Also, you can try to get "FindReplace" worksheet by CodeName instead of by the name of the sheet. The advantage is that if the user changes the name of the worksheet, the CodeName will remain the same and you won't need to update your code to the new worksheet name.
Public Function GetWsFromCodeName(codeName As String, wb As Workbook) As Worksheet
Dim ws As Worksheet
For Each ws In wb.Worksheets
If ws.CodeName = codeName Then
Set GetWsFromCodeName = ws
Exit For
End If
Next ws
End Function
Add this function in your code:
Sub FindReplace()
Dim FRep As Worksheet
Set FRep = GetWsFromCodeName("YourCodeName", ThisWorkbook)

Splitting Sheets into Separate Workbooks

I have a workbook with a master sheet for school report cards. I have a macro applied to a button for exporting information from the master sheet to separate, newly-generated sheets in the same workbook. A1:C71 is the template and goes to every new sheet, and the following columns of info, from D1:71 to Q1:71, each appear in separate sheets (always in D1:71).
Here's the screenshot (http://imgur.com/a/ZDOVb), and here's the code:
`Option Explicit
Sub parse_data()
Dim studsSht As Worksheet
Dim cell As Range
Dim stud As Variant
Set studsSht = Worksheets("Input")
With CreateObject("Scripting.Dictionary")
For Each cell In studsSht.Range("D7:Q7").SpecialCells(xlCellTypeConstants, xlTextValues)
.Item(cell.Value) = .Item(cell.Value) & cell.EntireColumn.Address(False, False) & ","
Next
For Each stud In .keys
Intersect(studsSht.UsedRange, studsSht.Range(Left(.Item(stud), Len(.Item(stud)) - 1))).Copy Destination:=GetSheet(CStr(stud)).Range("D1")
Next
End With
studsSht.Activate
End Sub
Function GetSheet(shtName As String) As Worksheet
On Error Resume Next
Set GetSheet = Worksheets(shtName)
If GetSheet Is Nothing Then
Set GetSheet = Sheets.Add(after:=Worksheets(Worksheets.Count))
GetSheet.Name = shtName
Sheets("Input").Range("A1:C71").Copy
GetSheet.Range("A1:D71").PasteSpecial xlAll
GetSheet.Range("A1:B71").EntireColumn.ColumnWidth = 17.57
GetSheet.Range("C1:C71").EntireColumn.ColumnWidth = 54.14
GetSheet.Range("D1:D71").EntireColumn.ColumnWidth = 22
End If
End Function`
I would now like to create a separate button to split the sheets into separate workbooks so that the master sheet can be kept for record keeping and the individual workbooks can be shared with parents online (without divulging the info of any kid to parents other than their own). I would like the workbooks to be saved with the existing name of the sheet, and wonder if there's a way to have the new workbooks automatically saved in the same folder as the original workbook without having to input a path name? (It does not share the same filename as any of the sheets).
I tried finding other code and modifying it, but I just get single blank workbooks and I need as many as have been generated (preferably full of data!), which varies depending on the class size. Here's the pathetic attempt:
`Sub split_Reports()
Dim splitPath As String
Dim w As Workbook
Dim ws As Worksheet
Dim i As Long, j As Long
Dim lastr As Long
Dim wbkName As String
Dim wksName As String
Set wsh = ThisWorkbook.Worksheets(1)
splitPath = "G:\splitWb\"
Set w = Workbooks.Add
For i = 1 To lastr
wbkName = ws
w.Worksheets.Add(After:=w.Worksheets(Worksheets.Count)).Name = ws
w.SaveAs splitPath
w.Close
Set w = Workbooks.Add
Next i
End Sub`
I have learned so much, and yet I know so little.
Maybe this will start you off, just some simple code to save each sheet as a new workbook. You would probably need some check that the sheet name is a valid file name.
Sub x()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Sheets
ws.Copy
ActiveWorkbook.Close SaveChanges:=True, Filename:=ws.Name & ".xlsx"
Next ws
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))

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

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