I have a few closed Excel workbooks, which I would be willing to access with =INDEX(MATCH) without openning them.
Unfortunately, I want to refer to them indirectly, thus based on the current sheet I am in.
E.g. - if I am in sheet -> then file path:
AAB -> 'C:\Users\vityata\Desktop\[AAB]Test'!$A:E
BBC -> 'C:\Users\vityata\Desktop\[BBC]Test'!$A:E
It seems like a trivial task, but the only options to do something like this seem to be the following:
Open the sheet and then use Indirect() (but I do not want to open the sheet)
Use VBA code (but it should be somehow reusable and really last resort)
Use data connection (I do not want it)
Use INDIRECT.EXT (but I do not want 3. party add-ins)
I have checked similar problems here: How to referencing value in closed excel workbook by formula incl. variable sheetname? but the first solution is rather too colmplicated to do it.
Any new ideas or best practices?
Update
So far I have achieved the following with VBA (although I would love to have a non-VBA solution):
Option Explicit
Public Sub VlookupClosedWb(Optional strLookFor As String = "Erteilung Baugenehmigung", _
Optional strSheet As String = "APF", _
Optional lngColIndex As Long = 2)
Dim strRange As String
strRange = "'" & ThisWorkbook.Path & "\[" & strSheet & ".xlsx]" & "Monatsbericht'!$A:$E"
ActiveCell.Formula = "=VLOOKUP(""" & strLookFor & """," & strRange & "," & lngColIndex & ",0)"
End Sub
Public Function fVlookupClosedWb(Optional strLookFor As String = "Erteilung Baugenehmigung", _
Optional strSheet As String = "APF", _
Optional lngColIndex As Long = 2)
Dim strRange As String
strRange = "'" & ThisWorkbook.Path & "\[" & strSheet & ".xlsx]" & "Monatsbericht'!$A:$E"
fVlookupClosedWb = WorksheetFunction.VLookup(""" & strLookFor & """, " & strRange & ", " & lngColIndex & ", 0)
End Function
Long story short - the Sub works as expected, providing exactly what I want in the active cell. The Function does not work. Any ideas how to make it work? I suppose that it does not work, because I am abusing a bit WorksheetFunction.VLookup, but I cannot pass a range without openning the other workbook. Ideas?
After some tries, I found out that the way to use some formulas on a closed excel workbook, without referring to the path is by using the Sumproduct() function.
E.g.:
If you want to use Sumproduct() as an alternative of Sumifs() this is how it looks like with two conditions:
=SUMPRODUCT(((B2:B6=C2)*1)*(A2:A6=D2))
*SUMPRODUCT(((B8:B13=C8)*1)*(A8:A13=D8))
*SUMPRODUCT(((B16:B20=C16)*1)*(A16:A20=D16))
I have put some more examples of it here.
Related
I created an Excel 2016-based template, which the user can fill and create a work form based on it. User inserts an unique ID and with basic INDEX&MATCH formulas some ID-related parameters are being fetched from separate worksheet a. The work form is created with VBA-macro using SaveCopyAs method.
After the parameters have been fetched and VBA is launched to create the work form the ID will not change anymore. Thus, I don't need the whole worksheet a anymore and would like to drop it to keep the work form more lightweight. I'm capable of retaining the fetched parameters, so this is not a problem.
I would NOT want the user to have to re-open the form every single time a work form is created, so I don't want the VBA to remove worksheet a from the template itself, as even though the user can't save changes to the template, (s)he would have to re-open the template file every time a work form has to be created.
Any idea if something could be done? Might it be possible to somehow run SaveCopyAs or similar method, but drop the worksheet a at the same time from the new target file? Having INDEX&MATCH formula fetch the needed information from another workbook would theoretically work but to my knowledge requires the other workbook to be open at all times which will undoubtedly start to cause unnecessary issues.
My current VBA for work form creating is something like this:
Sub Save_copy()
Dim FileName As String
With ActiveWorkbook
[H3] = Format(Now, "dd.mm.yy_hhmm")
Range("H2").Value = Range("H1").Value
FileName = "SERVICE " & _
Range("H1").Value & _
" - " & Format(Now, "dd.mm.yy") & _
"_" & Format(Now, "hhmm") & _
"." & Right(.Name, Len(.Name) - InStrRev(.Name, "."))
.SaveCopyAs "G:\SERVICE" & "\" & FileName
End With
Call Reset
End Sub
If I understood you properly try something like this ("air-coded" so there may be typos):
Sub Save_copy()
Dim FileName As String
With ActiveWorkbook
[H3] = Format(Now, "dd.mm.yy_hhmm")
Range("H2").Value = Range("H1").Value
FileName = "SERVICE " & _
Range("H1").Value & _
" - " & Format(Now, "dd.mm.yy") & _
"_" & Format(Now, "hhmm") & _
"." & Right(.Name, Len(.Name) - InStrRev(.Name, "."))
.SaveCopyAs "G:\SERVICE\" & FileName
End With
Dim newWorkbook As Excel.Workbook
Set newWorkbook = Workbooks.Open("G:\service\" & FileName)
newWorkbook.Worksheets("A").Delete
newWorkbook.Close True
Reset
End Sub
Additionally, a couple of coding tips:
There's no need for Call - that function is deprecated and only exists to keep ancient code from blowing up
There is an extra concatenation of the "\" in your .SaveCopyAs line - simply put the trailing slash in with the rest of the path (as I did).
The unqualified Range("H2") refers to the ActiveWorksheet and could blow up on you if your user ever happens to click on a different worksheet while your code is running
I am creating a new worksheet called varRef and am trying to link cells of an existing worksheet to this new worksheet by using VBA. I have been trying to solve it for a couple of hours but cannot get it right and cannot find a similar case on the web either.
The code is:
Dim varRef as Variant 'name of the new sheet
varRef = Inputbox("xyz") 'this is how I define the name
Dim intRow As Integer 'row that corresponds to the appropriate postion in the existing sheet
intRow = ActiveCell.Row 'see above
Cells(intRow, 22).Formula = "=IF(varRef & ""!I148""="""","""",varRef & _
""!I148"")" 'trying to link the contents within the same workbook
The result in the cell I get is
=IF(varRef & "!I148"="","",varRef & "!I148"
which is obviously not working.
Issue 1) is that VBA does not recognize my variable in the formula. It is working for naming the sheet however.
Issue 2) is the quotation marks, that are not working as intended. One is supposed to use double quotation marks to not end the string. However the second marks will not disappear in the final code of the cell.
Any help is very much appreciated and hopefully valuable for other users as well!
You had some count issues with hoe many " you have before and after the varRef variable.
Also, I prefer to use Chr(34) to have " inside the Formula string, this way I don't get confused with how many " I need to use.
Try the code below:
Cells(intRow, 22).Formula = "=IF(" & varRef & "!I148=" & Chr(34) & Chr(34) & "," _
& Chr(34) & Chr(34) & "," & varRef & "!I148)"
I have the goal to write a formula in a set of rows. Some references in the formula have to change each row.
I implemented the following script:
Dim i As Integer
Dim formcolM As String
Dim temprng As String
For i = 0 To 100
formcolM = "NUMBERVALUE(IF(Q" & i & "=""Bedarf kum."";A" & i & ";IF(Q" & i & "=""Ist"";OFFSET(A" & i & ";-1;0);IF(Q" & i & "=""Lz."";OFFSET(A" & i & ";-2;0);IF(Q" & i & "=""Ist+Lz.-Bedarf"";OFFSET(A" & i & ";-3;0);)))))"
Let temprng = "M" & i
Range(temprng).Select
ActiveCell.Value = "\=" & formcolM
next i
With this script I am writing a string each row in my excel table at column M.
I noticed that if the formula hasn't the symbol "\" , you can find an error .
In order to avoid the error I thought to leave the symbol "\" and to use a trick deleting it after (because I don't know how to solve with R1C1 formula. I read some answers on Stackoverflow, but unfortunately I did not understand )
The replacing script after the for cycle:
Columns("M:M").Replace What:="\=", Replacement:="=", LookAt:=xlPart
The strange thing is that the macro doesn't delete it.
Infact when the script finishes , it seems that nothing happened, without errors. But if I want substitute "\=" with another symbol, for example "*", the replacing script works.
I did not understand if the problem is :
the replace method did not recognized the symbol "=" to search
I cannot use the replace method because the symbol "=" disturbs in some way , I don't know in what.
OR, is there another simplest way to get this task done?
Someone could help me in order to fix? I should have the formula working in the column M , automatically with vba (not with another formula in the excel sheet) .
Thanks in advance for your time.
We can apply the formula directly. The issue is that vba is very US-EN Centric and all formula when using the .Formula needs to be in that format.
Also since your formula refers to values in a row 3 above the one in which it is put we need to start the loop at 4 not 0. There is no row 0
There are two ways, in US-En format with English functions and , as the deliminator using .Formula:
Dim i As Integer
For i = 4 To 100
Range("M" & i).Formula = "=NUMBERVALUE(IF(Q" & i & "=""Bedarf kum."",A" & i & ",IF(Q" & i & "=""Ist"",OFFSET(A" & i & ",-1,0),IF(Q" & i & "=""Lz."",OFFSET(A" & i & ",-2,0),IF(Q" & i & "=""Ist+Lz.-Bedarf"",OFFSET(A" & i & ",-3,0),)))))"
Next i
Or using .FormulaLocal and the formula as you would write it in your native tongue.
Dim i As Integer
For i = 4 To 100
Range("M" & i).FormulaLocal = "=NUMERO.VALORE(SE(Q" & i & "=""Bedarf kum."";A" & i & ";SE(Q" & i & "=""Ist"";SCARTO(A" & i & ";-1;0);SE(Q" & i & "=""Lz."";SCARTO(A" & i & ";-2;0);SE(Q" & i & "=""Ist+Lz.-Bedarf"";SCARTO(A" & i & ";-3;0);)))))"
Next i
By the time I got this worked out, Scott already had an answer. I just wanted to post your original code modified to work. I would suggest his method.
Sub TestScript()
Dim i As Integer
Dim formcolM As String
Dim temprng As String
For i = 4 To 100
formcolM = "NUMBERVALUE(IF(Q" & i & "=" & "Bedarf kum." & ";A" & i & ";IF(Q" & i & "=" & "Ist" & ";OFFSET(A" & i & ";-1;0);IF(Q" & i & "=" & "Lz." & ";OFFSET(A" & i & ";-2;0);IF(Q" & i & "=" & "Ist+Lz.-Bedarf" & ";OFFSET(A" & i & ";-3;0);)))))"
temprng = "M" & i
Sheets("Sheet1").Range(temprng).Select
ActiveCell.Value = " = " & formcolM
Next i
End Sub
I would like to do SUMIFS function in a range of active sheet from other workbook. Here is where I get my error of Macro:
ActiveSheet.Range(ActiveSheet.Cells(6, lastCol + 1),
ActiveSheet.Cells(lastRow, lastCol + 1)).Formula = Application.WorksheetFunction.SumIfs(" ' " & wbGSD.Name & "'!$F$10:$F$" & wbGSDlastRow & ",'" & wbGSD.Name & "'!$B$10:$B$" & wbGSDlastRow & ",B6,'" & wbGSD.Name & "'!$C$10:$C$" & wbGSDlastRow & ", Total")
The error I got is:
Type Mismatch
I tried Sumif function. It didn't work either.
You're passing SumIfs() one long string. It doesn't take one long string. It takes a number of parameters, the first two of which are Range objects, not strings. If you want to write your formula as one long string, then there's no need for WorksheetFunction.SumIfs(). Just assign the string formula to the range's Formula property:
Range("A1").Formula = "=SUMIFS('" & wbGSD.Name & "'!$F$10:$F$" & ...
If you really do want to use WorksheetFunction.SumIfs(), you'll need to use it properly by passing individual parameters of the right type:
Range("A1") = WorksheetFunction.SumIfs( _
Sheets(wbGSD.Name).Range("$F$10:$F$" & wbGSDlastRow), _
Sheets(wbGSD.Name).Range("$B$10:$B$" & wbGSDlastRow), _
....
I'm trying to get a Vlookup for a row which is just left of the Lookup_value. I can't do a Table_array of "-1" (or -2) so I'm wondering if I can do an Offset(0, -1) within that line of code.
The line in question:
wCell.FormulaR1C1 = "=VLOOKUP(RC[1],'[" & filename & "]" & ws.Name & "'!R8C4:R" & lastrow & "C5,-1,FALSE)"
The entire code block:
Range("$C$8:$C$" & lastrow).Select
For Each wCell In Range("$C$8:$C$" & lastrow)
wCell.Select
If wCell.FormulaR1C1 = "" Then
wCell.FormulaR1C1 = "=VLOOKUP(RC[1],'[" & filename & "]" & ws.Name & "'!R8C4:R" & lastrow & "C5,-1,FALSE)"
End If
Next
If you were looking to find information to the left of the reference point in excel, using a Match-Index lookup would be they way for you to go. Not only is this method able to look to the left or right of your reference, but it is also a faster process.
VLookup looks like this:
=VLookup([Value to find],[Where to find the value],[Column to return],[range lookup])
Where as using Match-Index looks like this:
=Index([Range to look in for return],Match([Value to find],[Range to look in for value],[Exact match or partial]))
So, while a bit more complicated to write, using the second method really increases the flexibility of what you can look up and where that information is.
Now, if you were to apply this method to your code, it should look something like this:
wCell.FormulaR1C1 = "=Index([Range of Value to Find],Match(RC[1],'[" & filename & "]" & ws.Name & "'!R8C4:R" & lastrow & "C5, [0 for exact match]))"
(Just change out the bits I added in brackets for the information that they need, and that should address that problem your are running into)