Excel VBA macro to copy certain columns to another Workbook - vba

I need to copy certain columns of one spreadsheet to another spreadsheet.
In order to do so, I have a macro:
Sub Submit()
Dim sourceColumn As Range, targetColumn As Range
Set sourceColumn =
Workbooks("Submission_Form.xlsm").Worksheets("RGSheet").Columns("A")
Set myData = Workbooks.Open("I:\Projects\...\Macros\RG.csv")
Worksheets(1).Select
Worksheets(1).Range("A1").Select
Set targetColumn = Workbooks("RG.csv").Worksheets(1).Columns("A")
sourceColumn.Copy Destination:=targetColumn
End Sub
However, when the cursor hits targetColumn, it gives error:
Run-time error '9':
Subscript out of range
For the sake of simplicity, I have put RG.csv in the same folder as Submission_Form.xlsm. So I am really confused why is it giving error.
I would also like to know how to handle if the RG.csv is located in another directory.

The error is probably because Submission_Form.xlsm isn't opened(?). Your code looks a little inconsistent. Maybe just open both source and destination, and copy the column. Something like this?
Option Explicit
Sub Submit()
Dim vSourceWorkbook As Workbook
Dim vDestinationWorkbook As Workbook
Set vSourceWorkbook = Workbooks.Open("Submission_Form.xlsm")
Set vDestinationWorkbook = Workbooks.Open("I:\Projects\...\Macros\RG.csv")
vSourceWorkbook.Worksheets("RGSheet").Range("A:A").Copy Destination:=vDestinationWorkbook.Worksheets(1).Range("A:A")
End Sub

Related

Why does assigning a reference in my spreadsheet sometimes work and sometimes not?

I have a few cells in my excel workbook which are available for a client to put his own values. I wanted the workbook to initialize those cells with default values. In order to do so I have a worksheet "Arkusz do makr", where I store the values.
In a module "GM" I declare a variable to reference my worksheet easier like this:
Public M As Worksheet
Then I initialize this variable and set my default values like this (in ThisWorkbook):
Private Sub Workbook_Open()
Set M = Worksheets("Arkusz do makr")
Worksheets("Values").Range("Value1") = M.Range("Value1")
Worksheets("Values").Range("Value2") = M.Range("Value2")
Worksheets("Values").Range("Value3") = M.Range("Value3") `etc
End Sub
Now sometimes this works like a charm, and sometimes, when I open the workbook I get a
Run-time error '91': Object variable or With block variable not set.
Could someone please explain this behaviour to me? Additionally I would like to ask if my approach makes sense, since I have a hard time grasping the order of events in excel as well as the range of its objects.
EDIT: Additionally I should mention that the Debug function highlights the first Worksheets... line in my code. In specific worksheets I reference the M object as well, though I thought it changes anything here...
Try to change the code of this Sub like below.
I have added a simple error handling - if there is no worksheet "Arkusze do makr" or "Values" in your workbook, warning message is displayed and default values are not copied.
You can find more comments in code.
Private Sub Workbook_Open()
Dim macrosSheet As Excel.Worksheet
Dim valuesSheet As Excel.Worksheet
'------------------------------------------------------------------
With ThisWorkbook
'This command is added to prevent VBA from throwing
'error if worksheet is not found. In such case variable
'will have Nothing as its value. Later on, we check
'the values assigned to those variables and only if both
'of them are different than Nothing the code will continue.
On Error Resume Next
Set macrosSheet = .Worksheets("Arkusz do makr")
Set valuesSheet = .Worksheets("Values")
On Error GoTo 0 'Restore default error behaviour.
End With
'Check if sheets [Values] and [Arkusz do makr] have been found.
'If any of them has not been found, a proper error message is shown.
'In such case default values are not set.
If valuesSheet Is Nothing Then
Call VBA.MsgBox("Sheet [Values] not found")
ElseIf macrosSheet Is Nothing Then
Call VBA.MsgBox("Sheet [Arkusz do makr] not found")
Else
'If both sheets are found, default values are copied
'from [Arkusz do makr] to [Values].
'Note that if there is no Range named "Value1" (or "Value2" etc.)
'in any of this worksheet, another error will be thrown.
'You can add error-handling for this case, similarly as above.
With valuesSheet
.Range("Value1") = macrosSheet.Range("Value1")
.Range("Value2") = macrosSheet.Range("Value2")
.Range("Value3") = macrosSheet.Range("Value3")
End With
End If
End Sub

Excel: How to program to have Excel read a cells contents then switch open a new worksheet?

I'm very new to programming (1 day experience) and I am trying to build an interactive database but I keep running into issues with having a certain part work.
I want Excel to read the value selected in a certain cell and based on the value in that cell then have it open to a separate sheet, where I can begin another set of data entry.
I have tried a number of different options but as of now, my code looks like this:
Dim inputWks As Worksheet
Set inputWks = ("Input")
With inputWks
If Range("D13").contents = "Yes" Then
ActiveWorkbook.Sheets("Sheets2").activate
End If
End With
I know this is a simple question but I have not been able to have this work..
try this
Sub DoIt()
Dim inputWks As Worksheet
Set inputWks = ActiveWorkbook.Sheets("Input")
With inputWks
If Range("D13").Cells(1, 1) = "Yes" Then
ActiveWorkbook.Sheets("Sheets2").Activate
End If
End With
End Sub

Store COPY of a worksheet in worksheet variable

What I want to achieve:
I want to assign copy of a worksheet to variable, for later use.
What I tried and results
First : The code below works fine. Something like this I would like to achieve, but using worksheet.copy.
Sub DuplicateSheetRenameFirst()
Dim wsDuplicate As Worksheet
Set wsDuplicate = Worksheets.Add
wsDuplicate.Name = "Duplicate"
End Sub
Second : Using the copy method, creates a worksheet in current workbook, but generates a Runtime error 424 - Object required.
Sub DuplicateSheetRenameSecond()
Dim wsDuplicate As Worksheet
Set wsDuplicate = Worksheets("Sheet1").Copy(after:=Worksheets(Worksheets.Count))
'above line : runtime error 424 object required, but the sheet is created
wsDuplicate.Name = "Duplicate"
End Sub
Third : Creates a worksheet in new workbook (so creates book, then sheet), but still generates the same Runtime error 424 - Object required.
Sub DuplicateSheetRenameThird()
Dim wsDuplicate As Worksheet
Set wsDuplicate = Worksheets("Sheet1").Copy
'above line : runtime error 424 object required, but the sheet is created in new workbook
wsDuplicate.Name = "Duplicate"
End Sub
Workaround : I can modify any of the second or third way to at first copy the sheet and then set the variable to activesheet, but I was wandering if there is a one step way of doing this. I'm not sure if this would work all the time, since the activesheet may not be the one just copied, maybe.
The Question:
Is there a simple (one step) way to store the copy of a worksheet in a variable? Preferably without errors or without filtering the error with error handler.
This is maybe ok?
Sub copySheet()
Dim ws As Excel.Worksheet
Excel.ThisWorkbook.Sheets("Sheet1").Copy After:=Sheets(1)
Set ws = Excel.ThisWorkbook.ActiveSheet
End Sub
It is unfortunate that in this case you need to use an Active... object. Generally it is good practice to avoid Active... objects.
You cannot do this though as the method .copy is not returning an object of the worksheet class:
Sub copySheet()
Dim ws As Excel.Worksheet
Set ws = Excel.ThisWorkbook.Sheets("Sheet1").Copy(After:=Sheets(1))
End Sub
Some further explanation is in this previous post:
Why does Worksheet.Copy not return a reference to the new workbook created
In MSDN it is not altogether obvious that the method returns nothing:
https://msdn.microsoft.com/EN-US/library/office/ff837784.aspx
...but in your friend Excel's Object Explorer it is more obvious. If it returned a worksheet object then by the arrow would read:
Sub Copy([Before], [After]) as Worksheet

Excel VBA Can't access sheet on external workbook

I have created a custom function in Excel using VBA. I'm trying to get data from a different workbook using the Workbooks.Open(path) command. Here's my code:
Option Explicit
Function TestFunction() As String
mySub
TestFunction = "Success."
End Function
Sub mySub()
Dim path As String
Dim wk As Workbook
path = "C:\Users\jg\Desktop\machine_data.xlsm"
Set wk = Workbooks.Open(path)
Dim ws As Worksheet
Set ws = wk.Sheets(1)
Debug.Print ws.Range("A2")
End Sub
Sub Test()
Debug.Print (TestFunction())
End Sub
Now my problem is the following:
When I run the Sub Test() within the VBA environment from Excel everything works as planned. machine_data.xlsm gets opened and the field A2 shows up in debug.
Once I go to the workbook where I defined this module in and type =TestFunction() into a cell, I get a #VALUE!. The file also doesn't get opened.
If I comment these two lines:
Set ws = wk.Sheets(1)
Debug.Print ws.Range("A2")
the cell will show Success!, but the file still doesn't open.
What am I doing wrong? Both workbooks are .xlsm files. I am using Microsoft Office Excel 2007.
Just throw everything from mySub into the test function and if everything is successful have test function return the value of the cell. So testFunc = ws.Range("A2").
As DaveU already stated UDFs can only return values. I found a different workaround simply calling the function from within the VBA environment which lets me modify cell contents wherever I'd like.

How to add a new spreadsheet with VBA-Code, using VBA

I am creating a macro and part of the macros function is to make VBA create a new spreadsheet. Because of the nature of distribution the name will change. I need to add code to this spreadsheet. Is there anyway I can do this?
Jook has already explained how it works. I will take it a step further.
The syntax of adding a worksheet is
expression.Add(Before, After, Count, Type)
If you check inbuilt Excel's help then you can see what Before, After, Count, Type stands for
FROM EXCEL"S HELP
Parameters (All 4 parameters are Optional)
Before - An object that specifies the sheet before which the new sheet is added.
After - An object that specifies the sheet after which the new sheet is added.
Count - The number of sheets to be added. The default value is one.
Type - Specifies the sheet type. Can be one of the following XlSheetType constants: xlWorksheet, xlChart, xlExcel4MacroSheet, or xlExcel4IntlMacroSheet. If you are inserting a sheet based on an existing template, specify the path to the template. The default value is xlWorksheet.
Once the sheet is created then you need to use .insertlines to create the relevant procedure and to also embed the code that you want to run.
NOTE - IMP: If you want the code to embed code in the VBA project, you need to ensure that you have "Trust Access to the VBA Project Object Model" selected. See snapshot.
Here is an example where I am creating a sheet and then embedding a Worksheet_SelectionChange Code which will display a message "Hello World"
CODE - TRIED AND TESTED
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim nLines As Long
Dim VBP As Object, VBC As Object, CM As Object
Dim strProcName As String
Set ws = Worksheets.Add
Set VBP = ThisWorkbook.VBProject
Set VBC = VBP.VBComponents(ws.Name)
Set CM = VBC.CodeModule
strProcName = "Worksheet_SelectionChange"
With ThisWorkbook.VBProject.VBComponents( _
ThisWorkbook.Worksheets(ws.Name).CodeName).CodeModule
.InsertLines Line:=.CreateEventProc("SelectionChange", "Worksheet") + 1, _
String:=vbCrLf & _
" Msgbox ""Hello World!"""
End With
End Sub
This is how the new sheet code area looks once you run the above code.
the following code will add you a spreadsheet.
Public Sub Workbook_Add()
Dim wks As Worksheet
Set wks = ThisWorkbook.Worksheets.Add(, , 1, xlWorksheet)
With wks
'set codename of wks
ThisWorkbook.VBProject.VBComponents(.CodeName).Name = "tblWhatever"
'set tablename of wks
.Name = "whatever"
'add code (untested demo)
'ThisWorkbook.VBProject.VBComponents(.CodeName).CodeModule.InsertLines 1, "Option Explicit"
'add code (as of example from excel-help)
'Application.VBE.CodePanes(1).CodeModule.InsertLines 1, "Option Explicit"
End With
End Sub
If you need to add VBA-Code to this specific spreadsheet, you should further inspect the VBProject object - look for CodeModule and then i.e. InsertLines.
A further hint for you - I would try to use the CodeNames of your tables. It is less likely to be changed - BUT it might be not that comfortable to use in your code at first. I had to get used to it, but for me it has many advantages against using a tables name.
Hope this helps ;)
The default .Add method adds a sheet at the start of the list. Often you want to add it at the end before adding the code lines, as explained by Siddarth Rout. To do that anywhere you can use:
ActiveWorkbook.Worksheets.ADD After:=ActiveWorkbook.Sheets(ActiveWorkbook.Worksheets.Count)
It is easier to read if you have defined and set WB:
Dim WB as Excel.workbook
Set WB = ActiveWorkbook
WB.Sheets.ADD After:=WB.Sheets(WB.Sheets.Count)
Set VBC = ActiveSheet 'If using in Siddarth Rout's code above
Sheets and Worksheets are interchangeable, as illustrated.