SAP Logon from Excel, permissions missing? - excel

I'm working with VBA and GuiXT separated and now I'm trying to use the SAP GUI VBA integration instead, but i think it's not working because I'm missing a permission.
I tried the code I've found in this thread:
Sub test()
Dim SapGuiAuto As Object
Dim SAPApp As Object
Dim SAPCon As Object
Dim session As Object
Set SapGuiAuto = GetObject("SAPGUI")
Set SAPApp = SapGuiAuto.GetScriptingEngine
Set SAPCon = SAPApp.Children(0)
Set session = SAPCon.Children.ElementAt(0)
SAPCon.FindById("wnd[0]").Maximize
End Sub
It runs and SAP informs me that a script tries to connect to SAP, but the line Set session = SAPCon.Children.ElementAt(0) gives me error 614: "The enumerator of the collection cannot find en element with the specified index".
So I googled and found out, that I'm missing the option "Script recording and playback" in SAP, it's greyed out. And i googled further and I found out, that I'm missing the permission to record or playback a script.
Because of that I'd like to know: if I don't have the permission in SAP to record or playback a script, then that's the reason for my not working VBA code, right?

Related

SAPGUI Script that used to work is giving me Run time error'91': object variable or with block variable not set**

I wrote a script on excel vba for SAP GUI and used to work fined but currently I'm getting
Run time error'91': object variable or with block variable not set
This error happens on the below bolded set objConn = objgui.children(0) line.
I always have the page logon to proceed but its keep giving me error.
Additionally, the scripting function does not work on SAP either. It used to work but not anymore. When I record it and play it back it says it can't find the file.
Scripting is enabled. I can press the red record button and finish record by yellow square button but nothing is getting recorded and no files are saved. However, it says:
SAP frontend server: Scripting support is disabled on the server
Option Explicit
Public SapGuiAuto
Public objGui As GuiApplication
Public objConn As GuiConnection
Public session As GuiSession
Sub dd()
Dim i As Integer
Dim lastrow As Long
Set SapGuiAuto = GetObject("SAPGUI")
Set objGui = SapGuiAuto.GetScriptingEngine
# Set objConn = objGui.Children(0)
Set session = objConn.Children(0)
lastrow = ThisWorkbook.ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row 'Define where is last row
On Error Resume Next
For i = 2 To lastrow 'Row 2 to lastrow will be inputted
If ActiveSheet.Cells(i, 1) = "Z2" Then
session.findById("wnd[0]/tbar[0]/okcd").Text = "niw21" 'Input niw21 t-code in SAP
End If
Next i
End Sub
I tried remove and install the SAP Logon 770.
I made sure the reference is added on the VBA (SAP GUI Scripting API).
You should make sure that you have installed your SAP GUI software with the component "SAP GUI Scripting" selected, otherwise you can't use SAP GUI Scripting from your laptop.
NB: to enable Server-Side Scripting (source: this question):
Start the SAP Logon and log in to the SAP server.
Run the ‘RZ11’ transaction (type ‘RZ11 ‘and click the green tick button)
Type ‘sapgui/user_scripting’ in the Maintain Profile Parameters window.
Click the ‘Display’ button
Click ‘Change Value’ in the Display Profile Parameter Attributes window.
Type ‘TRUE’ in the ‘New value’ field.
Save the settings and log out from SAP Logon.
Exit from the SAP Logon program (click the red cross button in the toolbar, or click the ‘X’ window button to close the window and the application). You may be prompted to save any unsaved changes, if you haven’t done so already.
If you're not authorized, please ask the SAP system administrator.

(Excel VBA) Outlook Application CreateItem Fails in Certain Situation

In our company .xlsm, I'm using "standard" macro to send e-mails via Outlook:
Dim olApp As Object, olMail As Object
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
If olApp Is Nothing Then
Set olApp = CreateObject("Outlook.Application")
End If
On Error GoTo 0
Set olMail = olApp.CreateItem(0)
With olMail
'properties, methods, events
End With
The thing is, it works on all company computers except for one. On this one:
If Outlook client is closed when running macro, everything works fine;
If Outlook client is opened when running macro, it returns Error '91' (Object variable not set) on Set olMail = olApp.CreateItem(0).
What could be the cause?
Your Excel Application must be run under the same security context with Outlook running to be able to get the running instance.
If Outlook client is opened when running macro, it returns Error '91' (Object variable not set) on Set olMail = olApp.CreateItem(0).
If you run Excel with admin privileges you need to run Outlook as well with admin privileges to be able to connect them together.
Also you may try to use the early-binding technology instead of late-binding one. For that you need to add an Outlook COM reference in the Excel COM References dialog (see the VBA editor). Read more about that in the Using early binding and late binding in Automation article.

User Defined Functions (UDF) from Access Query to Excel using VBA OpenRecordset failed - Undefined Function

How do I get the results of a query from Access into Excel if it has a UDF?
I receive the following error: "Run-time error '3085': Undefined function 'XXXX' in expression". The error occurs when opening an (access query) recordset from Excel VBA. The query being opened has a user defined function (UDF) which is triggering the error.
The code is in Excel Office 365. The query is in Access Office 365.
I have successfully utilized the query being called (and others with the UDFs) for about twelve months, and "suddenly" it is not working any more. I have googled and tested many options with no success.
Most threads say it can't be done, or to not use a udf but try a built-in that works. I am challenging those responses because it has worked previously. The main udf I am using is one called "iMax" which is written about in other posts. It functions like max() in Excel. (No max(x,y) function in Access)
I have also seen threads that suggest executing this in two steps: 1 - change the query to a make table query. 2 - pull the table results into Excel. While I could maybe get away with this (after much rework), it would result in me making many temporary tables with thousands and thousands of rows and doesn't seem very slick.
I have compiled vba and compacted the db with no impact to my problem.
As a long shot I created a dummy database with a simple udf public function that returned the number 1, a simple query that returns three records and a field for the function results. This gets the same error when pulling into Excel.
Sub RunQuery()
Dim MyDatabase As dao.Database
Dim qdf As dao.QueryDef
Dim rs As dao.Recordset
Dim qryname As object
Dim SheetName As String
Set MyDatabase = DBEngine.OpenDatabase _
("SomePath\SomeFilename.accdb")
For Each qryname In Range("SomeRange")
Set rs = MyDatabase.OpenRecordset(qryname) '<<<ERROR IS HERE
SheetName = "SomeSheetName"
With Sheets(SheetName)
.ListObjects(SomeTableName).DataBodyRange.Rows.ClearContents
.Range("A2").CopyFromRecordset rs
End With
Set rs = Nothing
Set qdf = Nothing
Next qryname
End Sub
For all queries in the For loop that do not have a udf, the results are pulled and dumped into a series of tables in Excel. Any query with a udf errors at the "Set rs = Mydatabase.OpenRecordset(qryname)
If you run the query within an Access application session, as Gustav suggested, the expression service can handle the UDF in your query.
Here is a quick tested Excel VBA snippet which pulls data from a query which includes a UDF:
Const cstrDbFile As String = "C:\share\Access\Database2.accdb"
Dim objAccess As Object
Dim rs As Object
Dim ws As Worksheet
Dim strSelect As String
Set objAccess = CreateObject("Access.Application")
objAccess.Visible = True ' useful during testing '
objAccess.OpenCurrentDatabase "C:\share\Access\Database2.accdb"
strSelect = "SELECT ID, DummyFunction('a', '', 'c') FROM Dual;"
Set rs = objAccess.CurrentDb.OpenRecordset(strSelect)
If Not rs.EOF Then
Set ws = ThisWorkbook.Sheets("Sheet1")
ws.Range("A1").CopyFromRecordset rs
End If
rs.Close
objAccess.Quit
Most threads say it can't be done,
and they are right.
Your only option is to use automation to open an instance of Access and, within this, run the query.
Well, as noted, most are saying this should not work.
However, if you are 100% sure it was and did work at one time?
You need to set the "sandbox" mode of the JET (now ACE) database engine.
The expression service normally does not allow evaluation of VBA functions as a security setting to prevent SQL injection, or code running outside of Access to allow SQL to run + call VBA functions. At one time, this feature did default to "on", but now the default is set to access only.
You have to set the folder where Access application as trusted. This should allow the VBA functions to now work. so, make sure you set the folder as trusted.
If the location (folder) where your access application is NOT trusted, then Access will use sandbox mode, and VBA in the SQL will not run.
If the location is trusted, THEN access uses the registry setting on your computer.
My bets are that the location is not trusted - so you always get sandbox mode for SQL in Access.
If you are 100% sure that the folder location is set as trusted in Access, and you still receive the errors, then you have to change the registry setting for Access "sandbox" mode.
The setting in the registry is outlined here:
https://support.office.com/en-us/article/Turn-sandbox-mode-on-or-off-to-disable-macros-8CC7BAD8-38C2-4A7A-A604-43E9A7BBC4FB
The registry settings are:
for x32 bit access:
Software\Microsoft\Office\ClickToRun\Registry\Machine\Software\
Wow6432Node\Microsoft\Office\16.0\Access Connectivity Engine\Engines
The above is for Office 2016
14 = 2010
15 = 2013
16 = 2016
The key value for sandbox mode is:
0 to 3
0 Sandbox mode is disabled at all times.
1 Sandbox mode is used for Access, but not for non-Access programs.
2 Sandbox mode is used for non-Access programs, but not for Access.
3 Sandbox mode is used at all times. This is the default value, set when you install Access
So, from above, you want a setting of 0.

Excel VBA late bind Microsoft DAO 3.6 object library

Can anybody post a snippet on how to create a reference to Microsoft DAO 3.6 object library from Excel 2007?
I gather I need to use the CreateObject method but I can't find anything online concerning the right parameters to reference DAO 3.6 specifically.
I need to late bind as I won't be able to manually set references on each PC using the file.
Many thanks
Thes best place to learn about DAO is Microsoft's Developer Network. There is a lot of documentation on the subject.
VBA supports three data access technologies. DAO, ADO and RDO. Of these Microsoft recommend you use ADO, the newer of the three.
I've been trying to write a late bound Excel DAO example, but I've run into a little trouble. I've only been able to get an early bound approach working.
Sub ExampleEarly()
Dim DB As DAO.database
Dim RS As DAO.Recordset
' Connect to Excel spreadsheet and read from tab called VA.
Set DB = OpenDatabase("C:\Example\ExcelFile.xls", False, True, "Excel 8.0;HDR=Yes")
Set RS = DB.OpenRecordset("SELECT * FROM [VA$]")
'Close the recordset
RS.Close
DB.Close
Set RS = Nothing
Set DB = Nothing
End Sub
ADO can be late bound like so:
Dim cn As Object
Dim rs AS Object
Set cn = CreateObject("ADODB.Connection")
Set rs= CreateObject("ADODB.Recordset")
For DAO late binding. Not fully tested compatibility if you use ADO in your code, but it works so far in my projects.
Dim db As Object 'late binding without reference, seems to work, but might cause trouble, not tested
Dim tbl As Object
Dim dbe As Object
Set dbe = CreateObject("DAO.DBEngine.120") 'depends on win version!
Set db = dbe.OpenDatabase(file)
Set tbl = db.TableDefs("CAPEX")

Access Shared Network Folder

I need to access via VBA a folder hosted on a Network File Server. The folder is accessible in writing only via a Service Account (different from normal user accounts) for which I do have username and password.
Via the UI I can see that folder and map it as a local drive but in order to access it in writing I need to log off from Windows and logon via the Service Account.
Is there any way to access the network folder during a normal user session but hardcoding username and pwd in the VBA code?
I did try mapping the folder as local drive with:
Set WshNetwork = CreateObject("WScript.Network")
WshNetwork.MapNetworkDrive "S:", "\\corp-server\HostingFolder", False, Username, pwd
but did not work ("S" drive was not mapped). If instead I do the same but without providing Username and password:
Set WshNetwork = CreateObject("WScript.Network")
WshNetwork.MapNetworkDrive "S:", "\\corp-server\HostingFolder"
it works perfectly.
Wondering now if what I am trying to do is actually possible? If not, is there any alternative?
Thanks
You might find this answer of value in your testing.
Essentially, I would check a couple things...
Make sure you are not already connected to this resource using the current logged in user. If you are, you might get an error message like the following:
Make sure you are using the domain\username syntax in your username.
Otherwise I think you are the right track. I put together some sample code based on the link above, and was able to successfully connect to a network share under a different user name and iterate through a list of files.
(Note the tip that you don't actually have to map a drive to establish a connection.)
The following code is a really quick (working) VBA implementation of the sample listed at Access network share from within VBScript eg FileSystemObject
Public Sub TestNetShareName()
Dim NetworkObject As Object
Dim FSO As Object
Dim Directory As Object
Dim Filename As Object
Dim ServerShare As String
Dim UserName As String
Dim Password As String
ServerShare = "\\corp-server\HostingFolder"
UserName = "mydomain\myuser"
Password = "freddie123"
Set NetworkObject = CreateObject("WScript.Network")
Set FSO = CreateObject("Scripting.FileSystemObject")
NetworkObject.MapNetworkDrive "", ServerShare, False, UserName, Password
Set Directory = FSO.GetFolder(ServerShare)
For Each Filename In Directory.Files
Debug.Print Filename.Name
Next
Set Filename = Nothing
Set Directory = Nothing
Set FSO = Nothing
NetworkObject.RemoveNetworkDrive ServerShare, True, False
Set NetworkObject = Nothing
End Sub

Resources