How to turn this Macro Based function into a genuine VBA function? - excel

I am trying to write a VBA function so that I can access the cell values of a closed Excel Workbook. I found online that one can write a macro routine like this:
Public Sub TestGetValue()
p = "C:\Users\Jake\Desktop"
f = "TestSample.xlsx"
s = "Sheet1"
a = "B10"
Call GetValue(p, f, s, a)
x = GetValue(p, f, s, a)
MsgBox x
End Sub
Public 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 an XLM macro
GetValue = ExecuteExcel4Macro(arg)
End Function
I can run the TestGetValue() as a macro, but when I try to use GetValue() as a custom VBA function directly in Excel cells it doesn't work. It seems that the line GetValue = ExecuteExcel4Macro(arg) cannot be executed.
Does anyone know how to get around that? I'm using Excel 2010.

As far as I see, the function ExecuteExcel4Macro isn't defined. But there might be an even easier way.
Try to open the Workbook, which contains the desired values. E.g.
Dim tempWb As Workbook
Dim testValue
Set tempWb = Application.Workbooks.Open(path)
testValue = tempWb.Sheets(1).Cells(1,1)
The path can be passed as in your example.

Related

VBA to open Excel file based on cell value WITHIN that file

I've been looking all over the web for an answer to this question. I see many blogs and postings regarding opening an excel file based on a cell value NOT within that file.
My question: Is it possible to open a file based on a cell value within the file I am trying to open? Another way to word it: Can VBA search for a cell value within a file, that is not open, and then open that file if it finds that cell value?
Further Explanation:
I save reports from a system into a folder and these files being saved have a common name (Report, Report (1), Report (2), Report (3).....). However, the data within the reports are different. They all have a common cell (Cell A7) that designates what the report is for. I want to use VBA code to open one of these files based on its value in cell A7. Is this even possible?
Thank you in advanced for any direction here.
If you know the sheet name you can use ExecuteExcel4Macro. If the sheet name is not known then you can use ADO to get that first (easier here as there's only one sheet)
Example:
Sub Tester()
Const fldr As String = "C:\Excel\Temp\"
Dim f, v
f = Dir(fldr & "*.xlsx")
'loop over all files in folder
Do While Len(f) > 0
'passing empty string for sheetname, since we don't know it...
v = ReadCell(fldr, f, "", Range("A7").Address(True, True, xlR1C1))
Debug.Print f, v
f = Dir
Loop
End Sub
'Read a cell value given a workbook path, name, optional sheetname,
' and cell address (R1C1 format)
Function ReadCell(fPath, wbName, wsName, addr)
Const adSchemaTables = 20
Dim cn, conStr, rs
If Len(wsName) = 0 Then
'sheet name is not known, so find the first name using ADO
conStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & fPath & wbName & "';" & _
"Extended Properties=""Excel 12.0;HDR=NO;IMEX=1;"";"
Set cn = CreateObject("ADODB.connection")
cn.Open conStr
Set rs = cn.openschema(adSchemaTables)
wsName = Replace(rs("TABLE_NAME").Value, "$", "")
rs.Close
cn.Close
End If
ReadCell = ExecuteExcel4Macro("'" & fPath & "[" & wbName & "]" & _
wsName & "'!" & addr)
End Function

Get value from closed Excel workbook via HTTP link

I have a bunch of Excel workbooks that are stored on a shared online directory (kind of like Dropbox) in different folders. I am creating a master workbook to pull values from these Excel workbooks into a summary. While testing I've managed to create one that works if the workbooks are stored in my disk drives and I refer to their directories, but not via the HTTP links they are stored on.
I'm currently using the ExecuteExcel4Macro macro to retrieve values from closed workbooks on my computer and passing the directory as the argument. Some code for example which works if it's a directory on the hard drive:
Private 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 an XLM macro
GetValue = ExecuteExcel4Macro(arg)
End Function
Sub TestGetValue()
p = "c:\XLFiles\Budget"
f = "Budget.xls"
s = "Sheet1"
a = "A1"
MsgBox GetValue(p, f, s, a)
End Sub
Is there any way to get this to work with direct HTTP links to Excel workbooks instead of directories? Downloading them all into my computer isn't really an option, unless I could somehow change it to download each workbook automatically, get the value and then delete it, or something like that?

Determine cell interior color in a closed workbook

I have this Walkenbach code that everybody uses to pull data from a closed workbook and it's working just fine for me:
Sub ImportData()
Dim p As String, f As String, s As String, a As String
p = "\\MyServer\MyFolder\MySubFolder"
f = "MyWorkbook.xlsx"
s = "MySheet"
a = "$A$1"
GetValue(p, f, s, a)
End Sub
Private Function GetValue(path, file, sheet, ref)
Dim arg As String
If Right(path, 1) <> "\" Then path = path & "\"
If Dir(path & file) = "" Then
GetValue = "File Not Found"
Exit Function
End If
arg = "'" & path & "[" & file & "]" & sheet & "'!" & Range(ref).Range("A1").Address(, , xlR1C1)
GetValue = ExecuteExcel4Macro(arg)
End Function
What I want to do is determine the interior color of each cell...if the manager of the source spreadsheet has changed the color of a cell, it indicates that the value within is invalid and should not be included in the analysis.
So currently 'arg' is set to...
'\\MyServer\MyFolder\MySubFolder\[MyWorkbook.xlsx]MySheet'!R1C1
and running ExecuteExcel4Macro with that argument pulls the value in A1.
How can I restructure the 'arg' assignment to pull the interior color instead of the value?
If necessary, I can ask the manager to change the font color instead of the interior color to mark data to be excluded.

Excel VBA function to get value using variables from closed workbook

I have the following function which I use to fetch data from a closed workbook:
Public 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 an XLM macro
GetValue = ExecuteExcel4Macro(arg)
End Function
Then I have the following test routine which works:
Sub TestGetValue()
p = Range("B2").Value
f = Range("B3").Value
s = "TOTAL"
a = "D" & ActiveCell.Row + 3
MsgBox GetValue(p, f, s, a)
End Sub
However, if I use the GetValue function in an Excel cell providing all 4 parameters exactly like in the routine, it always throws a #VALUE! error.
Why does it work in a routine and not while being called as a function?
After several attempts I did find 3 solutions:
Using a function with "ExecuteExcel4Macro"
Opening the other workbook in the background by vba procedure, then copy/pasting data
Creating external references by vba procedure, then leaving only values
First one while being able to use it as an excel custom formula, it is the slowest, especially when you need data from a specific range. So I don't recommend this option as it would slow your workbook down a lot.
Second option while being much faster, still takes around 15 seconds to get data from several ranges across 2 workbooks.
Third option was the fastest. Like an instant really less than 1 second execution time during which data was pulled from 2 closed workbooks and for different ranges.
Here's the 3rd option's procedure:
Sub getDS()
asname = "data"
bsname = "Anual"
csname = "Total"
filename = Sheets("data").Range("B64").Value
path = Sheets("data").Range("B63").Value
Dim ws As Worksheet
Set ws = Sheets("data")
With ws.Range("D4:D34")
.ClearContents
.Formula = "='" & path & "[" & filename & "]" & bsname & "'!R11"
.Value = .Value
End With
With ws.Range("J4:J34")
.ClearContents
.Formula = "='" & path & "[" & filename & "]" & bsname & "'!U11"
.Value = .Value
End With
With ws.Range("J37:J37")
.ClearContents
.Formula = "='" & path & "[" & filename & "]" & csname & "'!DW96"
.Value = .Value
End With
End Sub
I found this by far to be the BEST and FASTEST VBA solution to fetch data in an INSTANT from closed workbooks (with variables) without opening them.

Return cell values from a closed Excel workbook

I pull data off of a database and manually enter it into an Excel report template.
I want with VBA code to lookup an exported closed Excel file (Test.xls) with data (example in cells B1:B21).
The data in the cells B1:B21 have spaces between each line. So vertically a column would be like the following
Data1
Space
Space
Data2
....
I want this with exception of the spaces to be put into the Excel report file, and displayed horizontally (A10:"Data1",B10:"Data2",C10:"data3"...) instead of vertically.
I cannot pull data directly from the database to the Excel template for security reasons.
Private Function GetValue(path, file, sheet, ref, v)
path = "C:\Documents and Settings\sdavis\Desktop\Index\XXX\Results"
file = "test.xls"
sheet = "Sheet1"
ref = "A1:R30"
' Retrieves a value from a closed workbook
Dim arg As String
Dim p As Integer
' 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).Cells(v, 2).Address(, , xlR1C1)
' Execute an XLM macro
GetValue = ExecuteExcel4Macro(arg)
End Function
Sub TestGetValue()
'Declare
Dim v As Integer
'Starting Point
v = 21
'File Location
path = "C:\Documents and Settings\sdavis\Desktop\Index\XXX\Results"
file = "test"
sheet = "Sheet1"
Application.ScreenUpdating = False
For C = 1 To 15
a = Cells(5, C).Address
Cells(5, C) = GetValue(path, file, sheet, a, v)
v = v + 3
Next C
Application.ScreenUpdating = True
End Sub

Resources