Use the same workbook in multiple modules - excel

I have a workbook with two buttons. So an user can press them to open two workbooks (Input and Output). Then he will copy data from Input to Output. My problem here is that I don't know how to define the same workbook for my subs.
This is the code for opening the files:
Public wb1 As Workbook
Public wb2 As Workbook
Public result As Integer
Public fDialog As FileDialog
Public Sub inputs()
Set fDialog = Application.FileDialog(msoFileDialogOpen)
Set control = Workbooks("Control.xlsm").Worksheets("Control")
fDialog.Title = "Select a file"
fDialog.Title = "Select a file"
If fDialog.Show = -1 Then
If Right(fDialog.SelectedItems(1), 5) = ".xlsx" Or Right(fDialog.SelectedItems(1), 4) = ".xls" Then
Set wb1 = Workbooks.Open(fDialog.SelectedItems(1))
control.Cells(6, 2) = fDialog.SelectedItems(1)
Else
MsgBox ("Please select an excel file")
Exit Sub
End If
End If
End Sub
This is the other sub for copying data:
Public Sub stack()
For Each ws In wb1.Worksheets
'---here is the code for copying data---
Exit For
Exit Sub
When I run this code, of course it gives me this error "object variable or With block not set".
Do you know how can I resolve this? How can I use the same wb1 for both subs?

It's better to limit the scope of your variable whenever possible so what you can do is this:
Public Sub stack()
Dim wbControl As Worksheet
Set wbControl = Workbooks("Control.xlsm").Worksheets("Control")
'Check if there is possible input path in cell B6
If wbControl.Cells(6, 2).Value2 = vbNullString Then
MsgBox "Provide the Input workbook path first!"
Exit Sub
End If
'Check if there is possible output path in cell B6
If wbControl.Cells(6, 2).Value2 = vbNullString Then
MsgBox "Provide the Output workbook path first!"
Exit Sub
End If
'More error checking - e.g. check if both path are valid (file exist?)
Dim wbInput As Workbook
Set wbInput = Workbooks.Open(wbControl.Cells(6, 2).Value2) 'Input path in cell B6
Dim wbOutput As Workbook
Set wbOutput = Workbooks.Open(wbControl.Cells(6, 5).Value2) 'Output path in cell E6
Dim ws As Worksheet
For Each ws In wbInput.Worksheets
'Do whatever you want in here
Next ws
'Remember to close the workbook if not needed later
End Sub
Remove this line from your inputs sub (and also similar one for selecting the output file)
Set wb1 = Workbooks.Open(fDialog.SelectedItems(1))

Please, use the next way:
Declare public variables for both necessary workbooks, on top of the standard module:
Public wb1 As Workbook, wb2 As Workbook
Copy the next sub in a standard module, to open and Set the necessary workbooks:
Sub SetWorbooks()
Dim fdialog As FileDialog, i As Long
Set fdialog = Application.FileDialog(msoFileDialogFilePicker)
For i = 1 To 2
fdialog.Title = "Please, select """ & IIf(i = 1, "Input", "Output") & """ file"
If fdialog.Show = -1 Then
If Right(fdialog.SelectedItems(1), 5) = ".xlsx" Or Right(fdialog.SelectedItems(1), 4) = ".xls" Then
If i = 1 Then
Set wb1 = Workbooks.Open(fdialog.SelectedItems(1))
Else
Set wb2 = Workbooks.Open(fdialog.SelectedItems(1))
End If
Else
MsgBox "Please select an excel file (xls, xlsx)!"
Exit Sub
End If
Else
MsgBox "You should select an Excel file...": Exit Sub
End If
Next i
End Sub
Then use them in this way:
Sub Mystack()
Dim ws As Worksheet
If wb1 Is Nothing Then SetWorbooks 'for cases when having an error and the wb(s) reference have been lost.
For Each ws In wb1.Worksheets
'---here is the code for copying data---
Next
End Sub

Related

Open file, select sheet and copy it to file with macro

this is my first post. I would like to have a code which would let user to choose file with filedialog then populate sheet names from the file to userform and copy selected sheet to workbook with the code.
Private wbSource As Workbook
Private wsSource As Worksheet
Private Sub UserForm_Initialize()
Dim I As Long
Dim filedlg As FileDialog
Set filedlg = Application.FileDialog(msoFileDialogFilePicker)
With filedlg
.Title = "Please select a file to list Sheets from"
.InitialFileName = ThisWorkbook.Path
.ButtonName = "Select"
If .Show <> -1 Then End
End With
Set wbSource = Workbooks.Open(filedlg.SelectedItems(1))
Me.ComboBox1.Clear
With wbSource
For I = 1 To .Worksheets.Count
Me.ComboBox1.AddItem Sheets(I).Name
Next
End With
End Sub
Private Sub ComboBox1_Click()
Set wsSource = wbSource.Worksheets(Me.ComboBox1.Value)
wsSource.Copy ThisWorkbook.Sheets(Sheets.Count)
wbSource.Close SaveChanges:=False
Unload Me
End Sub
The code is working until excel tries copy the sheet, there is a Run-time error 9 - Subscript out of range. Did I declare variables wrongly?

Import a worksheet from another workbook (#2) to current workbook (#1)

I wrote a code that is opening a window in which I can select a the excel workbook (#2) I want to copy and import the worksheet from.
The Code is then checking whether the wanted worksheet (named "Guidance") exists in the opened workbook (#2).If so it should be copied and pasted into the current workbook (#1).
After pasting the worksheet the workbook (#2) should be closed again.
So far the code does what I want it to do, as it opens the window and lets me select the wanted worksheet (named "Guidance") but I have the bug (not sure if the translation is correct)
"Runtime error '9': index out of range"
where the worksheet is supposed to be copied and pasted.
Any help on that would be very much appreciated! Thanks in advance.
Private Function SheetExists(sWSName As String, Optional InWorkbook As Workbook) As Boolean
If InWorkbook Is Nothing Then
Set InWorkbook = ThisWorkbook
End If
Dim ws As Worksheet
On Error Resume Next
Set ws = Worksheets(sWSName)
If Not ws Is Nothing Then SheetExists = True
On Error GoTo 0
End Function
Sub GuidanceImportieren()
Dim sImportFile As String, sFile As String
Dim sThisWB As Workbook
Dim vFilename As Variant
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set sThisWB = ActiveWorkbook
sImportFile = Application.GetOpenFilename("Microsoft Excel Workbooks,
*xls; *xlsx; *xlsm")
If sImportFile = "False" Then
MsgBox ("No File Selected")
Exit Sub
Else
vFilename = Split(sImportFile, "|")
sFile = vFilename(UBound(vFilename))
Application.Workbooks.Open (sImportFile)
Set wbWB = Workbooks("sImportFile")
With wbWB
If SheetExists("Guidance") Then
Set wsSht = .Sheets("Guidance")
wsSht.Copy Before:=sThisWB.Sheets("Guidance")
Else
MsgBox ("No worksheet named Guidance")
End If
wbWB.Close SaveChanges:=False
End With
End If
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
The issue is here
Set wbWB = Worksheets("Guidance") '<-- this should be a workbook not a worksheet?
With wbWB '<-- this with is useless until …
If SheetExists("Guidance") Then
Set wsSht = .Sheets("Guidance") '<-- … until Sheets here starts with a dot
wsSht.Copy Before:=sThisWB.Sheets("Guidance") 'if the error is here then there is no sheet "Guidance" in sThisWB
Else
MsgBox ("No worksheet named Guidance")
End If
wbWB.Close SaveChanges:=False
End With
Also note that SheetExists("Guidance") does not check in a specific workbook (which may fail). I recommend to extend the function to:
Private Function SheetExists(WorksheetName As String, Optional InWorkbook As Workbook) As Boolean
If InWorkbook Is Nothing Then
Set InWorkbook = ThisWorkbook 'fallback if not set
End If
Dim ws As Worksheet
On Error Resume Next
Set ws = InWorkbook.Worksheets(WorksheetName)
SheetExists = Not ws Is Nothing
On Error Goto 0 'necessary because the Err.Number will not be cleared on End Function
End Function
So you can test if a worksheet exists in a specific workbook like
SheetExists("Guidance", sThisWB)
SheetExists("Guidance", wbWB)
Sub GuidanceImportieren()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim sImportFile As String
sImportFile = Application.GetOpenFilename("Microsoft Excel Workbooks, *xls; *xlsx; *xlsm")
If sImportFile = False Then 'false should not be "false"
MsgBox "No File Selected"
Exit Sub
Else
Dim vFilename As Variant
vFilename = Split(sImportFile, "|")
Dim sFile As String
sFile = vFilename(UBound(vFilename))
Dim ImportWorkbook As Workbook
Set ImportWorkbook = Application.Workbooks.Open(sImportFile)
If SheetExists("Guidance", ImportWorkbook) Then
ImportWorkbook.Sheets("Guidance").Copy Before:=ThisWorkbook.Sheets("Guidance")
'you might need to change it into something like this:
Else
MsgBox "No worksheet named Guidance"
End If
ImportWorkbook.Close SaveChanges:=False
End If
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

VBA: If Worksheet name in Workbook equals Combo Box value selected from Userform then copy that Worksheet and paste it into another Workbook

I am working on a Userform that will copy a specific sheet from Workbook A and paste it into Workbook B (essentially archiving that data). The Userform presents the user with a combo-box dropdown to select the sheet name to be copied. I receive a subscript out of range error however when using the sheets.copy command. Here is my code with names modified for ease of reading:
Dim ws as Worksheet
Dim WorkbookA as Workbook
Dim WorkbookB as Workbook
Dim ComboBoxValue as String
Set WorkbookA as ActiveWorkbook
Set WorkbookB as Workbook.Open("C:File Path Here")
With ThisWorkbook
For Each ws In Application.ActiveWorkbook.Worksheets
If ws.Name = UserForm1.ComboBox1.Text Then
ComboBoxValue = ws.Name
Worksheets(ComboBoxValue).Copy _
After:=Workbooks("Workbook B.xlsm").Sheets(Sheets.Count)
' Run-Time 9 Subscript Out of Range Error occurs on line above ^
ActiveSheet.Name = UserForm1.ComboBoxSelection.Text
WorkbookB.Save
WorkbookB.Close
WorkbookA.Activate
Application.CutCopyMode = False
End If
Next ws
End With
The root of your error is improper refenceing of the workbook. There are a lot of other issues, too.
Unnecassary reference to ThisWorkbook
Unnecassary loop through all worksheets
Unnecassary renaming of copied sheet
Unnecassry / incorrect references to the ActiveWorkbook and ActiveSheet
No Error Handling
Improper indenting
Your code, refactored. This is written as a button click event in the UserForm. Update to suit your needs.
Option Explicit
Const ArchiveFilePath As String = "C:\Path\To\ArchiveBook.xlsx"
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Dim WorkbookA As Workbook
Dim WorkbookB As Workbook
Dim wsName As String
Application.ScreenUpdating = False
Set WorkbookA = ActiveWorkbook
wsName = UserForm1.ComboBox1.Text
If wsName = vbNullString Then Exit Sub
On Error Resume Next 'Handle possibility that Open fails
Set WorkbookB = Workbooks.Open(ArchiveFilePath)
On Error GoTo 0
If WorkbookB Is Nothing Then
MsgBox "Failed to open " & ArchiveFilePath, vbOKOnly, "Error"
Exit Sub
End If
'Check if specified ws already exists in WorkbookB
Set ws = GetWorksheet(WorkbookB, wsName)
If Not ws Is Nothing Then
' Sheet already exists. What now?
MsgBox "Sheet " & wsName & " already exists in " & WorkbookB.Name & ". What now?", vbOKOnly, "Error"
WorkbookB.Close
Exit Sub
End If
Set ws = GetWorksheet(WorkbookA, wsName)
If ws Is Nothing Then
MsgBox "Sheet " & wsName & " does not exist in " & WorkbookA.Name, vbOKOnly, "Error"
WorkbookB.Close
Exit Sub
End If
ws.Copy After:=WorkbookB.Sheets(WorkbookB.Sheets.Count)
WorkbookB.Save
WorkbookB.Close
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
Private Function GetWorksheet(wb As Workbook, wsName As String) As Worksheet
On Error GoTo EH
Set GetWorksheet = wb.Worksheets(wsName)
EH:
End Function
Change Sheets(Sheets.Count) to Sheets(Workbooks("Workbook B.xlsm").Sheets.Count)
In this context, Sheets(Sheets.Count) is referring to your source workbook object, so you must specify to count the sheets in the other book.

VBA/Excel - Copy worksheet to another workbook (Replace existing values)

I am trying to copy the values from one sheet, into another workbooks sheet. However I can't get Excel to actually paste the values to the other workbook.
This my code.
Sub ReadDataFromCloseFile()
On Error GoTo ErrHandler
Application.ScreenUpdating = False
Dim src As Workbook ' SOURCE
Dim currentWbk As Workbook ' WORKBOOK TO PASTE VALUES TO
Set src = openDataFile
Set currentWbk = ActiveWorkbook
'Clear existing data
currentWbk.Sheets(1).UsedRange.ClearContents
src.Sheets(1).Copy After:=currentWbk.Sheets(1)
' CLOSE THE SOURCE FILE.
src.Close False ' FALSE - DON'T SAVE THE SOURCE FILE.
Set src = Nothing
ErrHandler:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
And below is the function openDataFile which is used to get the source workbok (File Dialog):
Function openDataFile() As Workbook
'
Dim wb As Workbook
Dim filename As String
Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
fd.AllowMultiSelect = False
fd.Title = "Select the file to extract data"
' Optional properties: Add filters
fd.Filters.Clear
fd.Filters.Add "Excel files", "*.xls*" ' show Excel file extensions only
' means success opening the FileDialog
If fd.Show = -1 Then
filename = fd.SelectedItems(1)
End If
' error handling if the user didn't select any file
If filename = "" Then
MsgBox "No Excel file was selected !", vbExclamation, "Warning"
End
End If
Set openDataFile = Workbooks.Open(filename)
End Function
When I try to run my Sub, it opens the src file and just stops there. No values are copied and pasted to my currentWbk
What am I doing wrong?
Maybe my sub will help u
Public Sub CopyData()
Dim wb As Workbook
Set wb = GetFile("Get book") 'U need use your openDataFile here
Dim wsSource As Worksheet
Set wsSource = wb.Worksheets("Data")'enter your name of ws
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets.Add
wsSource.Cells.Copy ws.Cells
wb.Close False
End Sub

Applying condition to processRange function below and perform loop

[table - worksheet "output - flat"][1]
I have code below that checks to see if column "NamedRange" in the table attached appears as a named range in the (dstRng) template and if it does exist it returns the value to the right ("report balance"). How can I add a condition where when the user chooses a template it will only return values based on the Ted ID - in the table attached. I have 2 templates and it loops through the two templates however I want the first template to only return values for Ted ID 10004 and template 2 it will only return values for Ted ID 11372 and etc. etc. Hope that makes sense... let me know if u have any questions
Option Explicit
Sub Button4_Click()
Dim Desktop As Variant
Dim Files As Object
Dim Folder As Variant
Dim oShell As Object
Dim Tmplts As Variant ' Templates folder
Dim wsLocal As Worksheet
Dim wsGroup As Worksheet
Dim wb As Object
' Check Box 2 "Select All" must be checked to run the macro.
If ActiveSheet.Shapes("Check Box 2").ControlFormat.Value = xlOff Then Exit Sub
Application.ScreenUpdating = False
Application.EnableEvents = False
' Prompt user to locate the Templates folder.
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = True Then
Tmplts = .SelectedItems(1)
Else
Exit Sub
End If
End With
Set oShell = CreateObject("Shell.Application")
Set Desktop = oShell.Namespace(0)
' Create the Output folder on the User's Desktop if it does not exist.
Set Folder = Desktop.ParseName("Output")
If Folder Is Nothing Then
Desktop.NewFolder "Output"
Set Folder = Desktop.ParseName("Output")
End If
Set Files = oShell.Namespace(Tmplts).Items
Files.Filter 64, "*.xlsm"
For Each wb In Files
Set wb = Workbooks.Open(Filename:=wb.Path, UpdateLinks:=False)
Call BreakLinks(wb)
On Error Resume Next
Set wsLocal = wb.Worksheets("RVP Local GAAP")
Set wsGroup = wb.Worksheets("RVP Group GAAP")
'unprotect workbook
wsLocal.Unprotect Password:="KqtgH5rn9v"
wsGroup.Unprotect Password:="KqtgH5rn9v"
On Error GoTo 0
' Check that both worksheets exist before updating.
If Not wsLocal Is Nothing And Not wsGroup Is Nothing Then
Call ProcessNamedRanges(wb)
'lock the workbook
wsLocal.Protect Password:="KqtgH5rn9v"
wsGroup.Protect Password:="KqtgH5rn9v"
''MsgBox "Ranges have been updated sucessfully."
' Save the workbook to the folder and close.
On Error Resume Next
wb.SaveAs Filename:=Folder.Path & "\" & wb.Name
ActiveWorkbook.Close True
On Error GoTo 0
End If
Next wb
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Sub ProcessNamedRanges(ByRef wb As Workbook)
Dim dstRng As Range
Dim rng As Range
Dim rngName As Range
Dim rngNames As Range
Dim wks As Worksheet
Set wks = ThisWorkbook.Sheets("Output - Flat")
' Exit if there are no named ranges listed.
If wks.Range("D4") = "" Then Exit Sub
Set rngNames = wks.Range("D4").CurrentRegion
Set rngNames = Intersect(rngNames.Offset(1, 0), rngNames.Columns(2))
'Loop through all the values in NamedRange
For Each rngName In rngNames
' Verify the Named Range exists.
On Error Resume Next
Set dstRng = wb.Names(rngName.Text).RefersToRange
If Err = 0 Then
'Copy the report balance to the Template worksheet in column "G".
dstRng.Value = rngName.Offset(0, 1).Value
Else
'answer = MsgBox("The Named Range """ & rngName.Value & """ Does Not Exist" & vbLf & vbLf & "Continue?", vbYesNo + vbExclamation)
'If answer = vbNo Then Exit Sub
End If
On Error GoTo 0
Next rngName
End Sub
Sub BreakLinks(ByRef wb As Workbook)
Dim i As Long
Dim wbLinks As Variant
wbLinks = wb.LinkSources(xlExcelLinks)
If Not IsEmpty(wbLinks) Then
For i = 1 To UBound(wbLinks)
ActiveWorkbook.BreakLink wbLinks(i), xlLinkTypeExcelLinks
Next i
End If
End Sub

Resources