MS Access Nz() Function not Recognised in MS Excel - excel

I'm trying to write an expression in MS Access which returns a string of text, "New Policy", in the Iif() statement after it returns an error.
When I export the data from Access into Excel it tells me that Nz() is not recognised.
Is there an alternative to this function? My Access expression is as follows:
Nz(IIf([Policy Status]=[Input - WFAC Previous Day]![Policy Status 1],"Remains " & [Policy Status],[Input - WFAC Previous Day]![Policy Status 1] & " to " & [Policy Status]), "New Policy")

Nz is defined in the Microsoft Access type library, which is automatically referenced when your host application is, well, Access.
If you add a reference to the Access type library in your Excel project, you should be able to use Nz... but then your Excel project won't work if Access isn't installed, which is... weird and rather heavy-handed.
What does Nz do? Looks like some kind of Coalesce function that should be rather trivial to implement on your own and customize as needed. Something like this?
Public Function Coalesce(ByVal value As Variant, Optional ByVal value_when_null As Variant = 0) As Variant
Dim return_value As Variant
On Error Resume Next 'supress error handling
If IsEmpty(value) Or IsNull(value) Or (VarType(value) = vbString And value = vbNullString) Then
return_value = value_when_null
Else
return_value = value
End If
Err.Clear 'clear any errors that might have occurred
On Error GoTo 0 'reinstate error handling
Coalesce = return_value
End Function

You don't need Nz for this:
IIf(IsNull([Policy Status]), "New Policy",
IIf([Policy Status] & "" = [Input - WFAC Previous Day]![Policy Status 1],
"Remains " & [Policy Status],
[Input - WFAC Previous Day]![Policy Status 1] & " to " & [Policy Status]))

If you're using VBA, you can add a Reference to the MS Access library, e.g. "Microsoft Access 14.0 object library. Then the Nz function is available as Access.Nz(value, "New Policy"). You could even create a user-defined function for use on Excel spreadsheets:
Public Function Nz(Value As Variant, Optional ValueIfNull As Variant = "New Policy") As Variant
Nz = Access.Nz(Value, ValueIfNull)
End Function
Hope that helps

Related

Extract file names from a File Explorer search into Excel

This has been bugging me for while as I feel I have few pieces of the puzzle but I cant put them all together
So my goal is to be able to search all .pdfs in a given location for a keyword or phrase within the content of the files, not the filename, and then use the results of the search to populate an excel spreadsheet.
Before we start, I know that this easy to do using the Acrobat Pro API, but my company are not going to pay for licences for everyone so that this one macro will work.
The windows file explorer search accepts advanced query syntax and will search inside the contents of files assuming that the correct ifilters are enabled. E.g. if you have a word document called doc1.docx and the text inside the document reads "blahblahblah", and you search for "blah" doc1.docx will appear as the result.
As far as I know, this cannot be acheived using the FileSystemObject, but if someone could confirm either way that would be really useful?
I have a simple code that opens an explorer window and searches for a string within the contents of all files in the given location. Once the search has completed I have an explorer window with all the files required listed. How do I take this list and populate an excel with the filenames of these files?
dim eSearch As String
eSearch = "explorer " & Chr$(34) & "search-ms://query=System.Generic.String:" & [search term here] & "&crumb=location:" & [Directory Here] & Chr$(34)
Call Shell (eSearch)
Assuming the location is indexed you can access the catalog directly with ADO (add a reference to Microsoft ActiveX Data Objects 2.x):
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim sql As String
cn.Open "Provider=Search.CollatorDSO;Extended Properties='Application=Windows'"
sql = "SELECT System.ItemNameDisplay, System.ItemPathDisplay FROM SystemIndex WHERE SCOPE='file:C:\look\here' AND System.Kind <> 'folder' AND CONTAINS(System.FileName, '""*.PDF""') AND CONTAINS ('""find this text""')"
rs.Open sql, cn, adOpenForwardOnly, adLockReadOnly
If Not rs.EOF Then
Do While Not rs.EOF
Debug.Print "File: "; rs.Collect(0)
Debug.Print "Path: "; rs.Collect(1)
rs.MoveNext
Loop
End If
Try using the next function, please:
Function GetFilteredFiles(foldPath As String) As Collection
'If using a reference to `Microsoft Internet Controls (ShDocVW.dll)_____________________
'uncomment the next 2 lines and comment the following three (without any reference part)
'Dim ExpWin As SHDocVw.ShellWindows, CurrWin As SHDocVw.InternetExplorer
'Set ExpWin = New SHDocVw.ShellWindows
'_______________________________________________________________________________________
'Without any reference:_____________________________________
Dim ExpWin As Object, CurrWin As Object, objshell As Object
Set objshell = CreateObject("Shell.Application")
Set ExpWin = objshell.Windows
'___________________________________________________________
Dim Result As New Collection, oFolderItems As Object, i As Long
Dim CurrSelFile As String
For Each CurrWin In ExpWin
If Not CurrWin.Document Is Nothing Then
If Not CurrWin.Document.FocusedItem Is Nothing Then
If left(CurrWin.Document.FocusedItem.Path, _
InStrRev(CurrWin.Document.FocusedItem.Path, "\")) = foldPath Then
Set oFolderItems = CurrWin.Document.folder.Items
For i = 0 To oFolderItems.count
On Error Resume Next
If Err.Number <> 0 Then
Err.Clear: On Error GoTo 0
Else
Result.Add oFolderItems.item(CLng(i)).Name
On Error GoTo 0
End If
Next
End If
End If
End If
Next CurrWin
Set GetFilteredFiles = Result
End Function
Like it is, the function works without any reference...
The above function must be called after you executed the search query in your existing code. It can be called in the next (testing) way:
Sub testGetFilteredFiles()
Dim C As Collection, El As Variant
Set C = GetFilteredFiles("C:\Teste VBA Excel\")'use here the folder path you used for searching
For Each El In C
Debug.Print El
Next
End Sub
The above solution iterates between all IExplorer windows and return what is visible there (after filtering) for the folder you initially used to search.
You can manually test it, searching for something in a specific folder and then call the function with that specific folder path as argument ("\" backslash at the end...).
I've forgotten everything I ever knew about VBA, but recently stumbled across an easy way to execute Explorer searches using the Shell.Application COM object. My code is PowerShell, but the COM objects & methods are what's critical. Surely someone here can translate.
This has what I think are several advantages:
The query text is identical to what you wouold type in the Search Bar in Explorer, e.g.'Ext:pdf Content:compressor'
It's easily launched from code and results are easily extracted with code, but SearchResults window is available for visual inspection/review.
With looping & pauses, you can execute a series of searches in the same window.
I think this ability has been sitting there forever, but the MS documentation of the Document object & FilterView method make no mention of how they apply to File Explorer.
I hope others find this useful.
$FolderToSearch = 'c:\Path\To\Folder'
$SearchBoxText = 'ext:pdf Content:compressor'
$Shell = New-Object -ComObject shell.application
### Get handles of currenlty open Explorer Windows
$CurrentWindows = ( $Shell.Windows() | Where FullName -match 'explorer.exe$' ).HWND
$WinCount = $Shell.Windows().Count
$Shell.Open( $FolderToSearch )
Do { Sleep -m 50 } Until ( $Shell.Windows().Count -gt $WinCount )
$WindowToSerch = ( $Shell.Windows() | Where FullName -match 'explorer.exe$' ) | Where { $_.HWND -notIn $CurrentWindows }
$WindowToSearch.Document.FilterView( $SearchBoxText )
Do { Sleep -m 50 } Until ( $WindowToSearch.ReadyState -eq 4 )
### Fully-qualified name:
$FoundFiles = ( $WindowToSearch.Document.Folder.Items() ).Path
### or just the filename:
$FoundFiles = ( $WindowToSearch.Document.Folder.Items() ).Name
### $FoundFIles is an array of strings containing the names.
### The Excel portion I leave to you! :D

Why do we need to use vbObjectError constant when raising user-defined errors in VBA? [duplicate]

This question already has answers here:
What numbers should be used with vbObjectError?
(3 answers)
Closed 10 months ago.
Microsoft Visual Basic for Applications 7.1; Version 1088
I created a custom error handler by following online tutorials and I've been using it for about a year now but I still don't get the part where vbObjectError constant is added to a number between 513-65535, which is reserved for user-defined errors. Most tutorials would recommend to use Err.Raise vbOjectError + 1000 as an example to generate custom errors. The reason for this is to avoid overlapping with errors 0-512, which is reserved for system errors. If I have to write a code around that idea, the code would look like this:
Option Explicit
Sub raiseError()
On Error GoTo errorHandler
Dim x As Double
Dim y As Double
Let x = 4.8
Let y = 5.5
If x <> y Then
Err.Raise vbObjectError + 1000
End If
errorHandler:
Select Case Err.Number
Case vbEmpty
MsgBox "alright!"
Case vbObjectError + 1000
MsgBox ("User-defined error '" & Err.Number & "':" & _
vbNewLine & _
vbNewLine & _
"X is not equal to Y")
Case Is <> vbObjectError + 1000
MsgBox "All other errors"
End Select
End Sub
Now, quoting Microsoft from this documentation:
"Visual Basic errors (both Visual Basic-defined and user-defined errors) are in the range 0–65535. The range 0–512 is reserved for system errors; the range 513–65535 is available for user-defined errors.
When setting the Number property to your own error code in a class module, you add your error code number to the vbObjectError constant. For example, to generate the error number 513, assign vbObjectError + 513 to the Number property."
But what confuses me is vbObjectError constant has a value of -2147221504. As you can see if you run the code, the sum of vbObjectError and 1000 or any number between 513–65535 is far from the range 513–65535, which is available for user-defined errors according to Microsoft.
If I need to use error numbers in the range of 513–65535, why not use those numbers directly like Err.Raise 513 or Err.Raise 1000?
I'd really appreciate any clarifications from you guys. Thank you all very much.
I finally found a good answer to this question. The Microsoft documentation for Err.Number explains it well and provides this example:
' Using Number property with an error from an
' Automation object
Dim MyError, Msg
' First, strip off the constant added by the object to indicate one
' of its own errors.
MyError = Err.Number - vbObjectError
' If you subtract the vbObjectError constant, and the number is still
' in the range 0-65,535, it is an object-defined error code.
If MyError > 0 And MyError < 65535 Then
Msg = "The object you accessed assigned this number to the error: " _
& MyError & ". The originator of the error was: " _
& Err.Source & ". Press F1 to see originator's Help topic."
' Otherwise it is a Visual Basic error number.
Else
Msg = "This error (# " & Err.Number & ") is a Visual Basic error" & _
" number. Press Help button or F1 for the Visual Basic Help" _
& " topic for this error."
End If
MsgBox Msg, , "Object Error", Err.HelpFile, Err.HelpContext
The key is that you are expected to subtract the large negative number from Err.Number and do your Select Case on the result. 0 - 65535 means the error was generated by Err.Raise.
As nobody answered, I'll hazard a (hopefully educated) guess. The "error numbers" generated aren't really those between 0 and 65535 (2^16-1). Those numbers are error offsets that create a negative error code.
For example, in Access, you'll often see positive error numbers (like 3146 if you can't connect to a DAO workspace). I wouldn't call those "user errors", but they are out of the "system error" range.
Also, if the true error numbers couldn't be larger than 65535 (the largest signed 16-bit number), you wouldn't need a Long type to hold them.
Finally, if you've ever noticed some error codes displayed by Microsoft products, you'll see hex codes like "8xxxxxxx", which are large negative numbers in signed decimal, as if they added vbObjectError to their own internal error numbers.
So your error messages between 513 and 65535 are really convenient numbers for you to use to create error codes by adding to vbObjectError. I suppose it also makes it easier to create a type that stores error information (error number, Description, Help ID, etc.) and create an array of those types. For example, Errors(0) would return the type with error number 513 and other information that you might need in your ERR.Raise statement.
But why is vbObjectError equal to -2147221504? I don't know. That's not -(2^31) + 512. In hex, it's FFFFFFFF80040000. I guess you'll have to ask Microsoft about that one.
For more information, here's another site's thoughts on this: http://www.vbforums.com/showthread.php?570075-vbObjectError-what-is-it-for
It's better and more secure use vbObjectError + 1001 based on this Microsoft article, Trappable errors, where it is said:
Unused error numbers in the range 1–1000 are reserved for future use by Visual Basic.
I was using vbObjectError + 513 a lot in my Enums definitions inside Interfaces for controling errors in the Classes that implement that interfaces but on one ocassion I've got an ambiguous name error while I was trying to use a second element from an Enum where the first element were equal to vbObjectError + 513.
Public Enum WorkbookXErrors
InvalidExtension = vbObjectError + 513
CannotCreateObject '***I got an error trying to use this Enum element.***
End Enum
Solution: I only changed to InvalidExtension = vbObjectError + 1001 and since then everything it's ok.
Greetings,

Evaluate statement (#DbLookUp) doesn't work with Lotusscript

The last week I asked how to solve an error in an evaluate statement (Error in Evaluate statement macro).
Once fix it, I have other error with the same evaluate statement, it doesn't give me any value.
I will describe what I have and what I try.
#DbLookup in Calculate Text
I have this code into in an calculate Text and it works fine.
suc := #Trim(#Left(LlcPoliza;2));
_lkp := _lkp := #DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D"+suc; "FullName");
#If( #IsError( _lkp ) ; " " ; _lkp );
#Name([CN];_lkp)
LlcPoliza is a document field (doc.LlcPoliza) and in a document it has for example the value C2H2H2.
The formula give first the value C2 and then look up into People2 who is D+C2 and give me a person.
It works fine.
Evaluate Statement (#DbLookup) in a Class
I have a class DirectorSucursal.
Class DirectorSucursal
Private m_branch As String
'Constructor class
Public Sub New (branch)
Dim subString As String
subString = Left(branch, 2)
me.m_branch = subString
End Sub
'Deleter Class
Public Sub Delete
End Sub
'Sub show the code about Suc
Public Sub GetCodSuc
MsgBox m_branch
End Sub
'Function get the name director
Public Function getNameDirector As String
Dim varResult As Variant
varResult = Evaluate({#DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D} & m_branch & {"; "FullName)"})
getNameDirector = CStr( varResult(0) )
End Function
End Class
Then, in a button I instantiate the new object DirectorSucursal with the parameter of the field doc.LlcPoliza(0) like this.
Sub Click(Source As Button)
Dim director As New DirectorSucursal(doc.LlcPoliza(0))
director.GetCodSuc
director.getNameDirector
end Sub
The field doc.LlcPoliza(0) has the value C2H2H2. GetCodSuc show the value C2, but the function getNameDirector doesn't work.
It shows the error:
Operation failed
Evaluate Statement (#DbLookup) in click button
I have tried the same but into a click sub.
Sub Click(Source As Button)
Dim subString As String
subString = Left(doc.LlcPoliza(0), 2)
Dim eval As String
eval = Evaluate({#DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D} & subString & {"; "FullName)"})
Msgbox eval
End Sub
The field doc.LlcPoliza(0) has the value C2H2H2. But it doesn't work
It shows the error:
Operation failed
My question is: what am i doing wrong? Why the code works fine in a calculate text with #Formula but with Lotusscript not?
Thanks.
EDIT 1:
I have added and Error Goto, modified the class code, modified #dblookup in calculate text and I have this error:
Error in EVALUATE macro
Please read documentation and use help! evaluate always returns an ARRAY, as stated in the help:
Return value
variant
The result of the evaluation. A scalar result is returned.
To make your code return a STRING you need to change it like this:
Public Function getNameDirector As String
Dim varResult as Variant
varResult = Evaluate({#DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D} & m_branch & {"; "FullName")})
getNameDirector = Cstr( varResult(0) )
End Function
The CStr is just there for the case where the #DBLookup returns an error or a number (both possible)
Just a few things in general:
NEVER write even one line of LotusScript- code without error handler. It will cause you trouble FOR SURE. If you had error handling in place, then it would have told you in which line the error occured...
NEVER use the result of #DBLookup without checking for #IsError... It will cause lot of troubles when the lookup fails.
IF you use #Iserror, then don't do the Lookup twice, assign the lookup to a variable and check that one for #Iserror, like this. Otherwise performance will go down in big forms:
Example:
_lkp := #DbLookup("":"NoCache";"C1256EAD:00478951";"People2"; "D"+suc; "FullName");
#If( #IsError( _lkp ) ; " " ; _lkp )
EDIT: As Knut correctly stated in his answer the real cause for the error was a typo in the formula ( Fullname)" instead of Fullname") that I fixed in my example as well.
1) My suggestion is to never (or at least very seldom) use Evaluate() in Lotusscript. You have proper Lotusscript functionality to do almost everything.
One of the major reasons is that the code is very hard to debug (which is what you are now experiencing).
2) Don't use extended notation when you work with fields. The best practice is to use the GetItemValue and ReplaceItemValue methods of the NotesDocument class for performance reasons as well as compatibility reasons.
3) In the examples with buttons you have a reference to doc, but it is never declared or initialized in the code. If you would use Option Declare at the top of your code you would catch these kinds of errors.
4) I also reccomend against using replica ID to reference databases, that makes it very hard to maintain in the future. Unless you have a very good and convincing reason, reference them by server and filename instead.
I would suggest you refactor your code to something like this:
'Function get the name director
Public Function getNameDirector() As String
Dim db as NotesDatabase
Dim view as NotesView
Dim doc as NotesDocument
Dim key as String
Dim fullname As String
Dim varResult As Variant
Set db = New NotesDatabase("Server/Domain","path/database.nsf")
If db Is Nothing Then
MsgBox "Unable to open 'path/database.nsf'"
Exit Function
End if
Set view = db.GetView("People2")
If view Is Nothing Then
MsgBox "Unable to access the view 'People2'"
Exit Function
End if
key = "D" & m_branch
Set doc = view.GetDocumentByKey(key)
If doc Is Nothing Then
MsgBox "Could not locate document '" & key & "'"
Exit Function
End if
fullname = doc.GetItemValue("FullName")(0)
End Function
Ando of course update the button actions in the same way.
Yes, it is a few lines longer, but it is much more readable and easier to maintain and debug. And you have error handling as well.
Change your last part in #DbLoookup code line to:
"FullName")})

After a WMI search in VBScript, can I create my search filter BEFORE my "For Each" statement?

I've created an alternative search utility to the Windows search utility with VBScript using a WQL search, but, as it turns out, it's quite slow. I would like to speed it up and I think I can do it, but I would need to place my search filter AFTER my WQL search and BEFORE my For Each statement. Is this even possible?
I've already tested by filtering in the WQL search, but it's about 40% faster if I filter after the WQL search. I've also tested with and without iFlags, but they tend to slow the search quite a bit, even though MS seems to believe otherwise.
Since the user can search by filename, creation date, last modified date and/or file size, if the filter is after the For Each statement then the script has to create the search filter each time it enumerates a file. I'd like to create the filter once in the hope of shaving some time off the search.
This will probably make better sense when you take a look at the snippet of code I've posted. Note that the sub subCreateSearchString will have calls to other search options and functions (ie: convert from UTC to local time, format file sizes, etc.)
Dim strSearchName, strComputer, objSWbemServices, objFile, colFiles
Dim strFileName, strReturnedFileName, strQueryDriveAndPath
strSearchName = "test" 'Text being searched for - change as needed
strQueryDriveAndPath = "PATH = '\\Drop_RW\\' AND DRIVE = 'D:'" 'Path and drive in which to search - change as needed
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colFiles = objSWbemServices.ExecQuery("Select * from CIM_DataFile WHERE " & "" & strQueryDriveAndPath & "")
'* I'd like to place the call to "subCreateSearchString" here
On Error Resume Next
For Each objFile in colFiles
strReturnedFileName = objFile.Name
subCreateSearchString ' Search filter - it works when placed here
If strSearchForString Then
MsgBox "File matches:" & vbCrLf & strReturnedFileName
Else
MsgBox "File DOES NOT match" & vbCrLf & strReturnedFileName
End If
Next
Sub subCreateSearchString
'* Set Filename Variable for search:
strFileName = InStr(LCase(strReturnedFileName), LCase(strSearchName))
strSearchForString = strFileName
End Sub
Since you depend on the names of the files you're iterating over in the For Each loop: no, not possible.
I'd strongly recommend making some adjustments, though.
Use a Function rather than a Sub if you want to return something from a subroutine.
Avoid using global variables. They have a nasty tendency of introducing undesired side effects and also make debugging your code a pain in the rear. Pass values into your subroutines via parameters, and return values as actual return values.
The returned value is an integer (or Null), but you use it like a boolean and named your variables (and sub) as if it were a string. Don't do that. Name your functions/procedures after what they're doing, and name your variables after what they contain. And if you want to use a boolean value make your function actually return a boolean value.
Avoid Hungarian Notation. It's pointless code-bloat the way most people use it. Even more if your naming doesn't even match the actual type.
Do not use global On Error Resume Next. Ever. It simply makes your code fail silently without telling you anything about what actually went wrong. Keep error handling as local as possible. Enable it only for single commands or short code blocks, and only if there is no other way to avoid/handle the error.
Function IsInFilename(searchName, fileName)
IsInFilename = InStr(LCase(fileName), LCase(searchName)) > 0
End Function
For Each objFile in colFiles
If IsInFilename(strSearchName, objFile.Name) Then
MsgBox "..."
Else
MsgBox "..."
End If
Next

SAP RFC call returns "Error 0" in RETURN parameter from vb

Hi everybody and thanks in advance.
I'm trying to call a SAP BAPI using RFC from vb but I'm having some problem to get the result of the call.
The BAPI "BAPI_GL_ACC_EXISTENCECHECK" (from General Ledger Account module) has two parameters,
COMPANYCODE and GLACCT, and a RETURN parameter.
I wrote this piece of code to make the call and I had no problem to establish the SAP Connection (I use the SAP Logon Control OLE/COM object to do the job), and I tried to make the RFC call.
Also in this case I make the call without problems (it seems, not sure about it ...), because the RFC call returns true and no exception.
However, looking through the objReturn object/parameter, it has a value "Error 0" in it.
I was expecting a complex structure like the BAPIRETURN object in SAP or something similar if the account doesn't exist.
Tried to search with Google and SAP forums but I haven't found a real solution to my problem, so here I am to ask you all if you have some idea to solve this problem (maybe I'm only making a wrong call!!! I'm quite a newbie on SAP integration ...).
BTW, Final Notes: after a lot of RFC_NO_AUTHORIZATION on the SAP side, they gave me a SAP_ALL / S_RFC authorization (sort of, not a SAP expert) and the error RFC_NO_AUTHORIZATION disappeared, but not the Error 0 return
Dim sapConn As Object
Dim objRfcFunc As Object
Dim SAPMandante As String
Dim SAPUtente As String
Dim SAPPassword As String
Dim SAPLingua As String
Dim SAPApplicationServer As String
Dim SAPNumeroSistema As Variant
Dim SAPIDSistema As String
Dim SAPRouter As String
Dim FlagInsertLogin As Integer
Dim FlagLogin As Variant
On Error GoTo ErrorHandler
Set sapConn = CreateObject("SAP.Functions") 'Create ActiveX object
'Silent Logon
SAPMandante = "xxx"
SAPUtente = "yyyy"
SAPPassword = "zzzzzz"
SAPLingua = "IT"
SAPApplicationServer = "www.xxx.com"
SAPNumeroSistema = x
SAPIDSistema = "zzz"
SAPRouter = ""
FlagLogin = SilentLogin(sapConn, SAPMandante, SAPUtente, SAPPassword, SAPLingua, SAPApplicationServer, SAPNumeroSistema, SAPIDSistema, SAPRouter) 'IT WORKS, NO PROBLEM HERE
If FlagLogin = False Then
'Explicit Logon
If sapConn.Connection.logon(0, False) <> True Then
MsgBox "Cannot Log on to SAP", 16, "Query Interrupted"
sapConn.Connection.logoff
Set sapConn = Nothing
InsertCash = False
Exit Sub
End If
End If
'BAPI RFC Call
Set objRfcFunc = sapConn.Add("BAPI_GL_ACC_EXISTENCECHECK")
objRfcFunc.exports("COMPANYCODE") = "C100"
objRfcFunc.exports("GLACCT") = "0000000001" 'Inexistent
Rem *** BAPI CALL ***
If objRfcFunc.Call = False Then
ErrorMsg = objRfcFunc.Exception 'Message collection
MsgBox ErrorMsg, 16, "Errore"
sapConn.Connection.logoff
Exit Sub
else
Dim objReturn As Object
Set objReturn = objRfcFunc.imports("RETURN")
End If
You need to put
Dim objReturn As Object
Set objReturn = objRfcFunc.imports("RETURN")
BEFORE objRfcFunc.Call
i.e. you must state what you're importing from the function before you call it. I usually put it alongside the .exports() lines.
The problem was solved, please take a look at this thread ...
http://sap.ittoolbox.com/groups/technical-functional/sap-dev/sap-rfc-call-returns-error-in-return-parameter-from-vb-before-the-rfc-call-4894968#M4902486

Resources