Referencing data from another workbook in an array - vba

I am currently using the below code to define an array from the active workbook
Dim MyRangeArray As Variant
MyRangeArray = Array(Sheet1.Range("A4:N19"), Sheet2.Range("A4:N19"))
I want this array to reference data from another workbook instead of the workbook which has the code. The result i am looking for is:
MyRangeArray= Array(Wb1.sheets.RangeX,wb2.sheets.rangeX)
Can somebody help?

In your first example you are using sheet Code Names, which will reference sheets in the book containing the code, irrespective of if that book is active.
To reference a different workbook, again irrespective of if it's active, create references to the workbook and worksheet objects
Dim MyRangeArray As Variant
Dim wb As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set wb = Application.Workbooks("NameOfWorkbook.xlsx")
Set ws1 = wb.Worksheets("NameOfSheet1")
Set ws2 = wb.Worksheets("NameOfSheet2")
MyRangeArray = Array(ws1.Range("RangeAddress1").Value, ws2.Range("RangeAddress2").Value)

I resolved the error by doing the following:
Dim r1,r2 as range
r1=ws1.Range("RangeAddress1")
r2=ws2.Range("RangeAddress2")
Mrangearray=array(r1,r2)

Related

Specify the workbook when working on a worksheet in VBA

I would like to get the value of cell. I have multiple workbooks, and some of the workbooks have sheets with the same name.
For example, test.xlsx and test2.xlsx both has a sheet named sheet1.xlsx
So, when working on a sheet, I would like to specify the workbook. I use wb.sh.*expression* all the time, and I am surprised that this does not work.
What am I missing here conceptually?
Code:
set wb1 = Workbooks("Test1.xlsx")
Set sh1 = Worksheets("Sheet1")
Debug.Print wb1.sh1.Range("A1").Value
Code which would work, but is not specific enough:
set wb1 = Workbooks("Test1.xlsx")
Set sh1 = Worksheets("Sheet1")
Debug.Print sh1.Range("A1").Value
Note: Test1.xlsx has a sheet named Sheet1
When you open the workbook, the Open method gives you the Workbook object reference - hold on to it instead of discarding it:
Dim wb As Workbook
Set wb = Workbooks.Open(path)
That way you never need to query the Workbooks collection and supply a hard-coded file name to get your workbook.
Next up, the Worksheet reference:
Set sh1 = Worksheets("Sheet1")
The Worksheets collection is a property that belongs to a Workbook object. Indeed, that's not "specific" enough: if you don't qualify the property call, then you're implicitly referring to ActiveWorkbook - which may or may not be the workbook you need to be using.
That's where that wb reference comes into play:
Set sh1 = wb.Worksheets("Sheet1")
Lastly, what you have here:
Debug.Print wb1.sh1.Range("A1").Value
Is not only illegal, it's overkill: sh1 already knows what Workbook object it belongs to - you can get that object reference through sh1.Parent and compare it to the wb reference:
Debug.Assert sh1.Parent Is wb
sh1 is a local variable, not a member of the Workbook interface: that's why you can't do wb1.sh1.
I use wb.sh.expression all the time
If your code ever worked, I guarantee you don't.

Excel VBA: Moving a sheet to a new workbook while maintaining worksheet object association

The goal here is to set a worksheet object, then move that worksheet to a new workbook and continue to use that worksheet object. However, by moving that worksheet it appears that the worksheet object previously associated with it is lost.
To test:
Lets say we have two excel workbooks in the same folder named Book1.xlsb and Book2.xlsb each with one sheet in them named Sheet1. When we open Book1 we put in the below sub and try to move a sheet from the other using a worksheet object.
Everything "works", but the worksheet object is lost in the process, and throws an error as soon as you try to use it again. Is it possible to move the worksheet to a new workbook and not lose that worksheet object association so that it can be referenced later?
Option Explicit
Sub test()
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim ws As Worksheet
Set wb1 = ThisWorkbook
Set wb2 = Workbooks.Open("Book2.xlsb")
Set ws = wb2.Sheets(1)
ws.Name = "Sheet2" 'name changed to avoid conflict with the one already there
ws.Move wb1.Sheets(1)
MsgBox ws.Name 'this line throws an error, indicating that ws association has been lost
End Sub
Edit:
If this is not possible, how can we reliably re-set that worksheet object to the one that we just moved?
To reset the ws object:
Set ws = wb1.WorkSheets("Sheet2")
If you dont know the name, you know it was moved to the last position, right?
Set ws = wb1.WorkSheets(wb1.WorkSheets.Count)
If it was moved to the first position, then:
Set ws = wb1.WorkSheets(1)
In your code
ws.Move wb1.Sheets(1)
You alreay moved the sheet ws to the first sheet of the Book2.xlsb file
"Sheets(1)" means the first sheet of the file
So you can reset ws like this.
Set ws = wb1.Sheets(1)

How to refer to a Excel Worksheet by its VBA Object Name in another Workbook?

I have two Excel Workbooks:
Source.xlsx
Tool.xlsm
Source.xlsx contains a Worksheet with the VBA Object Name shtTests:
Let's assume that in Tool.xlsm I have a variable that contains a reference to the Workbook stored in Source.xlsx:
Dim wkbSource as Workbook
Set wkbSource = GetSourceWorkbook() ' Some function that gives a reference to the workbook
Core Question: How can I reference shtTests within Tool.xlsm by using shtTests' VBA Name?
Or to formulate the question as code... assume you have this code snippet:
Dim wkbSourceShtTests as Worksheet
Set wkbSourceShtTests = GetShtTestsFromWkbSources(wkbSources)
Question: What does GetShtTestsFromWkbSources have to look like?
Note: I do not want to reference it by its Excel Name like you would do using wkbSources.Worksheets("Test Cloning") because people might change its Excel Name some day.
Is this what you are trying?
Sub Sample()
Dim wbThis As Workbook, wbThat As Workbook
Dim wsThat As Worksheet
Dim wsCodeName As String
Set wbThis = ThisWorkbook
Set wbThat = Workbooks("Book4") '<~~ Change this to relevant workbook
wsCodeName = "ShtSheets"
Set wsThat = wbThat.Worksheets(CStr(wbThat.VBProject.VBComponents(wsCodeName).Properties(7)))
Debug.Print wsThat.Name
End Sub
Note: For this to work, you need to enable access to Visual Basic Projects
On the File menu Excel, Click Options|Trust Center|Trust Center Settings|Macro Settings, Check the box "Trust Access to the VBA Project Object Model"
If you wanted a function instead of setting up the trusted access then this would probably work:
Sub example()
Dim wkbSource As Workbook
Set wkbSource = GetSourceWorkbook()
Dim wkbSourceShtTests As Worksheet
Set wkbSourceShtTests = GetShtTestsFromWkbSources(wkbSource, "shtTests")
End Sub
Function GetShtTestsFromWkbSources(wkbk As Workbook, codename As String) As Worksheet
For Each sht In wkbk.Sheets
If sht.codename = codename Then Set GetShtTestsFromWkbSources = sht
Next
End Function

Working with Named Ranges and Objects

I need to copy a range of cells from one workbook to another. However, unfortunately, because of the size of the two workbook I can't have them open at the same time.
So the idea was to do it in two steps:
1) Open workbook1 save the range from one workbook to a object range and close workbook1
2) Open workbook2 save the range from the object to the range in workbook
But this is not working. Could someone help with the code. Thanks. Sample code below
Dim Temp as Range
Workbooks.Open (Model1)
Workbooks(Model1).Activate
Temp = Range("First_Input").Value
Workbook(Model1).Close
Workbooks.Open(Model2)
Workbooks(Model2).Activiate
Range("Second_Input").Value = Temp.Value
A working example below:
Comments are embedded and works as is (without changes). Try this on a
workbooks first with random data.
The example works for a workbook already open, just alter it for "Opening" a workbook.
I have used the range address in the example. You can play with this depending on what you want to do.
The below works so should be easy to implement, copy and paste into excel.
Public Sub CopyData()
Dim wkb1 As Workbook
Dim wkb2 As Workbook
Dim sht1 As Worksheet
Dim sht2 As Worksheet
Dim wkb1rng As Range
Dim wkb2rng As Range
'Point to Workbook and Sheet 1
'Set wkb1 = Workbooks.Open(Model1) ' To Open Workbook
Set wkb1 = Workbooks("Book1") ' If workbook is open already
'Sheets is the Index use String for the sheet name
Set sht1 = wkb1.Sheets(1)
' Dont need this if you moving objects directly in and out of memory.
' Workbooks(Model1).Activate
' Point to Range
Set wkb1rng = sht1.Range("First_Input")
' What is the address of the Range
Dim address As String
address = wkb1rng.Cells.address
'Point to Workbook and Sheet 2
Set wkb2 = Workbooks("Book2")
'Sheets is the Index use String for the sheet name
Set sht2 = wkb2.Sheets(1)
'I imagine Second_Input should be output?
'Use this only if the data range is exactly the same size
'Set wkb2rng = Range("Second_Output")
'else use this ...
Set wkb2rng = sht2.Range(address)
'Copy data across ...
wkb2rng.Value = wkb1rng.Value
End Sub

VBA Macro workbook.open or workbook.activate through variable reference

How do I reference my primary workbook and the second workbook I open through this sub procedure? I attempt to do workbooks.("client_path").activate as my goal with this macro is to open a separate workbook, which is assigned to variable client_path and reconcile every (1 to 200) values in column A:A with all the values of column K:K of my primary workbook. If a value is found on the client_path workbook (again column A:A), but not on my primary workbook (again column K:K) - I would like to add the unique value to column M:M of my primary workbook. Opposite logic, I would like any value found on my primary workbook but not found on my client_path workbook to appear in column N:N of my primary workbook.
The name of my the primary workbook which I am developing this code is title "Client DIRTY watchlist" The contents of workbook client_path update daily and are useless as time passes.
Do I need to create a function to accomplish this variable workbook reference?
Sub Client_Dirty_Recon()
Dim Client_path As String
Dim Client_watchlist As Workbook
Dim Client_client_email As Workbook
Set Client_watchlist = ActiveWorkbook
Dim email_range As Range
Dim watchlist_range As Range
Application.ScreenUpdatClient = False
Client_path = Range("Path")
Workbooks.Open Client_path
Dim recon_list As Range
'For Each n In recon_list:
Dim i As Variant
For i = 1 To 200
Set email_range = ActiveWorkbook.ActiveSheet.Range("A" & i)
Dim b As Variant
For Each b In email_range
Set watchlist_range = Sheets("Client DIRTY watchlist").Range("B:B")
'if b
Next b
Next i
End Sub
Can you just make references to your workbook earlier?
Dim wb as workbook
Dim wbDirty as workbook
set wb = thisWorkbook
set wbDirty = workbooks.open Client_Path
Then when you define the ranges, Excel knows which workbook they belong to.
Dim rngReconcile as range
Dim rngWatch as range
set rngReconcile = wb.Sheets(1).Range("K:K")
set rngWatch = wbDirty.Sheets("Client DIRTY watchlist").Range("B:B")
Then continue on with your looping code
dim Wb as workbook
set wb= Workbooks.Open (Client_path).activate
this opens, and activates it all in one line, an sets a variable for later use (wb).
note that refering later to wb will NOT open it again, and NOT activate it again, its just reference to the wb ! (unless you tell him to)