I use these lines to get values from closed workbooks:
Arg = "'" & Path & "[" & File & "]" & Sheet & "'!" & "R4C4"
Arg = CStr(Arg)
GetValue = ExecuteExcel4Macro(Arg)
Is there another way than loop to get values from a range? The loop solution is working, but it would be clearer if I could get the range directly with ExecuteExcel4Macro. I've tried to input a range in Arg, but it returns an error.
I have the same question for charts, how can I get them? My solution for the moment consists of getting values and replotting the charts. It works, but I would be happier with a GetChart(Chartname) function.
I've seen that I can use ADODB connection to get value from closed workbooks. But it was a little too complex compared to ExecuteExcel4Macro. Would it be easier to use ADODB connection in the case of range/charts?
The following bit of code pulls info from a range in a closed workbook and copies it in the same ranges in the Active Workbook:
Sub GetRange()
With Range("A1:D50") 'set range to copy from / to.
.Formula = "='C:\E3_Test\[CC_Data.xlsx]AllData'!A1" 'refers to a workbook, sheet and first cell.
'It will put the relative references into the target sheet correctly.
.Value = .Value 'changes formula to value.
End With
End Sub
Related
I'm quite new to VBA and I'm having trouble debugging a certain code. What I want is a cell formula that has the formula link to another spreadsheet. However, I want to add cells from multiple workbooks. For example, if we had workbook1 and workbook 2. I want in cell F10 in final workbook to have formula reading '[workbook1]Sheet1'!!F10' + '[workbook2]Sheet1'!!F10'
I like to make the formula as flexible and have the following conditions
I like to have an open directory that lets me select excel files that I want as part of the formula
I can add as many external spreadsheets as possible
The final spreadsheet initially will have zeroes in them. I want to replace this with a formula link.
How i decided to code this is by first replacing the zero cell of the final workbook with cell F10 of first excel file selected from a directory. Once this step is done, any additional workbooks selected from directory will add on as an extra formula link to the cell. Below is a code I attempted but I can not figure why it doesn't work. Could anyone please let me know what is going wrong? Thanks.
Sub Sum_workbooks_Form()
Dim FileNameXls, f
Dim wb As Workbook, i As Integer
FileNameXls = Application.GetOpenFilename(filefilter:="Excel Files, *.xl*", MultiSelect:=True)
If Not IsArray(FileNameXls) Then Exit Sub
For Each f In FileNameXls
Set wb = Workbooks.Open(f)
If ThisWorkbook.Sheets("Sheet1").Cells(11, 6).Value = 0 Then
ThisWorkbook.Sheets("Sheet1").Cells(11, 6).Formula = "=[" & wb.Name & "]Sheet1!" & Cell(11, 6).Name
Else
ThisWorkbook.Sheets("Sheet1").Cells(11, 6).Formula = "=[" & ThisWorkbook.Name & "]Sheet1!" & Cell(11, 6).Name & " + [" & wb.Name & "]Sheet1!" & Cell(11, 6).Name
End If
wb.Close SaveChanges:=False
Next f
End Sub
Well, normally a reference to cell F10 of Sheet1 of Book2 is expressed like this in a formula:
=[Book2]Sheet1!$F$10
Is it possible for you to reference the Sheet NAME instead of the NUMBER?
If yes, the first of your assignments should look like this:
ThisWorkbook.Sheets(9).Cells(11, 6).Formula = "=[" & wb.Name & "]Sheet1!$F$10"
Where Sheet1 is of course the name of your Sheets(9)
My file has two identical Worksheets for users to input two different sets of assumption variables, called "InputA" and "InputB". I want to quickly switch which Input sheet is feeding into the other sheets of the model.
Using Find and Replace took over 5 minutes, and there were over 350,000 references to "InputA".
I tried the following macro, which takes an instant to run, but unfortunately also changes all references in the workbook, effectively keeping everything referenced to the original input sheet.
Sheets("InputA").Name = "temp"
Sheets("InputB").Name = "InputA"
Sheets("temp").Name = "InputB"
Is there a way to execute the macro but prevent any references to worksheets from changing to the new sheet name, basically freezing everything except the sheet name change? Or perhaps any other solution that will work quickly? I don't want to go through 350,000 instances and rewrite using INDIRECT(), as that is the only other solution I've seen, because my references are complex and nested and that will take an age.
Thanks.
Assuming that your 2 Input-Sheets have the same structure, I would suggest the following:
Create a named range on Workbook-level, name it for example InputData. This range should contain all data from InputA.
Create a helper-sheet and name it Input - you can later set it to hidden.
Mark the range in the new sheet that is exactly the size of the Input-Data-Range and enter the formula =InputData as Array-formula. You can do so by entering Ctrl+Shift+Enter. The formula should have curly brackets and the sheet should now display the data of InputA.
Change all you formulas to refer to the helper Sheet Input instead of InputA.
Create a macro:
Sub switchInput()
Const sheetAName = "InputA"
Const sheetBName = "InputB"
With ThisWorkbook.Names("inputData")
If InStr(.RefersTo, sheetAName) > 0 Then
.RefersTo = Replace(.RefersTo, sheetAName, sheetBName)
Else
.RefersTo = Replace(.RefersTo, sheetBName, sheetAName)
End If
End With
End Sub
This routine will just change the definition of the named range to point either to the first or second input sheet. As a consequence, the helper sheet will show the data of the selected Input-Sheet. All your formulas itself stays unchanged.
As stated in the comments, you could take the approach recommended by Damian and use a conditional in all relevant cells. The generic conditional would be
=IF(A1="InputA",FORMULA INPUTA,FORMULA INPUTB)
This formula makes A1 the cell that decides which input to pull. This will make changing the around 350.000 output formulas in your workbook the bottleneck, the following macro takes care of changing all the formulas to conatin the conditional:
Sub changeFormulas()
Dim rng As Range, cll As Range
Set rng = shOutput.Range("A2:C10") 'Your relevant worksheet and range here
Dim aStr As String, bStr As String, formulaStr As String
aStr = "InputA"
bStr = "InputB"
For Each cll In rng
If cll.HasFormula And InStr(1, cll.Formula, aStr, 1) Then
formulaStr = Right(cll.Formula, Len(cll.Formula) - 1)
cll.Formula = "=IF(A1=" & Chr(34) & aStr & Chr(34) & "," & formulaStr & "," & Replace(formulaStr, aStr, bStr) & ")" 'Change A1 to the reference most suited for your case
End If
Next cll
End Sub
This might take a bit of time, since it has to access all the relevant cells one by one, but it will only have to run once.
To explain: This macro will go through all the cells in your range rng specified at the top. If a cell has a formula in it and the formula contains "InputA" it will change that formula to fit the generic conditional (with the cells own formula of course). Chr(34) is the quotation mark ", I find using Chr(34) more readable than multiple quotation marks """, but that is just preference.
I have a code snippet that I can't understand why it's failing. I get "Application-Defined or Object-Defined Error". I tried hard coding the range and it does work, but I even hardcoded the "Named Range" and it still failed.
Eg: This Doesn't Work
If regexp.test(strInput) Then
Set clloffset = rcell.Offset(0, 1)
Call GetColLet(rcell)
'Set PalletCol = Range(rcell.Address(False, False) & ":K39")
Set PalletCol = ActiveWorkbook.ActiveSheet.Range("K24:K39")
Set FormulaCol = ActiveWorkbook.ActiveSheet.Range("L24:L39")
ActiveWorkbook.ActiveSheet.Range(FormulaCol).Formula = "=" & Chr(34) & "BINWH" & Chr(34) & "&" & rcell.Address(0, 1)
But this does and I can't get it!
If regexp.test(strInput) Then
Set clloffset = rcell.Offset(0, 1)
Call GetColLet(rcell)
'Set PalletCol = Range(rcell.Address(False, False) & ":K39")
Set PalletCol = ActiveWorkbook.ActiveSheet.Range("K24:K39")
Set FormulaCol = ActiveWorkbook.ActiveSheet.Range("L24:L39")
ActiveWorkbook.ActiveSheet.Range("L24:L39").Formula = "=" & Chr(34) & "BINWH" & Chr(34) & "&" & rcell.Address(0, 1)
Note: I tried using both (FormulaCol) and ("FormulaCol"), I'm not sure when to use "" inside a named range to be honest, but neither work. Then I tried hard coding ("L24:L39"). and it worked. I appreciate any help troubleshooting this.
There are three main methods of accessing ranges in Excel:
Hard-coded values
Variables
Named Ranges
Hard-coded values
I won't really spend time explaining these, but here are some examples:
ThisWorkbook.Sheets("Name").Range("A1:B2")
ActiveWorkbook.ActiveSheet.Range("C3:E50")
Sheet1.Cells(1,3) 'Range("C1")
Notes
ThisWorkbook is a reference to the workbook which holds the code. An important distinction from ActiveWorkbook, as they are not always the same workbook (primarily when 2+ workbooks are open).
Sheet1 is the code name of a sheet. Sheet code names can only be used for the sheets contained in ThisWorkbook. If referencing a sheet from a different workbook, you'd have to use either the name or index to access it.
Variables
This would be like the FormulaCol in your original code. Variables are either declared in the code (Set FormulaCol = ActiveWorkbook.ActiveSheet.Range("L24:L39")) at local or global scope level, or are passed into routines as parameters (Function Sample(rangeVariable as Range) : End Function).
Interacting with a range variable could be thought of as using substitution, such as:
Set FormulaCol = Sheet1.Range("L24:L39")
FormulaCol.Formula = ""
instead of
Sheet1.Range("L24:L39").Formula = ""
Named Ranges
Interacting with a named range is similar to interacting with a hard-coded range. Assuming that the named range "Test" references Range("B2:C3") on Sheet1, it would be interacted with via:
Sheet1.Range("Test")
However, before named ranges can be referenced through VBA, they first have to be set up in the workbook. This can be done a couple of different ways:
Select all the cells for the named range, then in the "Name Box" (to the left of the formula bar) type in the name for that named range, and press enter (if you forget "enter", the name doesn't get saved).
Open the Name Manager in the Formulas tab and press "New" (or "Edit", if editing an existing named range). Note: when adding a named range via the manager, you can select the scope to be either the workbook or any of the sheets within the workbook. This affects which sheets can reference the named range.
and a window will open where you choose the name for the named range, and select what range it's referencing.
I'm working on a cell formula that returns (via VLOOKUP?) a cell in a closed workbook (thus I believe INDIRECT will not work). The issue is that I want to use a value in the active sheet to determine the name of the sheet in the reference workbook and can't figure it out. Here's the best I've got.
=VLOOKUP($A3,'[Other Workbook.xlsm]ObsDFW'!$1:$800,COLUMNS($D4:D4)+3)
ObsDAL is the name of one of the sheets in the "Other Workbook". What I can't figure out is how to keep the "Obs" part of that name constant, but take the "DFW" from a cell value.
Using bad code, I want it to be:
=...[Master Statistics.xlsm]("Obs" & A1)'!$1:$800...
If context is helpful, the "Other Workbook" is full of hourly weather observations, separated into one sheet for each of a series of airports. I'm trying to pull this info into another file/workbook so I don't have to specify each airport specifically in the code many times over.
Thanks in advance!
You could try this VBA approach. This way you are adjusting Vlookup formula based on your dynamic_part (sheetname)
Sub VlookupClosedWorkbook()
Dim dynamic_part As Variant
dynamic_part = Range("B1").Value 'You should enter in cell B1 dynamic part of sheet name
For x = 3 To Range("A" & Rows.Count).End(xlUp).Row
Range("B" & x).Value = "=VLOOKUP(A" & x & ",'[Other Workbook.xlsm]Obs" & dynamic_part & "'!$1:$800,COLUMNS($D4:D4)+3,FALSE)"
Next x
End Sub
Assign this macro to shape and fire it after you change your dynamic part. When you trigger it for the first time, make sure that you have both Workbooks open.
I am trying to import a range of cells from a closed workbook.
I use the external reference link built into Excel:
='F:\UGR\JOB DATA SHEET\[JOB SHEETS 1-500.xlsx]JobNumber'!B4
='F:\UGR\JOB DATA SHEET\[JOB SHEETS 1-500.xlsx]JobNumber'!B5
...
Going down the column from B4:B23 and replicating that for columns B-Z.
This works if the sheet name doesn't change. But that file contains sheets for Jobs 1 - 500, each on their own sheet. I am trying to pull those columns of data for whatever JobNumber gets entered into cell "B7". So ideally it would look like this:
='F:\UGR\JOB DATA SHEET\[JOB SHEETS 1-500.xlsx]&B7&'!B4
='F:\UGR\JOB DATA SHEET\[JOB SHEETS 1-500.xlsx]&B7&'!B5
...
Etc.
I know this won't work without the Indirect function, but I need to have the other file open for that to work. This isn't practical given the number of users who are using this file for reference.
I found a macro in VBA that should do what I need, but I can't get it to work. Here is the base macro before I started messing around with it.
Function GetValue(Path, File, Sheet, Ref)
'Retrieves a value from a closed workbook
Dim Arg As String
'Make sure the file exists
If Right(Path, 1) <> "\" Then Path = Path & "\"
If Dir(Path & File) = "" Then
GetValue = "File not Found"
Exit Function
End If
'Create the argument
Arg = "'" & Path & "[" & File & "]" & Sheet & "'!" & Range(Ref.Range("A1").Address(, , xlR1C1))
'Execute XLM macro
GetValue = ExecuteExcel4Macro(Arg)
End Function
Any ideas on how to get it to work, or an alternative work around? I could also temporarily import the sheet to my other file and overwrite it when a new value is entered, thus importing another sheet from the other workbook, but that seems far more complex.
I am using Excel 2013.
UPDATE: I am closer to figuring it out but I cant get it to display anything but #Value errors. My formula looks like this in excel:
=GetValue(H11,H12,B7,B4)
Cell H11 = F:\UGR\JOB DATA SHEET\
Cell H12 = JOB SHEETS 1-500.xlsx
Cell B7 = The input cell where the user enters a JobNumber (aka sheet name).
Cell B4 = B4 (The cell I want to search on the external workbook)
Cell B4 is where I think the error lies. Will this macro be able to tell that it needs to search the external file at cell B4?
I figured it out. The macro cannot be launched from within the workbook itself, it must be done from VBA.