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

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)

Related

Excel VBA: Counting Data in Column from Another Workbook and Inputting Counter in Master Workbook

I need to create a macro in my CountResults.xlsm (Master Workbook) that solves the following problem. I have a column of data in another worksheet with either YES or NO. I need to come up with a macro that counts the amount of "YES" in the column. The column is located in Sheet2 of the workbook Test01.xlsx. Then take that count and put it in one cell in my CountResults.xlsm file. Like so:
I have a code that displays a count for a column in the same sheet. But this code does not count when there are 'breaks' in the column (empty spaces) like I have in my picture. This is that code:
Private Sub CommandButton1_Click()
MsgBox Range("A1").End(xlDown).Row
Range("A1").End(xlDown).Offset(1, 0).Select
End Sub
I have another code that helps with accessing another workbook and defining values for each workbook and worksheet:
Dim wbSource As Workbook
Dim wbTarget As Workbook
Dim shSource As Worksheet
Dim shTarget As Worksheet
Set wbSource = Workbooks.Open(Filename:="C:\Users\khanr1\Desktop\Test_Excel\Test03.xlsm", ReadOnly:=True)
Set wbTarget = ThisWorkbook
Set shSource = wbSource.Worksheets("Sheet2")
Set shTarget = wbTarget.Worksheets("Sheet1")
Use COUNTIF. It will give you the total even if the range is in another workbook. i.e. =COUNTIF([Book2.xlsx]Sheet2!$D$2:$D$9, "Yes"). Problem with having COUNTIF within your sheet as a formula is that you will need to open the other workbook if you want the count to be update. Below VBA code will perform an update for you. Assign the sub to a button in your CountResults.xlsm workbook
EDIT: Added row count as per OP's requirement
Sub UpdateResults()
Dim oWBWithColumn As Workbook: Set oWBWithColumn = Application.Workbooks.Open("<your Test01.xlsx address here>")
Dim oWS As Worksheet: Set oWS = oWBWithColumn.Worksheets("Sheet2")
Dim intLastRow as Integer: intLastRow = oWS.Cells(Rows.Count, "B").End(xlUp).Row
ThisWorkbook.Worksheets("<name of the sheet in your CountResults.xlsm workbook>").Range("<cell address>").Value = Application.WorksheetFunction.CountIf(oWS.Range("B2:B" & intLastRow), "yes")
oWBWithColumn.Close False
Set oWS = Nothing
Set oWBWithColumn = Nothing
End Sub

VBA: How to extend a copy/paste between two workbooks to all sheets of both workbooks

I have a plethora of Excel workbooks containing 25+ worksheets each containing 20 columns of data from range 1:500 (or 1:1000 in some cases). Frequently I am tasked with updating the "template" onto which new data is entered for new calculations. I want to be able to easily paste extant data from old worksheets into sheets with new formatting while retaining any new formatting/formulas in the new templates.
I am using VBA to open the sheet I want to copy and paste it onto the new template sheet. So far my code will copy everything from the first sheet (S1) of the to-be-copied workbook and paste it onto the first sheet (S1) of the target workbook.
I want to extend this process to go through all active sheets (do whatever it is doing now for each sheet in the workbooks). I previously was able to do this with different code but it removed the formulas in rows 503 and 506 that I need when it pasted in. Can I do a pastespecial and skip empty cells? I am new to this.
Here is my current code:
Sub CopyWS1()
Dim x As Workbook
Dim y As Workbook
Set x = Workbooks("Ch00 Avoid.xlsx")
Set y = Workbooks("Ch00 Avoid1.xlsx")
Dim LastRow As Long
Dim NextRow As Long
x.Worksheets("S1").Activate
Range("A65536").Select
ActiveCell.End(xlUp).Select
LastRow = ActiveCell.Row
Range("A2:T" & LastRow).Copy y.Worksheets("s1").Range("A1:A500")
Application.CutCopyMode = False
Range("A1").Select
End Sub
I believe that I need to use something like the following code in order to extend this across the worksheets, but I'm not sure how to iterate through the sheets since I'm specifically referencing two sheets in my above code.
Sub WorksheetLoop2()
' Declare Current as a worksheet object variable.
Dim Current As Worksheet
' Loop through all of the worksheets in the active workbook.
For Each Current In Worksheets
' Insert your code here.
' This line displays the worksheet name in a message box.
MsgBox Current.Name
Next
End Sub
I imagine that I might be able to solve this as a for loop across an index of worksheets (make a new variable and run a for loop until my index is 25 or something) as an alternative, but again, I'm not sure how to point my copy/paste from a particular sheet to another sheet. I am very new to this with semi-limited experience with Python/Java only. These VBA skills would greatly benefit me on the day to day.
The two files in question:
Ch00 Avoid
Ch00 Avoid1
This should do it. You should be able to drop this in a blank workbook just to see how it works (put some values in column A on a couple of sheets). Obviously you will replace your wbCopy and wbPaste variables, and remove the wbPaste.worksheets.add from the code (my excel was only adding 1 sheet in the new workbook). LastRow is determined per your code, looking up from column A to find the last cell. wsNameCode is used to determine the first part of your worksheets you are looking for, so you will change it to "s".
This will loop through all sheets in your copy workbook. For each of those sheets, it's going to loop 1 through 20 to see if the name equals "s" + loop number. Your wbPaste has the same sheet names, so when it finds s# on wbCopy, it is going to paste into wbPaste with the same sheet name: s1 into s1, s20 into s20, etc. I didn't put in any error handling, so if you have an s21 on your copy workbook, s21 needs to be on your paste workbook, and NumberToCopy changed to 21 (or just set it to a higher number if you plan on adding more).
You could have it just loop through the first 20 sheets, but if someone moves one it will throw it all off. This way sheet placement in the workbook is irrelevant as long as it exists in the paste workbook.
You can also turn screenupdating off if you don't want to have a seizure.
Option Explicit
Sub CopyAll()
'Define variables
Dim wbCopy As Workbook
Dim wsCopy As Worksheet
Dim wbPaste As Workbook
Dim LastRow As Long
Dim i As Integer
Dim wsNameCode As String
Dim NumberToCopy As Integer
'Set variables
i = 1
NumberToCopy = 20
wsNameCode = "Sheet"
'Set these to your workbooks
Set wbCopy = ThisWorkbook
Set wbPaste = Workbooks.Add
'These are just an example, delete when you run in your workbooks
wbPaste.Worksheets.Add
wbPaste.Worksheets.Add
'Loop through all worksheets in copy workbook
For Each wsCopy In wbCopy.Worksheets
'Reset the last row to the worksheet, reset the sheet number search to 1
LastRow = wsCopy.Cells(65536, 1).End(xlUp).Row
i = 1
'Test worksheet name to match template code (s + number)
Do Until i > NumberToCopy
If wsCopy.Name = (wsNameCode & i) Then
wsCopy.Range("A2:T" & LastRow).Copy
wbPaste.Sheets(wsNameCode & i).Paste
End If
i = i + 1
Loop
Next wsCopy
End Sub
Thank you for all of your help, everyone. I went back yesterday afternoon from scratch and ended up with the following code which, at least to my eyes, has solved what I was trying to do. The next step will be to try to make this less tedious as I have a gajillion workbooks to update. If I can find a less obnoxious way to open/update/save/close new workbooks, I will be very happy. As it stands now, however, I have to open both the example workbook and the target workbook, save both, and close...but it works.
'This VBA macro copies a range of cells from specified worksheets within one workbook to a range of cells
'on another workbook; the names of the sheets in both workbooks should be identical although can be edited to fit
Sub CopyToNewTemplate()
Dim x As Workbook
Dim y As Workbook
Dim ws As Worksheet
Dim tbc As Range
Dim targ As Range
Dim InxW As Long
Dim WshtNames As Variant
Dim WshtNameCrnt As Variant
'Specify the Workbook to copy from (x) and the workbook to copy to (y)
Set x = Workbooks("Ch00 Avoid.xlsx")
Set y = Workbooks("Ch00 Avoid1.xlsx")
'Can change the worksheet names according to what is in your workbook; both worksheets must be identical
WshtNames = Array("S1", "S2", "S3", "S4", "S5", "S6", "S7", "s8", "s9", "S10", "S11", "S12", "S13", "S14", "S15", _
"S16", "S17", "S18", "S19", "S20", "Ext1", "Ext2", "Ext3", "EFS BigAverage")
'will iterate through each worksheet in the array, copying the tbc range and pasting to the targ range
For Each WshtNameCrnt In WshtNames
With Worksheets(WshtNameCrnt)
'tbc is tobecopied, specify the range of cells to copy; targ is the target workbook range
Set tbc = x.Worksheets(WshtNameCrnt).Range("A1:T500")
Set targ = y.Worksheets(WshtNameCrnt).Range("A1:T500")
Dim LastRow As Long
Dim NextRow As Long
tbc.Copy targ
Application.CutCopyMode = False
End With
Next WshtNameCrnt
End Sub

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

merging variable amount of files under matching columns

I have 3 open Excel files which i have opened using this code;
Dim myWorkbooks As New Collection
Sub GetFile()
Dim fNameAndPath As Variant, i As Long, x As Variant
fNameAndPath = Application.GetOpenFilename("All Files (*.*), *.*", , "Select Files To Be Opened", , True)
If Not IsArray(fNameAndPath) Then
If fNameAndPath = False Then Exit Sub Else fNameAndPath = Array (fNameAndPath)
End If
For i = LBound(fNameAndPath) To UBound(fNameAndPath)
Set x = Workbooks.Open(fNameAndPath(i))
myWorkbooks.Add x
Next
End Sub
i merged all the Sheets i Need in one Workbook. There is a mastersheet called "KomKo" in this Workbook. And i have other Sheets which are "data (2)" , "data (3)" and "data(4)". These Sheets can be more then 4 so i might have Sheets called "data(11) " and so on. I would like to be able to copy Column C of all "data" Sheets and paste it to Column A of "KomKo" Sheet. i should be able to paste These values to the next empty value of that Column A.
How can i do this ?
So, after you have corrected your question, this code should do the desired work:
Dim masterSheet As Worksheet
Set masterSheet = Sheets("Komko")
'Variable to save the used Range of the master sheet
Dim usedRangeMaster As Integer
Dim ws As Worksheet
'loop through each worksheet in current workbook
For Each ws In Worksheets
'If sheetname contains "data" (UCase casts the Name to upper case letters)
If InStr(1, UCase(ws.Name), "DATA", vbTextCompare) > 0 Then
'calculate the used range of the master sheet
usedRangeMaster = masterSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row + 1
'Variable to save the used Range of the sub sheet
Dim usedRangeSub As Integer
'calculate the used range of the sub sheet
usedRangeSub = ws.UsedRange.SpecialCells(xlCellTypeLastCell).Row
'copy relevant range from the subsheet
ws.Range("C1:C" & usedRangeSub).Copy
'paste the copied range after the used range in column a
masterSheet.Range("A" & usedRangeMaster).PasteSpecial
End If
Next ws
Since you already have a collection containing the relevant workbooks, you can just loop through these and copy the relevant stuff into your main wb.
So define a variable for the master sheet(to be able to refer to it)
And one Variable inside the loop which holds the "subsheet":
Dim mastersheet As Workbook
Set mastersheet = ThisWorkbook 'Assuming the code is inside the master sheet
Dim wb As Workbook
For Each wb In myWorkbooks
'Copy stuff
'Example to get a value from the "subsheet"
mastersheet.Sheets("sheet1").Cells(1, 1).Value = wb.Sheets("sheet1").Cells(1, 1)
Next wb
Then inside the loop, copy column c for example and paste it into column a of the master sheet:
wb.Sheets("sheet1").Range("C1").EntireColumn.Copy
mastersheet.Sheets("sheet1").Range("A1").PasteSpecial

Assigning String a value from another workbook

I am trying to assign a value from a cell in another workbook to a string variable in my code.
So currently my code will look up column P,G,H,I in the workbook but I have created another workbook which I have input all the columns I need it to look up. So on the other workbook I have mapped it out so the Ship to site ID value is P but I cant workout how to assign the value from this workbook to the below code.
I want it so I can just change the value in my mapping workbook rather than having to come back to my coding and change the column letter everytime there is a change.
ShipToSiteID = Application.WorksheetFunction.Trim(Range("P" & counter))
AltShipTo1 = Application.WorksheetFunction.Trim(Range("G" & counter))
AltShipTo2 = Application.WorksheetFunction.Trim(Range("H" & counter))
AltShipToCity = Application.WorksheetFunction.Trim(Range("I" & counter))
When you use Range("P" & counter) this will be refering to the ActiveWorksheet
so it is the same as ActiveWorksheet.Range("P" & counter)
If you want to refer to another workbook then you need use a range from a sheet within this workbook.
Sub test()
Dim newWorkbook As Workbook
Dim newWorksheet As Worksheet
'NewWorkbook.xlsm is already open
Set newWorkbook = Workbooks("NewWorkbook.xlsm")
Set newWorksheet = newWorkBook.Worksheets("Sheet1")
MsgBox "This value is A1 in NewWorkbook - " & newWorksheet.Range("A1").Value
End Sub
You can also get an open workbook by index (although this isn't really recommended).
Set newWorkbook = Workbooks(1)
You can get and open a workbook at the same time by using Workbook.Open
Set newWorkbook = Workbooks.Open("C:/Path/To/Workbook")
Or get and add a new workbook by using Workbook.Add
Set newWorkbook = Workbooks.Add()
Also, regarding your usage of Application.WorksheetFunction.Trim
There is a built in VBA Trim() function that would suit better..
I'm not entirely sure from your question how you are trying to copy from one workbook to another, but the below code is a general approach for getting a specific cell's data out of another workbook.
Sub GetOtherValues()
Dim thisWS As Worksheet
Dim thatWS As Worksheet
Dim thatWB As Workbook
Dim ShipToSiteID As String
Dim counter As Integer
Set thisWS = ActiveSheet
Set thatWB = Workbooks.Open("C:\demo.xlsx")
Set thatWS = thatWB.Worksheets(1)
counter = 2 'initialized here for the sake of code completeness
ShipToSiteID = Trim(thatWS.Range("P" & counter))
'Do something else with the trimmed data from ShipToSiteID
thisWS.Cells(2, 2) = ShipToSiteID
thatWB.Close
End Sub
This code assumes you are running from the current workbook, and there is another worksheet/workbook that you need to get the data from. After declaring the variables, it assigns thisWB to be the current worksheet, then opens the next workbook and assigns the first worksheet to thatWS. We can now use thatWS and the counter variable to copy and trim the data, and stick it in the variable ShipToSiteID (and then do whatever else you're needing to do with it).