Pages

Monday, February 13, 2012

Get Document Path from SharePoint Library in VSTO


While working with VSTO AddIn, there was a need to get the source path of the document while it is being opened from a SharePoint document library.
After little efforts, managed to find the property like

Globals.ThisAddIn.Application.ActiveDocument.Path;

But this works only when you open an existing document from the library and not when you try to create new document.
Was wondering for some time that why is this behavior shown by Word APIs?? But MS forums helped a lot.
There are two ways to get the document path / source URL when you open the new document from document library.

1. Get the template of the document and then retrieve source / path of the template. Generally all template path returns something like – http://siteurl/doclibname/forms/templatename
Template template = Globals.ThisAddIn.Application.ActiveDocument.get_AttachedTemplate() as Template;
string path = template.Path;

2. Environment.CommandLine returns the string using which you can get the source of the document. Some formatting is needed which can be done like this
public string GetDocLibPath()
{
  string path = string.Empty;
  string[] tempArray = Environment.CommandLine.Split(new char[] { '"' }, StringSplitOptions.RemoveEmptyEntries);
  if (tempArray.Length >= 3)
  {
string[] temp2Array = tempArray[2].Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
       if (temp2Array.Length == 3)
       {
          path = temp2Array[2];
       }
               
   }
  return path;
 }

References: MSDN Forums | MSDN Forums

Monday, January 9, 2012

How to find and replace text programmatically – MS Word


While working with the Add – In, came across the scenario where I needed to replace the text in word document programmatically, this is how it can be done
Following code finds the word occurrence and replaces with the desired characters in first paragraph of the document.
private void FindAndReplaceText(object _wordToFind, object _replaceWith)
{
      
 string _text = Globals.ThisAddIn.Application.ActiveDocument.Paragraphs[0].Range.Text;

 object machtCase = true;
 object matchWholeWord = true;
 object matchWildCards = false;
 object matchSoundsLike = false;
 object nmachtAllWordForms = false;
 object forward = true;
 object format = false;
 object matchKashida = false;
 object matchDiacritics = false;
 object matchAlefHamza = false;
 object matchControl = false;
 object read_only = false;
 object visibible = true;
 object replace = 2;
 object wrap = 1;

 _Globals.ThisAddIn.Application.ActiveDocument.Paragraphs[0].Range.Find.Execute(ref _wordToFind,
        ref machtCase,
        ref matchWholeWord,
        ref matchWildCards,
        ref matchSoundsLike,
        ref nmachtAllWordForms,
        ref forward,
        ref wrap,
        ref format,
        ref _replaceWith,
        ref replace,
        ref matchKashida,
        ref matchDiacritics,
        ref matchAlefHamza,
        ref matchControl);
 }

Reference Link: - Here

Tuesday, January 3, 2012

How to Read Document Properties Programmatically


This was the one of good learning while working with MS Office Add-In using visual studio so thought to share.
Each document ships with some kind of metadata with it, and to them we call as properties. For word documents there are three types of properties available (As per my knowledge). And here are those
(Examples / APIs below are accessible when you create new application level add in, reference links are from MSDN pages where excel is considered as MS Office Application)

1.    Built In Properties / Default Properties – These are set of properties which are available with any word document, example of these can be – Title, Description, Keywords. More Information/Reference - Here
You can programmatically deal with these properties as –
DocumentProperties builtInDocProperties = (DocumentProperties)Globals.ThisAddIn.Application.ActiveDocument.BuiltInDocumentProperties;
foreach (DocumentProperty prop in builtInDocProperties)
{
   try
   {
     //Console.WriteLine(prop.Name + " - " + prop.Value);
   }
   catch { }
}

2.   Custom Properties – More Information / Reference - Here
DocumentProperties customDocProperties =  (DocumentProperties)Globals.ThisAddIn.Application.ActiveDocument.CustomDocumentProperties;

foreach (DocumentProperty prop in customDocProperties)
{
   try
   {
//Console.WriteLine(prop.Name + " - " + prop.Value);
   }
   catch { }
}

3.    Content Type Properties – These are the set of properties which are as the site columns / fields    in content type of the document library. In short these are server side properties of the document when document is opened from the document library. You won’t be able to access these properties programmatically when document is opened locally on machine. i.e. unless and until document is not opened from SharePoint document library , these properties will not be available to do to get/set operations. More Information Here / Reference - Here

MetaProperties _ctProperties = (MetaProperties)Globals.ThisAddIn.Application.ActiveDocument.ContentTypeProperties;
foreach (MetaProperty _ctp in _ctProperties)
{
   try
   {
       //Console.WriteLine(ctp.Name + " - " + ctp.Value);
   }
   catch { }
}

Noticed catch blocks while iterating through for each loop? Yes, these are required because few properties throws exception and reason is unknown to me. For example, in content type properties whenever people and group type of property is accessed, exception is thrown. You can read more on the MSDN Forums about this issue. – Here is the link.
More ever you can set the server side properties programmatically using same API like –
MetaProperties _ctProperties = (MetaProperties)Globals.ThisAddIn.Application.ActiveDocument.ContentTypeProperties;
_ctProperties ["Title"].Value = "TestTitle";

You just need to call the save method of the document instance to get these properties reflected in document library.

Word Add In Installer - Unable to read App Config


app.config file is not getting read after installing word add in installer?
Solution:
In Installer project there is a registry key for add in which has manifest entry. MSDN Documentation says that manifest values should be set to - [TARGETDIR]YourAddIn.vsto|vstolocal , now when this is changed to file path like file:/// [TARGETDIR]YourAddIn.vsto|vstolocal and reinstalling add in I got everything working fine.
Note : This worked for me and there is no guarantee that will work in each scenario , also be careful while modifying registry entries.

Error while accessing office document cache


I don’t know why but suddenly I started facing this error while I was trying to create new document or edit existing document in the SharePoint document library. was using Office 2010 and SharePoint 2010.
Error Message was: - Error while accessing office document cache.
Solution:
A quick search on the dear friend google given some idea I don’t remember what was the source of this post and that’s why thought to share.
Open task manager and take a look at processes tab. Try to find the process with name MSOSYNC.exe

And end the process. Now try to create / open documents from SharePoint document library and I hope this error will not be there anymore.
Note: I didn’t search for where else this process is used for, so not sure what effects this can have in your environment but worked fine for me for above error.
More Information about MSOSYNC.exe and other way to delete cached files here.

How to set people and group column programmatically using Client Object Model


using SP = Microsoft.SharePoint.Client;
using (SP.ClientContext _ctx = new SP.ClientContext("http://YourSiteUrl"))
{
  SP.ListItem _listItem = null;

  ctx.Credentials = CredentialCache.DefaultCredentials;
 
  SP.List _testList = web.Lists.GetByTitle("TestList");
  SP.CamlQuery _query = new SP.CamlQuery();
  query.ViewXml = @"<View><Query><Where><Geq><FieldRef Name='ID'/>" + "<Value Type='Number'>10</Value></Geq></Where></Query></View>";
  SP.ListItemCollection _listitems = _configList.GetItems(_query);

  ctx.Load(_listitems);
  ctx.ExecuteQuery();
 
  if (_listitems != null && _listitems.Count > 0)
  {
     _listItem = _listitems[0];

     SP.FieldUserValue _userValue = new SP.FieldUserValue();
     SP.User _newUser = _ctx.Web.EnsureUser("domain\\username");
     _ctx.Load(_newUser);
     _ctx.ExecuteQuery();

     _userValue.LookupId = _newUser.Id;

     _listItem["userfield"] = _userValue;
     _listItem.Update();

     _ctx.ExecuteQuery();

  }   

);

Wednesday, December 28, 2011

How to hide properties in Document Information Panel – SharePoint

Document Information Panel – This is the window which shows all the properties associated with the document. Let it be out of the box / default properties (like Title, Keywords), or custom properties or content type properties.

Wait, what are content type properties?
Consider a scenario where you have a SharePoint site and a document library. You create some site columns and then create content type for your document library. (Inheriting from the document content type). Now you associate this newly created content type to your document library and done.

You go ahead and click on create New Document link and Word Editor opens up. Now there you see the Document Information Panel (DIP) containing all the site columns in your content type. These are metadata holders for your document. And that’s why these document properties are called as content type properties.

In Following Image, I have opened the document from the SharePoint document library and added Version and Comments column in the default document content type , which are visible in DIP.


Issue:
There were some of the content type properties which were getting displayed in DIP, but I didn’t want users to see those /change those. In short I needed to hide those.
Let’s try to hide version property from DIP.
Solution:
First thought comes to mind like – ok these properties are nothing but the site columns right? So why don’t we just delete the site columns and get rid of properties in DIP? But NO. Because if we delete the site columns from the content type , the DIP won’t show the property but document will not be holding the metadata for that column.
So what could be done?
Trick I found is, just hide the site column.
How we can do it?
Library settings > Find your content type and click on it > select the site column which you don’t want to see in DIP > click on Hidden option in advanced option and select ok.



Now DIP will not show the content type property when creating new documents from the library
Version column gets hidden from DIP



Note: This approach is used only when the site column is not of type mandatory/required. As per my knowledge you cannot hide the column which is required.