Objects/dictionary for global variables - vba

I am writing a macro that will sit in workbook A.
Workbook A's primary function will be to open workbooks 1-5, and run the macros in those workbooks. However in order to run the macros in workbooks 1-5 I will need to pass inputs to workbooks 1-5 from workbook A.
I would like to define a dictionary or an object in workbook A, which will pass an entire set of inputs to each workbook 1-5. And the macros in workbooks 1-5 will only grab the necessary inputs.
How can I acheive this?

I'm wary of the vagueness of "run the macros in those workbooks", but I'll proceed with caution... :)
Let's say you have your workbooks, Master.xls and Child1-3.xls. They all have a reference set to the Windows Scripting Runtime library.
Master has a Settings worksheet and some VBA
Child1-3 each have two worksheets, DataDump and Settings
Child1-3 each have a public module with a VBA proc to be run (name is known)
The Master Settings w/s is populated thusly:
A1 = SettingName B1 = SettingValue
A2 = Setting1 B2 = Value1
A3 = Setting2 B3 = Value2
A4 = Setting3 B4 = Value3
(note that column C is empty and E always has a trailing \)
D1 = WBName E1 = WBPath F1 = ProcName
D2 = Child1.xls E2 = C:\Temp\ F2 = MaryJo
D3 = Child2.xls E3 = C:\Temp\ F3 = MaryLou
D4 = Child3.xls E4 = C:\Temp\ F4 = DaisyLou
There's the setup, now the execution.
Within a proc ("Bob") in Master write something like this:
Public Sub Bob
Dim dctSetting As Dictionary
Dim wkbCurrent As Workbook
Dim rngWkbook As Range
Dim rngSetting As Range
Set rngSetting = ThisWorkbook.Worksheets("Sheet1").Range("A2")
Set dctSetting = New Dictionary
Do Until rngSetting = ""
dctSetting.Add rngSetting.Value, rngSetting.Offset(0, 1).Value
Loop
Set rngWkBook = ThisWorkbook.Worksheets("Sheet1").Range("D2")
Do Until rngWkBook.Value = ""
Set wkbCurrent = Workbooks.Open(rngWkBook.Offset(0,1) & rngWkBook)
Application.Run "'" & rngWkBook & "'!" & rngWkBook.Offset(0,2),
dctSetting
Set wkbCurrent.Saved = True
wkbCurrent.Close False
Set rngWkBook = rngWkBook.Offset(1,0)
Loop
End Sub
Each of Child1-3 has their respective procs (MaryJo, MaryLou, DaisyLou), with the limitation of this approach being that each of those procs has to accept one param (best to make it a dictionary, I guess).
Each child's proc doesn't have to use all three settings, or even any of them. By using a dictionary, you can check for the existence of a setting prior to using it. So in each of the child procs there would be something like:
Public Sub MaryLou(dctSettings as Dictionary)
Dim strMyValue As String
If dctSettings.Exists("TheNameOfTheMasterSettingIWantToUse") Then
strMyValue = dctSettings("TheNameOfTheMasterSettingIWantToUse")
' Your code runs here with the populated variable
End If
End Sub
You'll need to do extra stuff like check for the child w/b at the specified path - at a bare minimum!

Related

How to pass dynamic variables to an equation in VBA [duplicate]

I have a bunch of rows and 25 columns in a worksheet, and need to find the value in the 4th column based on columns B and C using VBA. I am using a combination of index and multiple condition match functions.
I tried to follow along via https://www.mrexcel.com/forum/showthread.php?650832-VBA-Multiple-Criteria-Index-Match and pass an integer variable into vba array formula to no avail.
I made this macro which works:
Sub VariablesInArrayFormula()
SA = "Apples"
C1 = "Oranges"
Range("D27").Select
Selection.FormulaArray = "=index(A2:G27,match(1,(B2:B27=b4)*(C2:C27= c6),0),4)"
Range("E27").Select
Selection.FormulaArray = "=index(A2:G27,match(1,(B2:B27=""Apples"")*(C2:C27= ""Oranges""),0),4)"
f = Evaluate("index(A2:G27,match(1,(B2:B27=""Apples"")*(C2:C27= ""Oranges""),0),4)")
Range("G27").Select
Selection.FormulaArray = "=index(A2:G27,match(1,(B2:B27="" & SA & "")*(C2:C27= "" C1 ""),0),4)"
End Sub
I want to assign the value to a variable for future use.
When I assign it to D27, it works because the I refer to cell references b4 and c6.
Assigning it to cell E27 also works, but then I need to refer directly to Apples and Oranges, where as I would prefer to pass in a variables
assigning it to a variable f works when I pass in the words Apples and Oranges
when I attempt to pass a reference to Apples and Oranges (SA and C1 respectively), I receive a #N/A error.
Can anyone suggest a way that I can pass in the variables to this function.
NB I tried using worksheetfunction.index and worksheetfunction.match and kept receiving errors as well. Specifically, I tried:
gr4 = WorksheetFunction.Index(Range("A2:G27"), WorksheetFunction.Match(1, ((Range("B2:B27") = SA) * (Range("C2:C27") = C1)), 0), 4)
which returned a run time error #13: type mismatch.
Odd that using 2 matches failed, as when I use a single column to check with the match function worked
Sub vfhj()
SA = "Apples"
C1 = "Oranges"
gr3 = WorksheetFunction.Index(Range("C2:C27"), WorksheetFunction.Match(C1, Range("C2:C27"), 0))
End Sub
If I understand correctly, I think your syntax was just off slightly - you omitted some ampersands and overlooked the rule about doubling up the quotes. Also no need to Select.
Range("G27").FormulaArray = "=index(A2:G27,match(1,(B2:B27=""" & SA & """)*(C2:C27=""" & C1 & """),0),4)"
May be a bit quicker using memory arrays:
Sub VariablesInArrayFormula()
Dim SA As String
SA = "Apples"
Dim C1 As String
C1 = "Oranges"
With Worksheets("Sheet1") 'Change to your worksheet
Dim DtaArray As Variant
DtaArray = .Range("B2:D27").Value
Dim i As Long
For i = LBound(DtaArray, 1) To UBound(DtaArray, 1)
Dim ans
If DtaArray(i, 1) = SA And dtaaray(i, 2) = C1 Then
ans = DtaArray(i, 3)
Exit For
End If
Next i
.Range("G1").Value = ans
End With
End Sub

How to pass variables to an double match function in VBA

I have a bunch of rows and 25 columns in a worksheet, and need to find the value in the 4th column based on columns B and C using VBA. I am using a combination of index and multiple condition match functions.
I tried to follow along via https://www.mrexcel.com/forum/showthread.php?650832-VBA-Multiple-Criteria-Index-Match and pass an integer variable into vba array formula to no avail.
I made this macro which works:
Sub VariablesInArrayFormula()
SA = "Apples"
C1 = "Oranges"
Range("D27").Select
Selection.FormulaArray = "=index(A2:G27,match(1,(B2:B27=b4)*(C2:C27= c6),0),4)"
Range("E27").Select
Selection.FormulaArray = "=index(A2:G27,match(1,(B2:B27=""Apples"")*(C2:C27= ""Oranges""),0),4)"
f = Evaluate("index(A2:G27,match(1,(B2:B27=""Apples"")*(C2:C27= ""Oranges""),0),4)")
Range("G27").Select
Selection.FormulaArray = "=index(A2:G27,match(1,(B2:B27="" & SA & "")*(C2:C27= "" C1 ""),0),4)"
End Sub
I want to assign the value to a variable for future use.
When I assign it to D27, it works because the I refer to cell references b4 and c6.
Assigning it to cell E27 also works, but then I need to refer directly to Apples and Oranges, where as I would prefer to pass in a variables
assigning it to a variable f works when I pass in the words Apples and Oranges
when I attempt to pass a reference to Apples and Oranges (SA and C1 respectively), I receive a #N/A error.
Can anyone suggest a way that I can pass in the variables to this function.
NB I tried using worksheetfunction.index and worksheetfunction.match and kept receiving errors as well. Specifically, I tried:
gr4 = WorksheetFunction.Index(Range("A2:G27"), WorksheetFunction.Match(1, ((Range("B2:B27") = SA) * (Range("C2:C27") = C1)), 0), 4)
which returned a run time error #13: type mismatch.
Odd that using 2 matches failed, as when I use a single column to check with the match function worked
Sub vfhj()
SA = "Apples"
C1 = "Oranges"
gr3 = WorksheetFunction.Index(Range("C2:C27"), WorksheetFunction.Match(C1, Range("C2:C27"), 0))
End Sub
If I understand correctly, I think your syntax was just off slightly - you omitted some ampersands and overlooked the rule about doubling up the quotes. Also no need to Select.
Range("G27").FormulaArray = "=index(A2:G27,match(1,(B2:B27=""" & SA & """)*(C2:C27=""" & C1 & """),0),4)"
May be a bit quicker using memory arrays:
Sub VariablesInArrayFormula()
Dim SA As String
SA = "Apples"
Dim C1 As String
C1 = "Oranges"
With Worksheets("Sheet1") 'Change to your worksheet
Dim DtaArray As Variant
DtaArray = .Range("B2:D27").Value
Dim i As Long
For i = LBound(DtaArray, 1) To UBound(DtaArray, 1)
Dim ans
If DtaArray(i, 1) = SA And dtaaray(i, 2) = C1 Then
ans = DtaArray(i, 3)
Exit For
End If
Next i
.Range("G1").Value = ans
End With
End Sub

Both variables are the same, however calculating a=b disagrees?

On my Workbook, I have a sheet called "check"
Where the CELLS have the values:
F8 = 176129.20
H8 = 176129.20
My VBA code is a basic validation script which checks boths cells and displays messages based on the outcome.
Function plchk()
Dim sheet As Worksheet
Set sheet = ActiveWorkbook.Sheets("check")
qb = sheet.Range("F8").Value
xl = sheet.Range("H8").Value
If qb = xl Then
plchk = "They're the same"
Else
plchk = qb & " " & xl
End If
End Function
Should be pretty straight forward when I compare qb = xl the THEN should be executed, however instead VBA doesn't recognise them as the same and goes down the ELSE route and outputs both numbers with a space, and they're exactly the same number. I'm lost! Variable types?
Whomever helps me i send out good karma to you inadvance!!
try this:
Function plchk()
Dim sheet As Worksheet, qb as double, xl as double
Set sheet = ActiveWorkbook.Sheets("check")
qb = cdbl(trim(sheet.Range("F8").Value))
xl = cdbl(trim(sheet.Range("H8").Value))
If qb = xl Then
plchk = "They're the same"
Else
plchk = qb & " " & xl
End If
End Function

Delete entire row when a value exist (With sheets) [duplicate]

I have 2 sheets: sheet1 and sheet2. I have a value in cell A3 (sheet1) which is not constant. And many files in sheets2.
What I would like to do, is when the value in cell A3 (Sheet1) is the same as the value in the column A (Sheet2), it will delete the entire row where is find this value (Sheet2).
This is my attempt. It doesn't work: no rows are deleted.
If Worksheets("Sheet1").Range("A3").Text = Worksheets("Sheet2").Range("A:A").Text Then
Dim f As String
f = Worksheets("Sheet1").Range("A3")
Set c = Worksheets("Sheet2").Range("A:A").Find(f)
Worksheets("Sheet2").Range(c.Address()).EntireRow.Delete
End If
My guess is that you're not finding anything with the .Find(). Since you're not checking it for is Nothing you don't know. Also, .Find() retains all the search parameters set from the last time you did a search - either via code or by hand in your spreadsheet. While only the What parameter is required, it's always worth setting the most critical parameters (noted below) for it, you may want to set them all to ensure you know exactly how you're searching.
Dim f As String
If Worksheets("Sheet1").Range("A3").Text = Worksheets("Sheet2").Range("A:A").Text Then
f = Worksheets("Sheet1").Range("A3")
Set c = Worksheets("Sheet2").Range("A:A").Find(What:=f, Match:=[Part|Whole], _
LookIn:=[Formula|value])
if not c is Nothing then
Worksheets("Sheet2").Range(c.Address()).EntireRow.Delete
else
MsgBox("Nothing found")
End If
End If
Go look at the MS docs to see what all the parameters and their enumerations are.
Sub Test()
Dim ws As Worksheet
For x = 1 To Rows.Count
If ThisWorkbook.Sheets("Sheet2").Cells(x, 1).Value = ThisWorkbook.Sheets("Sheet1").Cells(3, 1).Value Then ThisWorkbook.Sheets("Sheet2").Cells(x, 1).EntireRow.Delete
Next x
End Sub

Excel - VBA Object does not support this property or method - Paste - Excel

the line that is giving me trouble is ""Sheets(CStr(WS_M.Cells(n, START_C))).Cells(n, START_C).Paste""
this is supposed to find the tab name in column 3 and go to that tab and paste the tab name in that tab.
Const START_C = 3
Const MAX_TRAN = 1000
Const START_R = 2
Const MASTER = "MASTER"
Sub MOVEDATACORRECTLY()
Dim WS_M As Worksheet
Dim thisWB As Workbook
Set thisWB = ActiveWorkbook
Set WS_M = Worksheets(MASTER)
For M = START_R To (START_R + MAX_TRAN)
If WS_M.Cells(M, (START_C + 1)) = "" Then Exit For
Next M
M = M - 1
For n = START_R To M
WS_M.Cells(n, START_C).Copy
Sheets(CStr(WS_M.Cells(n, START_C))).Cells(n, START_C).Paste
Next n
End Sub
Try this instead:
For n = START_R To M
WS_M.Cells(n, START_C).Copy
Sheets(CStr(WS_M.Cells(n, START_C))).Cells(n, START_C).Select
ActiveSheet.Paste
Next n
If you look at the documentation for the Excel Range object, Paste is not in the list of members. There is PasteSpecial, however. I haven't experimented with that, but that might also work.
For copying a range of cells in Excel, using Copy method makes the VBA program easier to crash / or to give inpredictable results.
Suppose during the your procedure copies data from system clipboard and user was trying to store some other to system clipboard!
Not always, but from users this kind of mistake might happened.
So I always prefer to use a better approach, something like Swaping the range on the fly. Here's a small demonstration:
Public Sub Sample_Copy_without_Clipboard()
Dim dRange As Range, iRange As Range
Set iRange = Range("A1:B3")
Set dRange = Range("D1:E3")
dRange.Value = iRange.Value
End Sub
Note: This method works only with unformatted textual data. If not then either use Tim's suggestion or DanM's answer.