I have 2 ALM's (11 and 12.5), with the below code, i am able to connect to ALM11, but it says invalid user name and password for 12.5 ALM, (user credentials are correct)
Function ALM_Connection(ByRef TDConnection, server, user, pwd)
On Error Resume Next
Dim fileArray
almLogin.connectionMessage.ForeColor = vbBlue
Set TDConnection = CreateObject("tdconnection")
sUserName = user
sPassword = pwd
If Trim(sUserName) = "" Or Trim(sPassword) = "" Then
almLogin.connectionMessage.ForeColor = vbRed
almLogin.connectionMessage.Caption = "Please Enter the data and click on 'Authenticate'"
ALM_Connection = False
Exit Function
End If
almLogin.connectionMessage.Caption = " Please Wait.. "
Application.Wait (Now + TimeValue("0:00:02"))
TDConnection.InitConnectionEx server
TDConnection.Login sUserName, sPassword
If (TDConnection.loggedin <> True) Then
almLogin.connectionMessage.ForeColor = vbRed
almLogin.connectionMessage.Caption = "Invalid UserName or Password"
ALM_Connection = False
Exit Function
Else
almLogin.connectionMessage.Caption = "Logged In Successfully"
ALM_Connection = True
End If
End Function
any help is appreciated
I generally use the below syntax to create the OTA object
Set TDconnection = CreateObject("tdapiole80.tdconnection")
However, Since the connection and authentication are enclosed inside "On Error Resume Next", the error message may not actually reflect the real cause.
So, this is what I would do to debug.
Remove the On Error Resume Next and check whether the code can create a TDConnection Object
Installing the correct version of HP ALM Addin.
Console out "err.description" to understand the real cause
As I can see from your code it throws message "Invalid UserName or Password" in any case when TDConnection.loggedin property is not True, but it can be because of other reason, e.g. wrong OTAClient.dll library (they are not backward compatible). So in general case you should register your ALM client on the machine (server_url/qcbin -> Tools -> Register client) and then try one more time.
If it doesn't help, you can try to rewrite your code using sample from official documentation http://alm-help.saas.hpe.com/en/12.50/api_refs/ota/topic96.html
This problem is due to the Project unavailable. Also check if you have access to any one of the projects in the v12.5.
Thanks.
Related
My SAP-GUI has Scripting installed and Scripting is enabled.
Like in this screenshot:
In this Introduction to SAP GUI Scripting in "Step 2: Setup your SAP System" you need to call RZ11.
I don't have permissions to call RZ11.
Is there a way to detect this (sapgui/user_scripting on or off) via a script?
At the moment I use below code, but the list of connections is always empty:
import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
sapgui = win32com.client.GetObject("SAPGUI")
system = query.get('system')
client = query.get('mandant')
session = False
application = sapgui.GetScriptingEngine
seen = []
for i_conn in range(0, application.Connections.Count):
seen.append('i_conn=%s session_count=%s' % (i_conn, application.Connections.Item(i_conn).Sessions.Count))
for i_sess in range(0, application.Connections.Item(i_conn).Sessions.Count):
session_info = application.Connections.Item(i_conn).Sessions.Item(i_sess).Info
system_of_session = session_info.SystemName
client_of_session = session_info.Client
if system_of_session == system and client_of_session == client:
connection = application.Connections.Item(i_conn).Children(i_sess)
session = connection.Children(i_sess)
break
seen.append('system=%s client=%s' % (system_of_session, client_of_session))
if session:
break
else:
info_popup('You are not logged into system %s in Client %s! Seen:\n%s' % (
system, client, '\n'.join(seen)))
return
When you don't have sufficient priviledges in sap, the fact that you can't connect is a pretty good indication that the user does not have scripting enable (assuming the user has a active sap session running), other wise you could just test with 'session.findById("wnd[0]/usr/tblSAPLCMDITCTRL_3500").getAbsoluteRow(3).selected = true' and check for errors.
Also, I suggest you factor in "SAPGUISERVER' in your sapgui = win32com.client.GetObject("SAPGUI") connection if "SAPGUI" fails.
As I know sapgui/user_scripting is a system-level = application level setting but not a user-level. So, if you have no permissions to run RZ11 tcode then you have no opportunity or permissions to read applicaton server settings and, of course, no permissions to change it. You have to contact your basis administrator to verify this application settings with him.
You see, SAP limited scripting abilities due to possible vulnerability, that's why scripting support should be turned on both on client side and on application server side.
If you have access to interrogate the registery you could write a cutom function to check SAPGUI is installed and flagged e.g:
Public Sub CheckKey()
Const cRegKey As String = "HKEY_CURRENT_USER\Software\SAP\SAPGUI Front\SAP Frontend Server\Security\UserScripting"
If CheckSAPGUI(cRegKey) Then
MsgBox "User has SAPGUI installed and initialized", vbOKOnly Or vbInformation, Application.Name
Else
MsgBox "User does not have SAPGUI installed", vbOKOnly Or vbCritical, Application.Name
End If
End Sub
Public Function CheckSAPGUI(RegKey As String) As Boolean
Dim rtn As Variant
On Error Resume Next
rtn = vbNullString
With CreateObject("wscript.shell")
rtn = .RegRead(RegKey)
End With
If Len(rtn) = 0 Then
CheckSAPGUI = False
ElseIf Val(rtn) <> 1 Then
CheckSAPGUI = False
Else
CheckSAPGUI = True
End If
On Error GoTo 0
End Function
You should be able to modify the MsgBox comments to better suit how you want to interact with your end user
Good morning, everybody!
I've been looking for the solution in the last days but I really have not managed to succeed: I am trying to make a VBA code to:
log into SAP,
run some transactions,
export to excel.
But even the "log into SAP" part is not OK!
I tried several codes, the one below OPENS the SAP logon screen, but does not fill in any fields.
In the first attempt, I Used CreateObject("Sapgui.ScriptingCtrl.1"):
Sub Entrar_SAP()
If Not IsObject(SAPguiApp) Then
Set SAPguiApp = CreateObject("Sapgui.ScriptingCtrl.1")
End If
If Not IsObject(Connection) Then
Set Connection = SAPguiApp.OpenConnection("xxxxxxx)", True)
End If
If Not IsObject(session) Then
Set session = Connection.Children(0)
End If
session.findById("wnd[0]/usr/txtRSYST-MANDT").Text = "100"
session.findById("wnd[0]/usr/txtRSYST-BNAME").Text = "user"
session.findById("wnd[0]/usr/pwdRSYST-BCODE").Text = "pass"
session.findById("wnd[0]/usr/txtRSYST-LANGU").Text = "PT"
session.findById("wnd[0]/usr/txtRSYST-LANGU").SetFocus
session.findById("wnd[0]/usr/txtRSYST-LANGU").caretPosition = 2
session.findById("wnd[0]").sendVKey 0
In the second attempt, I tried CreateObject("SAP.Functions"), it showed:
"RFC error received. No RFC authorization for function module RFC PING"
The code is:
'Declaration
Dim objBAPIControl As Object 'Function Control (Collective object)
Dim sapConnection As Object 'Connection object
Set objBAPIControl = CreateObject("SAP.Functions")
Set sapConnection = objBAPIControl.Connection
sapConnection.Client = "xxxxx"
sapConnection.User = "xxxxxx"
sapConnection.Language = "PT"
sapConnection.hostname = "xxxxx"
sapConnection.Password = "xxxxxxxx" 'Fake password
sapConnection.SystemNumber = "4"
sapConnection.System = "xxxxxx)"
sapConnection.Logon
If sapConnection.Logon(1, True) <> True Then
MsgBox "No connection to R/3!"
Exit Sub 'End program
End If
Can someone please help me? Thanks!!
First of all, RFC is a perfectly fine method for interacting with SAP. It's not out of support.
Second, you don't have enough authorization so your code will not work even if you get the syntax right. "RFC error received. No RFC authorization for function module RFC PING". Ask your SAP team to give you access to execute RFCs remotely. Ask for SAP_S_RFCACL.
On a side note, your main object of running some transactions and exporting to Excel is quite easy to do in SAP. Maybe you should just ask your SAP team to do it for you instead of developing it in VBA?
I assume your pulling via an RFC read Table. This Connection will work fine for those.
Dim LogonControl As Object
Dim conn As Object
Dim retcd As Boolean
Set LogonControl = CreateObject("SAP.LogonControl.1")
Set conn = LogonControl.NewConnection
conn.System = "strSystemName"
conn.Client = "100"
conn.Language = "EN"
conn.User = "sUserName"
conn.Password = "strPassword"
retcd = conn.Logon(0, True) 'True = No logon GUI 'False = logon GUI
If retcd <> True Then
MsgBox "Login failed for- " & strSystemName & " -UserName or Password are incorrect, check them and run try again ."
Exit Sub
End If
Set funcControl = CreateObject("SAP.Functions")
funcControl.Connection = conn
From this Point on you can make your RFC call without any issues.
But to be truthful though, Above is almost exactly what you have as your second example. your RFC Error your getting seems like you don't have security settings for SAP to make RFC calls to whatever table your pulling from and not a problem with your login code.
Disclaimer: RFC_READ_TABLE is NOT supported by SAP and is more of a backdoor then a day to day method for pulling data.
Edit1: To Cover the Comments and not turn this into a discussion I will try and Summarize them here.
Firstly
the pop-up: If you want the pop-up for the log in then you need to change this line of code
retcd = conn.Logon(0, True)
to
retcd = conn.Logon(0, False) 'This one DISPLAYS the pop-up
Secondly
The Permissions: RFC_Read_Table uses Very Different Security Settings then a SAP t-Code uses, The technical Difference is difficult to explain but for a rule of thumb, If you cant access the SAP Table (t-Code SE16) you most likely not be able to pull it from RFC Read Table
Thirdly
If your company has Multiple SAP boxes (DEV, production, test) the Systemname would be EXACTLY what shows up on the box selection screen of SAP under name. assuming you were getting an RFC error from your second code block then the box name you used in that code would be the correct one.
You can bypass RFC controls and just go for a normal scripting that imitates a human user and manually introduces username and password. Credit to The Script Man from the SAP forums:
Sub SapLogin()
'Logs onto SAP system
Dim SapGuiApp As Object
Dim oConnection As Object
Dim session As Object
Dim SAPCon As Object, SAPSesi As Object
Dim SAPGUIAuto As Object, SAPApp As Object
Dim system As String
system = "XX" 'SAP system you will log on to like "01. ENGINEERING PRODUCTION [EG1]
If SapGuiApp Is Nothing Then
Set SapGuiApp = CreateObject("Sapgui.ScriptingCtrl.1")
End If
If oConnection Is Nothing Then
Set oConnection = SapGuiApp.OpenConnection(system, True)
End If
If SAPSesi Is Nothing Then
Set SAPSesi = oConnection.Children(0)
End If
Application.DisplayAlerts = FALSE
With SAPSesi
.FindById("wnd[0]/usr/txtRSYST-MANDT").Text = "100"
.FindById("wnd[0]/usr/txtRSYST-BNAME").Text = "USERNAME"
.FindById("wnd[0]/usr/pwdRSYST-BCODE").Text = "PASSWORD"
.FindById("wnd[0]/usr/txtRSYST-LANGU").Text = "EN"
.FindById("wnd[0]").SendVKey 0
'start extraction
.FindById("wnd[0]").Maximize
.FindById("wnd[0]/tbar[0]/okcd").Text = "/TCODEYOUWANTTORUN"
.FindById("wnd[0]").SendVKey 0
'...
'etc
'...
End With
Application.DisplayAlerts = True
MsgBox "After clicking OK, this SAP session is terminated."
End Sub
I am implementing a tool which relies on Bloombergs blpapilib2, which is the Bloomberg API COM Lib 3.5.
Before giving my user access to any refresh-data functionality, I want to make sure that the connection works. My approach so far:
Check wether the library is available and linked. Basically a loop through references does the job.
Open a connection with session.Start() . I was hoping to get an error here, but it won't give me one. Thus, step 3.
Request some data and verify it (make sure its not empty)
Surporisingly, I cannot reliably reproduce getting an empty result. I expected my session relies on a user being looged into the terminal. It seems I was wrong; even if I log out, my request will be handled and return correct data.
I can imagine two scenarios:
some background caching in the bbcom-Server
an alternative authentication method is used
I have two questions:
Q1. What is the best way to make sure a user will be able to download data?
Q2. How can I verify whether a connection has been established successfully and a user is authenticated?
Thanks.
To "cut" the connection, you need to log out and log in on a different machine. If you simply log out the feed is still available using the API.
This is how I test the connection - I think it works fairly well. I have a BloombergWrapper class that handles all the low level stuff of communicating with the API and it has the following functions:
Private pSession As blpapicomLib2.Session
Private pService As blpapicomLib2.Service
Private Sub Class_Initialize()
Dim locStatusBar As Variant
Dim locBbResult As Variant
On Error GoTo error_handler
If Application.StatusBar = False Then locStatusBar = False Else locStatusBar = Application.StatusBar
Application.StatusBar = "Connecting to Bloomberg..."
Set pSession = New blpapicomLib2.session
pSession.Start
pSession.OpenService ("//blp/refdata")
Set pService = pSession.getService("//blp/refdata")
Application.StatusBar = locStatusBar
Exit Sub
error_handler:
If InStr(Err.Description, "timeout") Then
Call MsgBox("A Bloomberg timeout has occured. Make sure you are logged on your terminal.", vbCritical + vbOKOnly, "Bloomberg error...")
End If
If locStatusBar <> "" Then Application.StatusBar = locStatusBar
End Sub
Private Sub Class_Terminate()
pSession.Stop
Set pSession = Nothing
End Sub
I keep getting an error:
System.NullReferenceException: Object reference not set to an instance
of an object.
Everytime I run the application outside the IDE, but for some magical reason, it works fine inside the IDE. I am definitely sure the error is caused by this code as the app ran smoothly when I removed it:
Public Function GetCommonFolder() As String
On Error GoTo ErrH
Dim winPath As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
Dim commonfolderpath As String
commonfolderpath = Replace(winPath & "\MyApp Data", "\\", "\")
If My.Computer.FileSystem.DirectoryExists(commonfolderpath) = False Then
System.IO.Directory.CreateDirectory(commonfolderpath)
End If
GetCommonFolder = commonfolderpath
Exit Function
ErrH:
GetCommonFolder = ""
Msgbox("Error retrieving common folder")
End Function
Does anyone here know what is causing this annoying problem?
It seems like the user that you run the program on outside the IDE doesn't have access to the common application data folder. Try executing it by "Run as administrator". Are you running on Windows Vista or newer? Maybe you have to require UAC elevation?
Wrote a small app that accesses a bunch of search websites and puts the results in a word document, which gets run a few hundred times a day.
It saves individual search results in a number of local folders so the next time those words are searched, it grabs them locally instead of loading the website again.
This works fine - even though it's not quick. People are impressed because until a few weeks ago they did this manually by literally loading up six different search websites, searching, and then copying and pasting the results in a word document.
However, our Office's internet is unreliable, and has been down the last half a day. This has meant about 400 bad searches have been saved in the local folders, and inserted into the final documents.
When a person was searching they could tell if the internet was broken and they would do their searches later. Obviously, though, this app can't tell, and because I'm not using APIs or anything, and because I am limited to using the VBA environment (I'm not even allowed MZ tools), I need to find some way to check that the internet is working before continuing with the program flow, without relying on too many references, and preferably without screenscraping for the phrase "404 Page Not Found".
I'm not very familiar with VB, and VBA is ruining me in so many ways, so there's probably some easy way to do this, which is why I'm asking here.
Appreciate any help.
Obviously, your problem has many levels. You should start by defining "connected to the internet", and go on with developing fallback strategies that include not writing invalid files on failure.
As for the "am I connected" question, you can try tapping into the Win32 API:
Private Declare Function InternetGetConnectedState Lib "wininet.dll" _
(ByRef dwflags As Long, ByVal dwReserved As Long ) As Long
Public Function GetInternetConnectedState() As Boolean
GetInternetConnectedState = InternetGetConnectedState(0&,0&)
End Function
Though depending on your network setup (proxy/NAT/firewall restrictions etc.), Windows might have a different opinion about this than you.
Trying to GET the pages you are interested in, checking on the return status in the HTTP headers (gateway timeout, 404, whatever you expect to happen when it "doen't work) might also be a way to go.
You could use MSXML library & use XMLHttpRequest class to check for things
e.g.
On Error Resume Next
Dim request As MSXML2.XMLHTTP60
request.Open "http://www.google.com"
request.Send
Msgbox request.Status
The status will give you HTTP Status code of what happened to the request.
You might have to do some more checks, depending on your scenario.
Hope that helps.
Use the following code to check for internet connection
first anable XML v6.0 in your references
Function checkInternetConnection() As Integer
'code to check for internet connection
'by Daniel Isoje
On Error Resume Next
checkInternetConnection = False
Dim objSvrHTTP As ServerXMLHTTP
Dim varProjectID, varCatID, strT As String
Set objSvrHTTP = New ServerXMLHTTP
objSvrHTTP.Open "GET", "http://www.google.com"
objSvrHTTP.setRequestHeader "Accept", "application/xml"
objSvrHTTP.setRequestHeader "Content-Type", "application/xml"
objSvrHTTP.Send strT
If err = 0 Then
checkInternetConnection = True
Else
MsgBox "Internet connection not estableshed: " & err.Description & "", 64, "Additt !"
End If
End Function
Unfortunately, this is a bit of a difficult question to answer for a couple of reasons:
How do you define a non-working internet connection? Do you check for a valid IP address? Do you ping out? How do you know that you have permissions to check these things? How do you know that the computer's firewall/antivirus isn't causing wonky behavior?
Once you've established that the connection is working, what do you do if the connection drops mid-operation?
There are probably ways to do what you want to do, but a lot of "devil's in the details" type things tend to pop up. Do you have any way to check that the saved search is valid? If so, that would probably be the best way to do this.
Building on shakalpesh's answer and the comments to it, there are (at least) two ways to get the web page into Word without parsing the XML returned by the XMLHTTP60 object.
(NB the HTTP status code of 200 indicates that "the request has succeeded" - see here)
write the XMLHTTP60.ResponseText out to a text file and then call Documents.Open on that text file
If (xhr.Status = 200) Then
hOutFile = FreeFile
Open "C:\foo.html" For Output As #hOutFile
Print #hOutFile, xhr.responseText
Close #hOutFile
End If
// ...
Documents.Open "C:\foo.html"
This has the disadvantage that some linked elements may be lost and you'll get a message box when the file opens
check the URL status with the XMLHTTP60 object and then use Documents.Open to open the URL as before:
If (xhr.Status = 200) Then
Documents.Open "http://foo.bar.com/index.html"
End If
There is a slight chance that the XMLHTTP60 request could succeed and the Documents.Open one fail (or vice versa). Hopefully this should be a fairly uncommon event though
I found most answers here and elsewhere confusing or incomplete, so here is how to do it for idiots like me:
'paste this code in at the top of your module (it will not work elsewhere)
Private Declare Function InternetGetConnectedState Lib "wininet.dll" (ByRef dwflags As Long, ByVal dwReserved As Long) As Long
Private Const INTERNET_CONNECTION_MODEM As Long = &H1
Private Const INTERNET_CONNECTION_LAN As Long = &H2
Private Const INTERNET_CONNECTION_PROXY As Long = &H4
Private Const INTERNET_CONNECTION_OFFLINE As Long = &H20
'paste this code in anywhere
Function IsInternetConnected() As Boolean
Dim L As Long
Dim R As Long
R = InternetGetConnectedState(L, 0&)
If R = 0 Then
IsInternetConnected = False
Else
If R <= 4 Then IsInternetConnected = True Else IsInternetConnected = False
End If
End Function
'your main function/calling function would look something like this
Private Sub btnInternetFunction_Click()
If IsInternetConnected() = True Then
MsgBox ("You are connected to the Internet")
'code to execute Internet-required function here
Else
MsgBox ("You are not connected to the Internet or there is an issue with your Internet connection.")
End If
End Sub
This is what I use. I prefer it because it doesn't require any external references or DLLs.
Public Function IsConnected()
Dim objFS As Object
Dim objShell As Object
Dim objTempFile As Object
Dim strLine As String
Dim strFileName As String
Dim strHostAddress As String
Dim strTempFolder As String
strTempFolder = "C:\PingTemp"
strHostAddress = "8.8.8.8"
IsConnected = True ' Assume success
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("Wscript.Shell")
If Dir(strTempFolder, vbDirectory) = "" Then
MkDir strTempFolder
End If
strFileName = strTempFolder & "\" & objFS.GetTempName
If Dir(strFileName) <> "" Then
objFS.DeleteFile (strFileName)
End If
objShell.Run "cmd /c ping " & strHostAddress & " -n 1 -w 1 > " & strFileName, 0, True
Set objTempFile = objFS.OpenTextFile(strFileName, 1)
Do While objTempFile.AtEndOfStream <> True
strLine = objTempFile.Readline
If InStr(1, UCase(strLine), "REQUEST TIMED OUT.") > 0 Or InStr(1, UCase(strLine), "COULD NOT FIND HOST") > 0 Then
IsConnected = False
End If
Loop
objTempFile.Close
objFS.DeleteFile (strFileName)
objFS.DeleteFolder (strTempFolder)
' Remove this after testing. Function will return True or False
MsgBox IsConnected
End Function
I encourted this same problem and after googling a lot, I realized there was a simpler way to do it... It requires the user to enable the Microsoft Internet Explorer Controlers library, but that is all. The idea is that your code navigates to a website (in this case google), and after getting the webpage document (HTML). puts a value in the search box.
Sub Test1()
On Error GoTo no_internet 'Error handler when no internet
Dim IE As New SHDocVw.InternetExplorer
IE.Visible = False 'Not to show the browser when it runs
IE.navigate "www.google.com" 'navigates to google
Do While IE.ReadyState <> READYSTATE_COMPLETE 'loops until it is ready
Loop
'Here It gets the element "q" from the form "f" of the HTML document of the webpage, which is the search box in google.com
'If there is connection, it will run, quit and then go to the msgbox.
'If there is no connection, there will be an error and it will go to the error handler "no_internet" that is declared on top of the code
IE.document.forms("f").elements("q").Value = "test"
IE.Quit
MsgBox "Internet Connection: YES"
Exit Sub
no_internet:
IE.Quit
MsgBox "Internet Connection: NO" ' and here it will know that there is no connection.
End Sub