I writing a macro for ms word, that starts when the document is loaded and fills a few fields with user information (tel,email etc.). I want this information to come form our domino-servers, as they are our primary database.
I have tried using notes objects in vba to establish a session on the server, but that requires that user to keep their notes-client open(as far as I know), so thats not an option.
Currently I am trying to get the information via ldap request(the domino-server runs the ldap-service), however I cant find information on how the code and search string has to look like.
The last site I tried was this one (http://www.selfadsi.org/bind.htm), using the "Bind using special credentials" variant.
But I am getting a protocol error.(the string proably needs to be adjusted for connecting to domino, I tried "LDAP://[Server-FQN]/dc=DE" hoping it would show me all users registered as C=DE, but it did not work.)
I have also searched through IBMs Support Site and Knowledge-Center, but could not find the info I need.
If anyone could provide me an example on how to connect to the domino ldap and pull the information for a user, I would be very grateful.
There are two different sets of Notes objects available to you in VBA. There are OLE objects, which you access this way:
Set Session = CreateObject("Notes.NotesSession")
And there are COM objects, which you access this way:
Set Session = CreateObject("Lotus.NotesSession")
The key differences between them are that OLE objects require that the Notes client must be running and they also include the "front-end" classes like Notes.NotesUIWorkspace that can actually drive the Notes client, while the COM objects do not require that the Notes client is running (though either it, or the Domino server, must be installed) and it does not provide the front-end classes.
If you want to stick with the LDAP approach, the first thing you should probably do is download an LDAP client. I like the SoftTerra LDAP browser, but I've also heard that a lot of people like the Apache Directory Studio. Browsing the tree is really the best way to figure out what queries will get you the info you need.
s mentioned in the commment on Richards answer, I also tried finding the LDAP-String using a LDAP-Browser. Doing that and some testing with ADODB Objects I was able to come up with the following code:
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand = CreateObject("ADODB.Command")
Set objCommand.ActiveConnection = objConnection
objCommand.CommandText = "SELECT UID, mail FROM 'LDAP://[Server-FQN]:389 'WHERE ObjectClass='dominoPerson'"
Set objRecordSet = objCommand.Execute
While Not objRecordSet.EOF
varMail = objRecordSet.Fields("mail").Value
Debug.Print varMail(0)
objRecordSet.MoveNext
Wend
Which extracts the email-adress of all our users using anonymous access and prints the result into the debug window.
Now all I have to do is to adjust the WHERE-Statement to get the data I want per user. :-)
Related
I have 5 different MS Access 2013 db files which connect to system dsn files(Linked Server)
The machine/system dsn's are Oracle based but the issue I am running into is 1 my password isn't encryped and has to be changed every 90 days and
2 I have to open each file and save my password multiple times when its changed.
I want to have a secure location which has the credentials stored and pass this into access so that they are not visible to other users and
not having to save my password on each access file and relink it.
I have googled for over 2 days but can't find anything other than looking at connection strings which still doesn't solve the problem. What do I need to look at to solve this?
Sorry I dont have code as I just use the linked tables wizard inside of ms access.
#Albert D I couldn't get your code to work but I have done the following which fixes the issue on the tables but not the Pass Through queries
Created a File DSN and linked some tables to the access database.
Created an Excel File to store my UserName And Passwords but my credentials in the pass-through query still show which I am stuck on?
Option Compare Database
Function Connections()
On Error Resume Next
'delete query if exists
DoCmd.DeleteObject acQuery, "PTQ"
Err.Clear
On Error GoTo 0 '"on error" statement here
'GET EXCEL LOGIN DETAILS
Set xlsApp = CreateObject("Excel.Application")
Dim WkBk As Excel.WorkBook
Set WkBk = xlsApp.WorkBooks.Open(FileName:="C:\folderlocation\filename.xlsx")
Dim USERLIST As String
Dim PWDLIST As String
USERLIST = WkBk.Sheets(1).Range("A2").Value
PWDLIST = WkBk.Sheets(1).Range("B2").Value
If Not (xlsApp Is Nothing) Then xlsApp.Quit
'end excel stuff
Dim db As DAO.Database
Dim qdExtData As QueryDef
Dim strSQL As String
Set db = CurrentDb
'passthrough query statement
strSQL = "SELECT * FROM table"
Set qdExtData = db.CreateQueryDef("PTQ")
ServerName = "Server1"
qdExtData.Connect = "ODBC;DRIVER={Oracle in OraClient11g_home1};Server=" & ServerName & ";DBQ=Server1;UID=" & USERLIST & ";Pwd=" & PWDLIST & ""
qdExtData.SQL = strSQL
qdExtData.Close
db.Close
Set db = Nothing
End Function
I then Set up a runcode macro called AutoExec
Ok, first up?
I would avoid (not use) a system, or a user DSN. The reasons are MANY, but these types of DSN's require not only a external reference, but also often require elevated registry rights. And worse yet, your password will be in plain view.
The best solution is to use what is called a DSN-less connection. And you can create these connections even without code!
And even better? If the server + database name is NOT changed, but ONLY the password? You can change the userID + password WITHOUT having to re-link the tables (ideal for you with a changing password, but NOT the server + database being changed).
Even better better? If you adopt a wee bit of "log on" code, then you don't have to store the password in the table links! What this means if someone decides to fire up access, and say import your linked tables? Well, for one, they will not be able to open the tables, and EVEN better yet the uid/password is NOT part of, nor is it stored in the connection string for each linked table. As noted, because of this, you can change the UID, and not have to re-link the tables.
The first step:
First up, ALWAYS (but ALWAYS!) when you link the tables, use a FILE dsn. this is imporant since when using a FILE dsn in access, they are automatic converted to DSN-less connections for you.
In other words, if you link your tables with a FILE dsn, then once the tables are re-linked, then you can even delete or toss out the DSN. And this means you can deploy the linked database (front end) to any workstation. You will not have to setup a DSN on that workstation, and in fact don't have to setup anything at all. (you will as before of course require the oracle database driver).
What the above means is when a password is updated/changed, you could then simply roll out a new front end. In fact, you likely have some auto updating ability for your application. (and if you don't', then you could (should) cobble together a bit of code to do this for you). So, you should have some means to roll out a new version of your software. After all, you REALLY have to install your "application" on each workstation LIKE you do with all other software, right???
So, there are two parts here:
Adopting a FILE dsn for the table links. As noted, once you do this, then you don't need the DSN anymore. This is great for distribution to each workstation.
Also MAKE SURE when you do link, you do NOT check the box to save the password. This is to ensure that uid/password is NOT saved in the connection strings.
So, if tables don't have uid/password, then how will they work?
Well, what you do is execute a "logon" to the database in your startup code. Once you execute this logon, then all linked tables will work! It is this "small" bit of code that can read the uid/password you place in an external file. Where you place this uid/password is up to you. It could be embedder in the code, or even some external text file that you read on startup. And it could even be a local table in the front end. (this idea would work well if you have some kind of automatic update system for when you roll out the next great version of your software.
So, with the ability to execute a logon, and not having to re-link the tables, then we have a EASY means to change the password.
So, you have to:
go dsn-less. Thankfully, access does this by default, but ONLY if you use a FILE dsn.
Get/grab the code to execute a logon to the database. In fact, you likly have to delete all your table links. Exit Access, then re-start Access. Now, run your logon code, and THEN re-link your tables (using a FILE dsn you make).
The code to execute a logon is this:
Function TestLogin(strCon As String) As Boolean
On Error GoTo TestError
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb()
Set qdf = dbs.CreateQueryDef("")
qdf.connect = strCon
qdf.ReturnsRecords = False
'Any VALID SQL statement that runs on server will work below.
qdf.sql = "SELECT 1 "
qdf.Execute
TestLogin = True
Exit Function
TestError:
TestLogin = False
Exit Function
End Function
The above of course requires a correctly formed conneciton string.
So, to make ALL of this work, you can adopt the FILE dsn, and use above. You will likly cobbile together some code to build you a connection string. Then add to your code some code to read an external ext file, or have the UID/password in some table. This logon code as per above has to run BEFORE any form or linked table is used or touched.
The whole process is simple, but only if you break down this into the correct steps.
How this logon trick, and example code works is not complex, but a full article explaining this approach is outlined here
Power Tip: Improve the security of database connections
https://www.microsoft.com/en-us/microsoft-365/blog/2011/04/08/power-tip-improve-the-security-of-database-connections/
Back Story
I am working with SAGE Mas 200 software, trying to link to it through Access. This software houses date for 300 investors for my company. With EACH investor I have a different investor ID that goes along with my UID and Password upon logging in, therefore EVERY connection string is different.
After many hours of trial and error, I have been successful in connecting via Access to only find out that I can only have one active connection string per database. Since I have 300 investors that I need to pull data from, there is the problem...and I can't figure it out.
I am a newby with VBA so my knowledge is extremely limited. I have read about linking to a 'template' file with the connection strings, but not sure how to format the template file. Can someone show me an example? Also, how would I get it to loop thru each query stored in the database and then pull the appropriate connection string?
Examples
Here is an example of my connection string where 'AAL' is the investor code:
ODBC;DSN=SOTAMAS90;UID=tbard|AAL;PWD=password;Directory=\\mas-200\MAS90;Prefix=\\mas-200\MAS90\SY\, \\mas-200\MAS90\==\;ViewDLL=\\mas-200\MAS90\HOME;SERVER=NotTheServer
The query name for this would be MAS_AAL.
Another investor: SMP, the query name MAS_SMP. Etc, etc, etc...
Can someone be my light at the end of the tunnel and help me out so I don't have to manually run 300 queries. I'm dying over here!!
You can programmatically set the connection string.
There is a MAS 90 / MAS 200 ODBC driver called SOTAMAS90. On MAS installations in the last 5 years, there is both a 32 and a 64 bit driver.
In VBA, if I remember correctly, you would do something like this. (This assumes you already have fetched the Investor object you need, and it has properties called username and password):
Dim conn as new ADODB.Connection()
' Set properties of connection string manually
conn.ConnectionString = "DRIVER = SOTAMAS90; UID=" & myInvestor.username & "; PWD=" & myInvestor.password & "; Company=ABC"
conn.Open()
Another approach is to use a single ODBC connection within Access, to set up a linked ODBC table, using Access' Get External Data feature. Then you can treat it like any other Access table, and just query it directly. The problem with this approach is that Access will keep prompting you for credentials, both when you first open the table, and then if you are inactive for a while. I'm told you can save the UID and password in the SOTAMAS90 ODBC connection, but I've never done it.
Hope that helps.
Aaron
So the previous developer added some application variables in Global.asa file but he hard coded those and we found a bug which need to be dynamic. Now is it possible(or correct way) to add a SQl query to fetch the data and setting the application variable in Global.asa file.
We have this in global.asa
Application("Email_Sales") = "SomeEmail_1#comcast.net"
Now we have new sales person and we give her admin rights in our portal and her email is
SomeEmail_2#comcast.net. Now i dont want to change the global.asa file every time a sales person change.and thats why i want to write a query in global.asa. For some process this sales person gets email and now its going to old email. Now i can write a query and fetch the new email where the email are going but that will be on so many places.
let me know if its good or not good to write a SQL query in global.asa file.
Thanks.
Actually I find it a good idea to host dynamic application wide variables in the global.asa file to keep the on site maintenance low. (But only if you need them at various occasions across the site, because otherwise you could call the information just in time with a little function.)
Depending on how often you change your values (lifecycle of app?) you could use something like this:
Sub Application_OnStart()
Set Conn = ...
Conn.Open ...
strSql = "SELECT SALESEMAIL ...."
Set objRs = ...
If NOT objRs.Eof Then
Application("SALESEMAIL") = objRs("SALESEMAIL")
End If
objRs.Close
Set objRs = Nothing
Conn.Close
Set Conn = Nothing
End Sub
Further information:
When to use Application_Start vs Init in Global.asax?
I'm interested in setting up an Access db to run a report automatically. To save myself the trouble of going to each client computer and setting up the appropriate DSNs, I'd like to set up the ODBC connections in the VB script itself if possible.
I've googled and checked this site and found some good starter code, but not enough to make all the error messages go away. Can someone complete the code below?
Sub SetupODBC(Str_Server as string, Str_Db as string)
'Str_Server=Name of Server
'Str_db=Name of Database
Dim C as ADODB.Connection
Set C = new ADODB.Connection
C.ConnectionString = ??
C.Open
Debug.print C.State
Exit Sub
Welcome to the board. ConnectionStrings is indeed your friend, but the issue you are having is that you don't have the driver:) Lotus Notes is not a relational database it is a document oriented database. Historically there has not been a way to Access it like it is a relational database for that reason. However IBM eventually got around to writing a sort of translator in the form of NotesSQL. If you follow the link and get the driver you should be able to use ODBC. It is worth noting that Notes exposes itself to COM. So if push comes to shove you can automate the client.
This site is your friend: http://www.connectionstrings.com/access
I didn't follow your question correctly at first. I see you want to create a link from Access to Lotus to report on Lotus Notes data. Well there are a few ways to do so.
I frequently use a method of exposing Lotus Notes data as XML, then accessing that XML from the remote system. You can easily create a Notes Page with the XML start tag, root element, and then insert an embedded view in between the root element. That embedded view then needs to display as HTML and contain columns that resolve to xml tags. For instance, each row of the view would look similar to this:
<Person><FirstName>Ken</FirstName><LastName>Pespisa</LastName></Person>
and your column formulas would be:
"<Person><FirstName>" + FirstName + "</FirstName>"
for the first name column, and for the last name column it would be this:
"<LastName> + LastName + </LastName></Person>"
Note that this assumes that your Notes server has the HTTP service turned on and you can reach the database via a browser.
However as mentioned by other answers, you can use other methods such as NotesSQL and COM. It sounds like you are putting this solution on many workstations, though, and NotesSQL would require you to install the driver on each workstation. The COM method would work without requiring any extra work at the users' desks so I'd favor that solution in this case.
Looks like a great site for my needs, even if it hasn't been updated in a year. But still no cigar. Now, I'm getting "Data source name not found and default driver not specified"
(Obviously, ServerNameGoesHere and DatabaseNameGoesHere are subsitutions)
Sub dbX()
Dim C As adodb.Connection
Set C = New adodb.Connection
C.Open _
"Driver={Lotus NotesSQL 3.01 (32-bit) ODBC DRIVER (*.nsf)};" & _
" Server=ServerNameGoesHere;" & _
" Database=DatabaseNameGoesHere.nsf;"
C.Close
End Sub
I have the following code:
Dim obj As New Access.Application
obj.OpenCurrentDatabase (CurrentProject.Path & "\Working.mdb")
obj.Run "Routine"
obj.CloseCurrentDatabase
Set obj = Nothing
The problem I'm experimenting is a pop-up that tells me Access can't set the focus on the other database. As you can see from the code, I want to run a Subroutine in another mdb. Any other way to achieve this will be appreciated.
I'm working with MS Access 2003.
This is an intermittent error. As this is production code that will be run only once a month, it's extremely difficult to reproduce, and I can't give you the exact text and number at this time. It is the second month this happened.
I suspect this may occur when someone is working with this or the other database.
The dataflow is to update all 'projects' once a month in one database and then make this information available in the other database.
Maybe, it's because of the first line in the 'Routines' code:
If vbNo = MsgBox("Do you want to update?", vbYesNo, "Update") Then
Exit Function
End If
I'll make another subroutine without the MsgBox.
I've been able to reproduce this behaviour. It happens when the focus has to shift to the called database, but the user sets the focus ([ALT]+[TAB]) on the first database. The 'solution' was to educate the user.
This is an intermittent error. As this is production code that will be run only once a month, it's extremely difficult to reproduce, and I can't give you the exact text and number at this time. It is the second month this happened.
I suspect this may occur when someone is working with this or the other database.
The dataflow is to update all 'projects' once a month in one database and then make this information available in the other database.
Maybe, it's because of the first line in the 'Routines' code:
If vbNo = MsgBox("Do you want to update?", vbYesNo, "Update") Then
Exit Function
End If
I'll make another subroutine without the MsgBox.
I've tried this in our development database and it works. This doesn't mean anything as the other code also workes fine in development.
I guess this error message is linked to the state of one of your databases. You are using here Jet connections and Access objects, and you might not be able, for multiple reasons (multi-user environment, unability to delete LDB Lock file, etc), to properly close your active database and open another one. So, according to me, the solution is to forget the Jet engine and to use another connexion to update the data in the "other" database.
When you say "The dataflow is to update all 'projects' once a month in one database and then make this information available in the other database", I assume that the role of your "Routine" is to update some data, either via SQL instructions or equivalent recordset updates.
Why don't you try to make the corresponding updates by opening a connexion to your other database and (1) send the corresponding SQL instructions or (2) opening recordset and making requested updates?
One idea would be for example:
Dim cn as ADODB.connexion,
qr as string,
rs as ADODB.recordset
'qr can be "Update Table_Blablabla Set ... Where ...
'rs can be "SELECT * From Table_Blablabla INNER JOIN Table_Blobloblo
set cn = New ADODB.connexion
cn.open
You can here send any SQL instruction (with command object and execute method)
or open and update any recordset linked to your other database, then
cn.close
This can also be done via an ODBC connexion (and DAO.recordsets), so you can choose your favorite objects.
If you would like another means of running the function, try the following:
Dim obj As New Access.Application
obj.OpenCurrentDatabase (CurrentProject.Path & "\Working.mdb")
obj.DoCmd.RunMacro "MyMacro"
obj.CloseCurrentDatabase
Set obj = Nothing
Where 'MyMacro' has an action of 'RunCode' with the Function name you would prefer to execute in Working.mdb
I've been able to reproduce the error in 'development'.
"This action cannot be completed because the other application is busy. Choose 'Switch To' to activate ...."
I really can't see the rest of the message, as it is blinking very fast. I guess this error is due to 'switching' between the two databases. I hope that, by educating the user, this will stop.
Philippe, your answer is, of course, correct. I'd have chosen that path if I hadn't developed the 'routine' beforehand.
"I've been able to reproduce this behaviour. It happens when the focus has to shift to the called database, but the user sets the focus ([ALT]+[TAB]) on the first database. The 'solution' was to educate the user." As it is impossible to prevent the user to switch application in Windows, I'd like to close the subject.