PivotTable with dynamic Query to External Datasource - excel

My question is less specifically looking for ideas to a solution, and more for a sanity check of my own solution since it's been a while (at least two major revisions) since I've worked with ADODBs in Excel VBA.
So the situation is this. I'm creating an Excel report for a user who wants to access large chunks of a database view that is much too big to fit in memory. The user needs to be able to access ALL of the view, so hardcoded filters are out of the question. Unless I'm missing a more elegant solution, what they need is to be able to dynamically control the filters on the connection in the form of a generated SQL statement, which feeds into the pivotcache and then tells the pivottable to refresh.
I created a "refresh" button which brings up a Form that has all the filters the user commonly needs. The user enters the filter values, I parse and validate them, form a proper SQL statement from the values. Then I run into a problem when I do this:
'this has to be dynamic becuase I'm distributing to multiple users, using different testing/production databases on different workstations.
mypivottable.PivotCache.Connection = "ODBC;" & driver & myserver & myuser & trusted & app & workstationid & databse
'this also has to be dynamic becuase of the sql filters
mypivottable.PivotCache.CommandText = sql
So I push the button and it works! after setting these properties the pivottable automatically refreshes because it knows there's new data behind the cache, and fetches the query results under the new criteria.
The problem is that when I look in the external datasource listing, every time I change these properties it creates a new connection and doesn't clean up after itself. After 100 uses, there are 100 connections laying around, 99 of them unused. If I delete ALL the connections, then it irreversibly breaks the pivottable.
Is there a better way to do this? Is there a programmatic way to clean up only unused connections?

You don't have to reset the connection if all you need to do is update the SQL statement. I actually had a similar issue to this and this is how I resolved it:
Sub test()
' add logic...
' then change sql code
With ThisWorkbook.Connections("your connection name").OLEDBConnection
.CommandText = Array("select * from mytable where id = 1") ' adjust accordingly
.Refresh
End With
End Sub
All you really need to do is grab the current connection then update the CommandText property. By the way, I'm not sure why I needed to use Array() but I had issues without it.
I actually wrote a blog post about using SQL to create a pivot table (link here). Maybe I should make another one about creating dynamic content :)

Related

Database last read/access?

I was asked to get 'last read/access' of databases from Domino server.
The option - 'Maintain LastAccess Property' is disabled in almost all databases.
The business case is next. My customer would like to get overview what databases are used and when they were used last time.
What are other ways to get this info? Thanks.
This information can be read from log.nsf in the view Usage\by database.
You can also get some information from catalog.nsf: You need to create an own view to show all databases, as the default views are filtered, just remove & !(DBListInCatalog = "0") from selection formula.
If you need more detailled data, then you have to activate "Activity Logging" on the server. Just read about that in Administration help or follow this link

How to implement user-level security in Access 2007

So after some digging I realize that there is no built in user level security option for Access 2007. What I need to do is restrict records that users can edit based on who is logged in (they can see all the data but only edit their own). I was thinking that I could make a log in form and assign passwords and go from there, but I was wondering if there was a better method to do this.
For user privileges for read-only, read-write on forms in the database, we implemented following tables, logic.
I created a privilege table along with log-in table. Each screen in the database will have Read-only or Read-write privilege to each user. I inserted all the screen names into privilege table. Another table UserPrivilege will have users and their privileges. Assigning privilege to an user will be done only by Admin user.
A function at start of each form check swhether a specified user is allowed to view or edit form. If he/she is given read-only, we will lock all controls looping thr' controls on the form. Else, nothing to do. OR keep all the controls read-only at design them and unlock them thr' code for write privilege.
The database window is kept hidden when a version to end user is delivered. This prevents usual , simple view to tables in the database, opening forms , reports object in database window. After making mde/accde few more tweaks can be done so that user is not easily able to view tables directly. by-passing startup, special keys etc.
I have been facing this problem too. My solution (which hasn't been broken yet) is to do exactly that. Make a user's table with passwords and a log in form which reads the table for User name, password and user type. I have used two ways to proceed from there: Case statement to open specific navigation forms for that user's functions or a global variable (in a module (enumeration helps)) and an getter function that is checked within each form's open events and changes properties like AllowEdits, and AllowAdditions and even cancel the form opening if it's administrative stuff.
The most important part of this set up is making sure the users are using Access Runtime. If they use the Access version you are developing in they can snoop a little bit and get around this.
Make sure you hide the user's table.
Access runtime can be forced by making a shortcut to the DB and adding /runtime to the end of the shortcut path (with a space).
It's not perfect, but it works for my purposes and It might work for your's.
I did dot this in 2010, but 2007 should be pretty much the same.
Assigning username/passwords in Access (especially with an access back end) has a number of critical issues that are worth pointing out. Firstly, if you don't encrypt your DB, then any of your users who are savvy enough to go looking for it will be able to find it, and therefore get full access to it. If you encrypt the DB, if anyone can get access to your source code you're toast, since they will be able to see the DB user/passwords stored in the code. This issue persists if you use other SQL db's, but at least in those cases you can restrict the user supplied to the Access .accdb file to have certain permissions.
For my case, I have 3 levels of security. Firstly, I heavily restrict what I send out to make it very difficult to access the source code, which you kind of have to do no matter what. Secondly, I distribute different levels of access with different DB passwords (I'm using a MySQL back-end, you could do the same with a SQLServer back-end, but with Jet you're out of luck), so even if users could see the DB user and password, they are limited in what they can do. Thirdly, since I deploy on a corporate network, I take advantage of windows groups, and use those to filter out what is visible to different users. That way, users can only use the forms if they are authenticated onto our network. If the file discovers it's not on the network, it deletes itself and terminates.
Function IsMember(strDomain As String, strGroup _
As String, strMember As String) As Boolean
Dim grp As Object
Dim strpath As String
strpath = "WinNT://" & strDomain & "/"
Set grp = GetObject(strpath & strGroup & ",group")
IsMember = grp.IsMember(strpath & strMember)
End Function
Function GetCurrentUser() As String
GetCurrentUser = VBA.Environ$("USERNAME")
End Function
Function GetCurrentDomain() As String
GetCurrentDomain = VBA.Environ$("USERDOMAIN")
End Function

Lotus notes - error accessing shared private on first use view from LotusScript

Good morning,
I have develop a note application which is used to make a booking. This application is used by multiple user at the same time.
I am quiet new to this development and now I would like to develop a functionality so that user can print a export data to excel.
I have created a view (Shared) where its Selection Formula is base on critical each user specify in a search form. I have problem when a user is being printing and yet finished, the other users is also clicking printing same time, the result of export data on the sides are the same to the one who created first.
I was thought may be using the kind of (Shared, Private on first Use View) but it generated an error [Notes error: Index is not to be generated on server ("view name") ] at the points where I called
view.Clear
view.SelectionFormula = formula
uiw.ViewRebuild
I have no idea how to solve this problem. Could you please advice how this problem could be solved?
Thanks your in advance for your great help.
Best regards,
Veasna
There are different ways to do this. One possibility is to use a "shared, private on first use" (spofu) view: then every user gets his own copy of the view, and they don't impact each other. But I think it is not a good idea to do it like that, as every user needs designer rights to change the selection formula of the view. This is something you do not want.
A better way would be to use a spofu folder for each user and put the documents in it like this:
Dim ses as New NotesSession
Dim db as NotesDatabase
Dim dc as NotesDocumentCollection
Dim folder As NotesView
Dim formula as String
Set db = ses.currentDatabase
Set folder = db.GetView("NameOfTheSpofuFolder" )
'Make it empty
Call folder.AllEntries.RemoveFromFolder("NameOfTheSpofuFolder")
'Search documents based on the formula
Formula = "Field1 = 2 & Field2 = 5"
Set dc = db.Search( formula, Nothing, 0)
Call dc.PutInFolder("NameOfTheSpofuFolder")
Spofu folders need a little "care" but usually they work quite nicely.
This code is not tested and just written down without syntax check etc. It might contain typos, but should give you an idea how to start.
You could create a Lotusscript agent to export the data the users specify.
Get the search criteria from the form, then use db.Search or (preferably) db.FTSearch to get the documents to export.
Now you can export the data of those documents to Excel, using one of the techniques described here:
http://blog.texasswede.com/export-from-notes-to-excel-3-different-ways/
If you want to export as CSV, you can use this code as a start: http://blog.texasswede.com/export-notes-view-to-excel-with-multi-value-fields/
According to this thread on the Notes 6/7 forum, there may be a workaround for this problem. You haven't shown enough code to know for sure. If you are using getView() to access the Shared - Private On First Use (SPOFU) view, that doesn't work. The workaround is to loop through the db.Views() array, checking both the Name and Readers properties in order to make sure that you get a handle on the private instance of the view instead of the shared instance.

Automatically copy data from SP2010 external list to an SP2010 custom list

I have an SP 2010 external list that is populated with customer names. The list is updated occasionally throughout the day. I would like to automatically copy the newly added names to another SP 2010 list when it is updated or at a set time (hourly).
Is there an easy way to do this? And if not, is there at least a way to do it?
Thank you for your help.
Unfortunately, External Lists do not support workflows. So workflow is not a solution here.
One of the way to do this would be to create a custom timer job to synchronize items & configure to run it periodically. See details about how to create & register custom job here.
But this approach has it's own drawbacks:
it is complex enough
you will need a farm scoped feature +
receiver to register the job. The
reason is that for security purposes
you can't register a custom job from
within the code running in Content
Web application (so it will not work
in site collection level feature
receiver), only from code running in
Central Admin app.
I'd build a windows service or a timed job in SharePoint and then hook up a compatible ado.net connector to my process. This way you can copy or synchronize data between your two lists as if they where ordinary SQL tables.
private void example()
{
// Fetch data from your left sharepoint
SharePointConnection leftConnection = new SharePointConnection(#"
Server=mysharepointserver.com;
Database=mysite/subsite
User=spuser;
Password=******;
Authentication=Ntlm;
TimeOut=10;
StrictMode=True;
RecursiveMode=RecursiveAll;
DefaultLimit=1000;
CacheTimeout=5");
leftConnection.Open();
string leftQuery = "SELECT * FROM LeftList";
SharePointDataAdapter adapter = new SharePointDataAdapter(leftQuery, leftConnection);
DataTable dt = new DataTable();
adapter.Fill(dt);
// Insert data in right sharepoint
SharePointConnection rightConnection = new SharePointConnection(#"
Server=anothersharepointserver.com;
Database=whateversite
User=spuser;
Password=******;
Authentication=Ntlm;
TimeOut=10;
StrictMode=True;
RecursiveMode=RecursiveAll;
DefaultLimit=1000;
CacheTimeout=5");
rightConnection.Open();
// build your rightQuery here
string rightQuery = "Insert into"...
SharePointCommand command = new SharePointCommand(rightQuery, rightConnection);
command.ExecuteNonQuery();
}
You could try this one http://www.bendsoft.com/net-sharepoint-connector/. This ado.net connector uses the API of SharePoint so you can run the service in a third machine and as long as it has access you'll be fine.
There are some examples and howto's at http://blog.bendsoft.com
A workflow can be created for this easily. The workflow can be triggered when an item is newly created or updated. The workflow can create the same item into another list.
Try creating the workflow using SharePoint designer, which is quiet straight forward.
Hope this helps. :)
Why do you want to copy the external data to another list? What is the purpose of doing this? Perhaps there is a better solution for what you are trying to do.
The reason I say this, is because you are going to be replicating data and could get a bit tricky, especially if you allow the data to be updated in both places.
I'd use MS access in order to copy data out of one table, and push it into another table. I've used Access/Sharepoint extensively, and it's a little bit buggy.. but it generally works. It might crash- but for 90% of small tables, heck yes you can do this!

How can I export a list of databases resident on a given Domino server?

I have a Lotus Domino server with a truly astounding number of Domino databases on it, arranged in various folders.
Is there some means of exporting a list of all these databases, with their titles and creators' names, in a spreadsheet format of some kind? I have the Domino Admin and Domino Designer software, and I have or can get whatever access rights I'd need.
Actually, you can use a very simple Lotuscript agent to connect to a server and walk through all databases on the server, using the NotesDbDirectory class. Here is some code, modified slightly from what's in the 6.5 Help files - this dumps the title and path of all databases to a csv file. Note: the one argument to the GetFirstDatabase method let's you specify which objects on the server you want to scan - 1247 is the constant for "Databases" - basically, all NSF files. There are other constants for finding templates only (NTF's), only database with replication enabled, etc.
Sub Initialize
Dim db As NotesDatabase
Dim f As Integer
f = Freefile
Open "c:\dbExport.csv" For Output As #f
Dim dbdir As New NotesDbDirectory("") ' opens LOCAL - put a server name here
Set db = dbdir.GetFirstDatabase(1247) ' all databases - NSF, NSG and NSH (no templates)
While Not(db Is Nothing)
Print #f, """" + db.Title + """, """ + db.FileName + """"
Set db = dbdir.GetNextDatabase
Wend
Close #f
End Sub
You'd think there'd be a way in the Domino Admin, but there's no way to export the list. So, your best bet I think is to use the Domain Catalog database. To build it, go into the server configuration doc > Server Tasks > and turn on the Domain Catalog. Then the catalog.nsf database will be built and will contain all the databases in your domain. You can customize the views to include the information you need.
Then finally, you can go into a view, select all the documents and click Edit > Copy Selected As Table. Then paste that into a spreadsheet.
It is a little known fact that you can "select all" in the Admin client and paste into Excel. There is also an option for a flat view of databases instead of a folder view.
The creator of the database is not listed but there is a lot of other useful information
Inherited some legacy server, didn't we ?
If the server was sensibly maintained in the past, you already have the following things :
a catalog.nsf database, which is exactly what you want, only better
the catalog server task up and running.
The catalog task is the task that automatically builds and maintain the catalog.nsf database. If it is not already running, you can launch it once at teh server console in Domino admin :
load catalog
and even better, add it to the server tasks in the server's notes.ini
Now, the catalog tasks only cover the databases whose properties have been set such as to allow cataloging. A well behaved Domino admin would not allow a database to reach production without those properties properly set (and I believe it is the default anyway) but it seems you are not exactly in a nominal situation.
If this is not enough and if you have time to tinker around, I was in a similar situation once, and I built a database with some rather advanced scripts to conduct a thourough census, including agents and their schedules etc. If you want, I'd be happy to pass it to you.
Have fun with your new toy !

Resources