If you view a SharePoint calendar in MS Outlook and change the color of that item in Outlook, the SharePoint ows_MetaInfo gets changed from this:
2362;#
to This:
2362;#vti_encoding:SR|utf8-nl
FollowUp:SW|
vti_serverversion:SW|2
vti_versionhistory:SW|473e1c0c47cf034d9969c8513def1903:4
vti_clientversion:SW|4
BusyStatus:SW|2
Categories:SW|Red Category
Priority:SW|
IntendedBusyStatus:SW|
vti_externalversion:IW|3
I have a C# program that creates the SP calendar entry but I would like to be able to modify this ows_MetaInfo Categories property so that I can color code these items so that users that view this in Outlook will see these color codes.
I have searched on everything that I can thing of. I have seen people reading this ows_MetaInfo data but nothing that says how it can be changed. As stated earlier, I'm doing this in C# and I would like to change the ows_MetInfo Categories property so that Outlook users will see color coded calendar entries.
Any help would be Greatly Appreciated!
I've been searching around for quite some time to figure this out and I overlooked the most obvious answer... :) All I had to do was ask for help for me to finally figure it out! LOL :D
MetaInfo is just another String field. When you make a color change in Outlook to a SharePoint attached calendar item it, just adds text to that field that specifies the color along with some other default items. To change the color you can just specify it with something like cListItem["MetaInfo"] = "Categories:SW|Red Category\r\n"; and it will just change the Categories field leaving the others alone.
For completeness, I'm going to post my entire test example. (Because I hate it when I find the answer to a problem but only part of the answer is posted leaving me to guess at what else was in the code that made the example actually work :) )
This is done is VS2013 using a Console App
using Microsoft.SharePoint.Client;
using SP = Microsoft.SharePoint.Client;
using System.Net;
namespace SharePointSetMetaInfo
{
class Program
{
static void Main(string[] args)
{
using (ClientContext context = new ClientContext("https://mySharePointServer/sites/MySite/"))
{
context.Credentials = new NetworkCredential("myUserName", "myPassword", "MYDOMAIN");
SP.List calendarList = context.Web.Lists.GetByTitle("Calendar");
ListItem cListItem = calendarList.GetItemById(2301);//This is one way to retrieve an item for update. You can also use a Caml Query
context.Load(cListItem);
cListItem["MetaInfo"] = "Categories:SW|Red Category\r\n";
cListItem.Update();
context.ExecuteQuery();
}
}
}
}
Hopefully this helps someone else who is trying to programmatically change the colors on SharePoint calendar items as they show up in Outlook. This is not applicable to how SharePoint calendar items appear in SharePoint, only Outlook.
Related
I am trying to read the AppointmentItem.BusyStatus from a shared calendar with limited access. I can see the BusyStatus for the entire day/week, but do not have access to information like the subject or location of an appointment.
My code looks like the following:
At first, I get the folder in which the shared calendars are stored.
oApp = new Outlook.Application();
mapiNamespace = oApp.GetNamespace("MAPI");
Outlook.Recipient oRep = mapiNamespace.CreateRecipient(oApp.Session.CurrentUser.Name);
calendarsFolder = mapiNamespace.GetSharedDefaultFolder(oRep, Outlook.OlDefaultFolders.olFolderCalendar).Folders;
In the next step, I iterate over all the calendars and their appointment items.
foreach(Outlook.Folder calendar in calendarsFolder){
Console.WriteLine(calendar.Name);
foreach(Outlook.AppointmentItem item in calendar.Items){
Console.WriteLine(item.Start.ToString("dd.MM.yyyy"));
Console.WriteLine(item.BusyStatus);
}
}
This code works just fine on a calendar which grants me full control to read any details the appointment may have. It does not work on the calendar with limited access though. After debugging my code, I found out that the calendar.Items list of this particular calendar is empty, its count is 0. I am assuming this has to do with me not having the proper authorization to retrieve this information, since I could read the subject and location if I got the appointment items. This is just an assumption however, and I am honestly not quite sure what is going on. Do I need an entirely different approach or am I just missing something? I would really appreciated it, if someone could help me out.
Use Recipient.FreeBusy instead - it does not require access rights to the mailbox.
I am updating rows of featureclasses via a plugin using C# and ArcObjects. For some reason the featureclasses then are not refreshing properly when the slider is moved, they do display properly if I manually refresh the map, however. I want to test if forcing a full refresh of the display on timeslider updates will work around the issue. In order to do that I want to listen for timeslider update events in my code.
I have seen another bug related to ArcSDE Direct Connection tables not displaying properly, but this is not my issue as I am not using an ArcSDE Direct Connection.
I have also recomputed attribute indexes (on time field) and spatial indexes but no dice.
So, hoping that refreshing on timeslider updates might help.
My C# plugin is running in ArcMap 10.1 SP1. Background enterprise geoDB is on SQLServer.
Thanks!
After a day of searching I posted my question, then found my solution within an hour.
ITimeDisplayEvents_DisplayTimeChangedEventHandler DTC_EH;
private void enableTimeDisplayEventHandler(bool enable = true)
{
IMxDocument pMxDoc = ArcMap.Document;
IMap pMap = pMxDoc.FocusMap;
IActiveView pActiveView = pMap as IActiveView;
IScreenDisplay pScreenDisplay = pActiveView.ScreenDisplay;
ITimeDisplay pTimeDisplay = pScreenDisplay as ITimeDisplay;
DTC_EH = new ITimeDisplayEvents_DisplayTimeChangedEventHandler(this.OnDisplayTimeChangedEventHandler);
((ITimeDisplayEvents_Event)pTimeDisplay).DisplayTimeChanged += DTC_EH;
}
private void OnDisplayTimeChangedEventHandler(IDisplay d, object oldvalue, object newvalue)
{
IMxDocument pMxDoc = ArcMap.Document;
IMap pMap = pMxDoc.FocusMap;
IActiveView pActiveView = pMap as IActiveView;
pActiveView.Refresh();
}
Hopefully somebody else finds that useful.
I need to get the direct reports from a logged in user (MVC 4)
I don't need the names of the direct reports but I do need their email addresses including their proxy addresses.
So for this reason I need to search through Exchange. I personally have never attempted to search Exchange in the past and everything I find out there tells me how to get from step 8 to the finish line but says nothing about how to go from step 1 to 8.
I can get the current users user name by simply
User.Identity.Name.Replace(#"yourdomain\", "")
and I have found this example which so far is probably the best example I have found
http://msdn.microsoft.com/en-us/library/office/ff184617(v=office.15).aspx
but even with that example the line
Outlook.AddressEntry currentUser =
Application.Session.CurrentUser.AddressEntry;
is not actually getting the current user logged into the site.
I really hope someone out there is familiar with this and can get me past this point.
I reworked the sample from the URL as the following LINQPad 4 query. I've found that LINQPad is a great way to experiment because it is very scripty, allowing quick experimentation, and you can easily view data by using the Dump() extension method. Purchasing intellisense support is totally worthwhile.
Also, I noticed there is a lot of fine print like:
The logged-on user must be online for this method to return an AddressEntries collection; otherwise, GetDirectReports returns a null reference. For production code, you must test for the user being offline by using the _NameSpace.ExchangeConnectionMode property, or the _Account.ExchangeConnectionMode property for multiple Exchange scenarios.
and
If the current user has a manager, GetDirectReports() is called to return an AddressEntries collection that represents the address entries for all the direct reports of user’s manager. If the manager has no direct reports, GetDirectReports returns an AddressEntries collection that has a count of zero.
So there are a lot of assumptions like Exchange is configured properly with Direct Report relationships, and the current user is online...which I believe brings Lync into the equation. Hopefully this LINQPad query will be useful to you. Just copy and paste it into a text editor and name it with the .linq file extension. You'll then be able to open it in LINQPad 4. BTW: You're question caught my attention because there was talk recently at my work of pulling direct reports from Active Directory. I wish I could be more helpful...good luck.
<Query Kind="Program">
<Reference><ProgramFilesX86>\Microsoft Visual Studio 12.0\Visual Studio Tools for Office\PIA\Office15\Microsoft.Office.Interop.Outlook.dll</Reference>
<Reference><ProgramFilesX86>\Microsoft Visual Studio 12.0\Visual Studio Tools for Office\PIA\Office15\Microsoft.Office.Interop.OutlookViewCtl.dll</Reference>
<Namespace>Microsoft.Office.Interop.Outlook</Namespace>
</Query>
void Main()
{
GetManagerDirectReports();
}
// Define other methods and classes here
private void GetManagerDirectReports()
{
var app = new Microsoft.Office.Interop.Outlook.Application();
AddressEntry currentUser = app.Session.CurrentUser.AddressEntry;
if (currentUser.Type == "EX")
{
ExchangeUser manager = currentUser.GetExchangeUser().GetExchangeUserManager();
manager.Dump();
if (manager != null)
{
AddressEntries addrEntries = manager.GetDirectReports();
if (addrEntries != null)
{
foreach (AddressEntry addrEntry in addrEntries)
{
ExchangeUser exchUser = addrEntry.GetExchangeUser();
StringBuilder sb = new StringBuilder();
sb.AppendLine("Name: " + exchUser.Name);
sb.AppendLine("Title: " + exchUser.JobTitle);
sb.AppendLine("Department: " + exchUser.Department);
sb.AppendLine("Location: " + exchUser.OfficeLocation);
sb.Dump();
}
}
}
}
}
I would suggest using EWS Managed API in conjunction with your code to get the direct reports for a user. As Jeremy mentioned in his response that you need to have your direct report relationships already set up. To help you get started, here some steps to get EWS Managed API up and running:
Download the latest version of EWS Managed API
Get started with EWS Managed API client applications to learn about how to reference the assembly, set the service URL, and communicate with EWS.
Start working with your code. If you need some functioning code to get you going, check out the Exchange 2013 101 Code Samples that has some authentication code already written and a bunch of examples you can modify to make your own.
If you have the email address or user name of the current user you can use the ResolveName() method to get to their mailbox to retrieve additional information. Here is an article to help with that method: How to: Resolve ambiguous names by using EWS in Exchange 2013
Essentially you want to get to the point where you can run a command similar to this:
NameResolutionCollection coll = service.ResolveName(NameToResolve, ResolveNameSearchLocation.DirectoryOnly, true, new PropertySet(BasePropertySet.FirstClassProperties));
If you give a unique enough value in the NameToResolve parameter you should only get back one item in the collection. With that, you can look at the direct reports collection within that one item and see not only the names of their direct reports, but their email addresses as well.
I hope this information helps. If this does resolve your problem, please mark the post as answered.
Thanks,
--- Bob ---
I´m trying to write an application to set Alerts on a list for all people that are already having minimum one alert in the sitecollection. I know how to get the user objects for all this users, but when I try to set the alert for each user there appears the problem. For some users there comes an SPException that says that the list is not existing. I looked in the user.Alerts propertie and there is a field Web, where the sitecollection name is at the users that dont work. It works only for the users that have the right web in there to access the list and set the alert. Does anyone know a workaround so that i can set alert for all the users that i want?
Here is the code I´m using to set the alerts:
SPAlert alert = user.Alerts.Add();
alert.AlertType = SPAlertType.List;
alert.EventType = SPEventType.Add;
Console.WriteLine(alertWeb.Url+" "+ alertingListName);
alert.List = alertWeb.Lists.TryGetList(alertingListName);
alert.AlertFrequency = SPAlertFrequency.Immediate;
alert.AlwaysNotify = false;
alert.Update(false);
Thanks in advance for helping me
I have solved the problem on myself now. I post the solution here so people who have the same problem can find it.
The problem was that in the User Object propertie user.alerts.web was the wrong web. I solved this problem by getting the user object not from the web.alerts collection but from the web.allusers collection, so that the right web stands in the propertie.
I'm working with the Audit framework in MOSS 2007, and I've programatically enabled Auditing for 2 specific lists in a bunch of sites in a site collection(meaning the sites all have their own two lists). I've only enabled the update mask, as I only want to know when something's been changed or added.
However, I'm only able to log when something's been added, with my current setup. To allow for seeing changes to the list items, I'm aware that the list item itself has to have auditing enabled. But when adding a new item to the list, how do I automatically enable Auditing for the item? If possible, I'd prefer to avoid creating an event receiver to accomplish this.
*EDIT
The code I use to enable auditing looks something like this:
foreach (SPSite site in webApp.Sites) {
foreach (SPWeb website in site.AllWebs) {
website.Lists["MyList"].Audit.AuditFlags = SPAuditMaskType.Update;
website.Lists["MyList"].Audit.Update();
}
}
And to read it:
SPUserToken sysAdmin = website.Site.SystemAccount.UserToken;
using (SPSite elevatedSite = new SPSite(website.Site.ID,sysAdmin)) {
using (SPWeb elevatedWeb = elevatedSite.OpenWeb(website.ID)) {
SPAuditQuery auditQuery = new SPAuditQuery(elevatedSite);
auditQuery.SetRangeStart(myDatetime);
auditQuery.RestrictToList(elevatedWeb.Lists["MyList"]);
listChanges = elevatedWeb.Lists["MyList"].Audit.GetEntries(auditQuery);
}
}
I realize I'm restricting to list here, but when I didn't I got changes from other lists on the site as well. Even though logically I'd assume I only got the changes from the list I called "GetEntries" on...
Thanks
If the library has auditing enabled, then new items will be audited. I'm not aware of any document-specific auditing
A little late in replying to this, but here is some additional information in case others find this post.
It is possible to track the auditing events at the document level. This link explains how it can be done. They use an event handler to make it work. I know you mention you do not want to do it this way, but this is what is needed to automatically track document events. Setting the audit mask type on the document library appears to only track the DL events, not the individual items.