Get Sharepoint store URL in Outlook? - sharepoint

I'm trying to write an Outlook 2007 VSTO add-in that lets you do some stuff with Sharepoint webservices. I'd really like to make it as simple as possible for the users; ideally, all that they would have to do is connect a Sharepoint list to Outlook. From there, my add-in would ideally grab the actual Sharepoint URL from the list and do its thing. Unfortunately, I can't seem to find where Outlook stores this information while running.
The best solution I've been able to find is to read in the files found in C:\Documents and Settings(username)\Local Settings\Application Data\Microsoft\Outlook*.sharing.xml.obi.
However, these files are only updated when you close Outlook. That means that the user would have to connect to the list, restart Outlook, and then things would work. I'd rather not have things get to that level.
It's almost like the information just magics its way into the sharing.xml.obi files. I've Googled, I've used OutlookSpy and in desperation I've used mfcmapi.exe, all to no avail. Where the heck does Outlook store this?

You can use the object model (or direct MAPI calls) to query this information from the outlook folder. First use the .isSharePointFolder property to locate your folder. The URL of the SharePoint List in outlook is then stored as the subject of a "hidden" message in the associated contents table.
Bonus tip: If you are not using it already, get yourself a copy of the excellent OutlookSpy. It makes figuring this kind of stuff out so much easier.

With Paul-Jan's pointer, I've figured this out. Since I hate it when I only find indirect hints while googling, here's exactly the code you need:
private string getSharepointURL(Microsoft.Office.Interop.Outlook.Folder SharepointFolder)
{
if (!SharepointFolder.IsSharePointFolder)
throw new Exception("Cannot get the SharePoint URL of " + SharepointFolder.FullFolderPath + ", because it is not a SharePoint folder.");
return (string)((object[])SharepointFolder.GetTable("", 1).FindRow("[From] = SharePoint").GetValues())[1];
}
That may be the ugliest return statement I've ever written. Here's what it does:
Calls Outlook.Folder.GetTable("",1). The first argument is a filter, which means "anything", and the second argument is equivalent to olHiddenItems. (I couldn't find the actual enumeration)
Gets the next row of that table whose sender (the [From] field) is "SharePoint". The information we want is always held in this hidden message.
Gets the values of that hidden message. This comes back as an object, but is secretly an object[].
Casts the values to an object[].
Gets the second item of the values, which is the url.
Casts the url to a string.
Fortunately, you can do all these steps yourself in OutlookSpy. That was a real help in figuring out how to get at this precious nugget of information.

Well, here is what I use... (C#3/VS2008, Outlook2007)
Outlook.Folder folder = GetSomeSpFolder(); // requirement :)
// Things to look for here, not in the columns by default
// the values can be found in OutlookSpy or perhaps MSDN (haha)
// this value refers to the SP site (not the full URL)
var SHARING_REMOTE_STORE_UID = "http://schemas.microsoft.com/mapi/id/{00062040-0000-0000-C000-000000000046}/8A48001E";
var table = folder.GetTable("[From] = SharePoint", Outlook.OlTableContents.olHiddenItems);
// setup columns to look through
table.Columns.RemoveAll();
table.Columns.Add(SHARING_REMOTE_STORE_UID);
if (!table.EndOfTable) {
var row = table.GetNextRow();
var siteURL = row[SHARING_REMOTE_STORE_UID];
Marshal.ReleaseComObject(row);
} else {
// No matching entry ...
}
Marshal.ReleaseComObject(table);
Also check out http://msdn.microsoft.com/en-us/library/bb176406.aspx
Happy coding!

Related

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.

Is it possible to compare the same Sharepoint list twice a day looking for changes/count of changes

I'm new to SharePoint and have a general question regarding list comparison. Currently, there is a user generated list that is constantly changing, and I wanted to gather quantitative data regarding the changes. Each day, I come in at 8:00 and then leave again at 5:00. I want to know what/how many items are in that list at 8:00 vs. 5:00 and then be able to review the results. For example, the list contains current projects that I need to finish. If there are 20 when I come in at 8:00, and 3 when I leave, I want to be able to view data that I completed 85% of the projects and 17/20.
Is this possible?
*Note, currently, I do not have SharePoint Designer or access to the server. Assuming access is needed and I can get it, what would be the best way to approach this?
There's really no built-in way to do this. But with all things SharePoint, there are multiple ways to accomplish things. Since you don't have access to SP Designer, or the server itself, probably the path of least resistance would be to use the SP Web Services to query the list (say, at 8AM) and get a count of items, store (persist) the item-count somewhere, then query the list again (5PM), and check it against the initial day's count, and give you a total.
You can access List data via the SP Web Services at http://server_name/_vti_bin/Lists.asmx. Use something like the code below to get the list count. You can persist the stored value anywhere - text file, local storage, memory..
Note, you need to add a Web Service reference to your project. In the code below, this is named sp2010, but obviously you can name your whatever you want. The variable listItemCount will hold your list count. Much of the rest of the code should be self-explanatory.
sp2010.Lists spList = new sp2010.Lists() { Credentials = new NetworkCredential("username", "password") };
string listName = "YourListName";
string listItemCount = string.Empty;
XmlNode listXML = spList.GetListItems(listName, null, null, null, null, null, null);
XmlDataDocument innerXml = new XmlDataDocument();
innerXml.LoadXml(listXML.InnerXml);
XmlNodeList rows = innerXml.GetElementsByTagName("rs:data");
foreach (XmlNode attribute in rows)
{
// listItemCount holds the count of your list
listItemCount = attribute.Attributes["ItemCount"].Value;
}
Timerjob might be a decent option. It's a little bit of coding that would just hit the list query all items and count and then ping an E-Mail to someone or drop the figure it returns somewhere in SharePoint.
In addition i would have a read around http://www.andrewconnell.com/blog/articles/CreatingCustomSharePointTimerJobs.aspx
blog for information as to how to code a timer job.
To actually get what you are needing I will talk you through what you need to do but won't give you the code as you should really attempt first before asking.
Get a spsite object.(This should contain the web containing your list)
Get the web object containing your list.
Get the list
SPList countLIst = <yourWeb>.lists["<listname or GUID>"]
Get the list count
int numberOfItems = countList.items.count
somehow display or save numberOfItems
Remember SPContext.current.site will not work within timer jobs due to their context.
Hope this extension fulfills your request
Cheers
Truez

Sharepoint 2007 Webpart variables problem on reload

I'm having trouble with the webparts variables... I came from standard ASP language, so, to me, store variables in session and other parts is the common way to do everything =)
Now i had to create a webpart, the wp has to write a graph from parameter and i cannot understand HOW variables works: i cannot understand WHEN saved and WHEN erased and other thing like this!
Let me explain: i have a web part with the configuration toolbar on the right in which i put the values.. Everytime a button is pressed or a value in the dropdown list changes, it raises an event which causes the "CreateChild" function..
Many times the data is "stored", other time they are not!
That's the way i used to store value (in the ApplyChanges override function):
WPChartGenerator wpParent = (WPChartGenerator)this.ParentToolPane.SelectedWebPart;
wpParent.WebUrl = txtWebUrl.Text.Trim();
And in the CreateChild event i get the value like:
WPChartGenerator wpParent = (WPChartGenerator)this.ParentToolPane.SelectedWebPart;
this.ddlWeb = new DropDownList();
this.ddlWeb.ID = "ddlweb" + wpParent.ID;
ddlWeb.SelectedValue = wpParent.WebService;
Now.. Sometimes this works, for example, when i push a button I invoke in the code of the button and then the code to store every value.. In some case (like buttons) this works, in other (like dropdown list index changed event) this fails and i found every object in the wpParent equal to it's initial value.
Another thing i noticed, is that in certain cases when an event is triggered, the first thing to be executed (even first than the event's associated code) il CreateChild (even first than OnLoad!!!)
Can anybody tell me what I'm doing in the wrong way? Do anybody has a good tutoria for this matter?
Thanks & sorry 4 my School level English =)
Forget to say that every variable has been implemented as a Property, like that:
[WebBrowsable(false)]
[Personalizable(PersonalizationScope.Shared)]
[WebPartStorage(Storage.Shared)]
public string WebUrl
{
get
{
return this.webUrl;
}
set
{
this.webUrl = value;
}
}
I can't see all the code there so I don't really know what you're doing wrong (i.e. do you actually have an ApplyChanges method) but from the way you've worded your question it sounds like you really need to start at the beginning, follow one of these walkthrough tutorials and make sure you understand the basics and then start adding in the code for your project.
MSDN - Creating Web Parts for SharePoint (VS2010)
MSDN - Walkthrough: Creating a Basic SharePoint Web Part (WSS 3.0)
Developing SharePoint 2007 Web Parts

In Sharepoint, how do I update a task directly from a link in an email?

I'm just starting to use sharepoint designer and realised there's a lot that can be done to extend the basic features in sharepoint. We have an email alert sent out when a new task is created (by the user) and I want to customise the email so that it also includes a link called 'Assign'. When clicked, I want this link to automatically update the task with the assigned to field for the person that clicked it.
So I think the way to do this would be to hard-code the assign to value in the url behind this link, but I have no idea if this is possible or if there is an easier/better way to do this.
Any advice would be appreciated as I'm a complete beginner.
thanks.
I will not cover "How to modify the contents of an eamil alert" here as that is a seperate question and there are a lot of articles that cover that already.
For the Assigned link :-
You would need to create a custom page (or web part on an existing page) as the destination of your Assign link - this would take the Task ID as a query string param and then update the assigned to with the current user.
You could make this flexible by also taking the ListID but you may want to think about how this could be abused and put appropriate measures in place.
EDIT - in response to comment.
This is top of my head, not checked in compiler. This would have to sit on the same server as SharePoint to work as its using the OM - if you want to use a different server (why would you though) then look in the web services.
private void updateAssignedTo(Guid listId, int itemID)
{
SPWeb web = SPContent.Current.Web();
SPList list = web.Lists[listId];
SPListItem item = list.GetItemById(itemID);
item["Assigned To"] = web.CurrentUser;
item.Update();
}
You're going to have to work out how to get this code into to page or web part (SharePoint Designer is not going to cut it I think, you need Visual Studio) but its a starting point.

Passing form data to another form via url in lotus

I am working on a new web app in lotus/domino. I am newer to lotus/domino programming, so forgive me for not knowing something simple.
What I am trying to do is display a table of information, with one of the columns containing a link. The link is formatted like [http://server/app.nsf/form?openform&ideaNum=1&var2=foo2]
How can I retrieve the information from the url, to get information from a view or a document?
So far I have tried to access the query string in the webQueryOpen event, but lotus runs the agent before the DOM writes to the browser, the query_string isn't available.
I am not sure how else to get information from one form to another in lotus.
Thanks for the help.
-Kris
If you're passing multiple params in the query_string, you can get Domino to do a bit more of the work for you. There's an Function command - UrlQueryString - that can format the params into a list, delimiting at the "&".
E.g. server/app.nsf/form?openform&ideaNum=1&var2=foo2
becomes a list:
openform
ideaNum=1
var2=foo2
To use it, on the destination form create a multi-value text field called something like "QryStringList".
Set it to be computed when composed, and set it's value to #UrlQueryString.
In your WebQueryOpen agent, you can access the params as doc.QryStringList(0), docQryStringList(1) and so on, if you're using Lotusscript.
I'm fairly sure I put this together using info from the IBM/ldd forum, but the exact source is lost in the mists of time and memory, so apologies if I've copied someone's post.
Just as a follow up, I found that you are able to specify an on form variable named the same as QUERY_STRING. The variable is actually a reserved term for Lotus, so Lotus pre-fetches the variable before running the information out the browser.
Due to the pre-fetching, you are able to access the url information during the webQueryOpen event.
I hope this helps someone else looking for the same type of functionality.
-Kris

Resources