Friday, June 29, 2012

Sharepoint 2010 - Multilanguage Site - Show column in current language

In multilanguage site feature, Sharepoint 2010 does not translate content of web part and metadata.
We have to find a way to show to user content or metadata in current language.

I used a list with columns with content in language and a lot of jquery to show and hide columns for current language.



I have a list with "DescriptionIT" and "DescriptionEN" columns.
Then, I set a view with both columns visible.
In this view, I added a content query web part whit code below.

In this code, I search for current language, i.e. "Italian", then search for column with "DescriptionIT", and hide all columns but "DescriptionIT" (with name starting with "Decsription").

Result is that if I change language (with Select Display Language), I see only column in respective language.



Simple and cross platform.

Here the code:


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

function DisplayLanguage(column)
{

 var langCode = _spPageContextInfo.currentLanguage;

 var columnEnglish = column+"EN";
 var columnItalian = column+"IT";
 var columnChinese = column+"CH";
 var columnSlovacchia = column+"SL";
 var columnSpanish = column+"ES";

 //
 var parentThName;
 var parentTh;
 //
 switch(langCode)
 {
    case 1033:
parentThName = columnEnglish;
        break;
    case 1040:
parentThName = columnItalian;
        break;
    case 1028:
parentThName = columnChinese;
        break;
    case 1051:
parentThName = columnSlovak;
        break;
    case 1034:
parentThName = columnSpanish;
        break;
    default:
  parentThName = columnEnglish;
        break;
 }

 //get column id to show
 parentTh = $("div[name='"+parentThName+"']").parent();
 parentThIndex = parentTh[0].cellIndex;
 //get all ths with Description
 allTh = $("div[name^='"+column+"']").parent();
 allTh.each(function(item){
    //hide all column but language column
    if($(this).index() != parentThIndex)
    {
  //hide
$(this).hide();
//get its id
var indth = $(this)[0].cellIndex;
//hide all cell of this column
$("td.ms-vb2").each(function(item){
   if($(this).index() == indth)
   {
$(this).hide();
   }
        });
    }
 });
}

DisplayLanguage("Description");

</script>


Friday, June 8, 2012

Sharepoint 2010: BeforeProperties and AfterProperties in Event Receivers!

Event Receiver is a great feature for Sharepoint 2010, but I spent many time to discover how Properties works..
Especially BeforeProperties and AfterProperties..

I found a great post with resume all available values. Here table and below the link!

http://www.synergyonline.com/Blog/Lists/Posts/Post.aspx?ID=122

These are the values of the properties in List events:
ListBeforePropertiesAfterPropertiesproperties.ListItem
ItemAddingNo ValueNew ValueNull
ItemAddedNo ValueNew ValueNew Value
ItemUpdatingNo ValueChanged ValueOriginal Value
ItemUpdatedNo ValueChanged ValueChanged Value
ItemDeletingNo ValueNo ValueOriginal Value
ItemDeletedNo ValueNo ValueNull
And here are the properties available in Library events:
LibraryBeforePropertiesAfterPropertiesproperties.ListItem
ItemAddingNo ValueNo ValueNull
ItemAddedNo ValueNo ValueNew Value
ItemUpdatingOriginal ValueChanged ValueOriginal Value
ItemUpdatedOriginal ValueChanged ValueChanged Value
ItemDeletingNo ValueNo ValueOriginal Value
ItemDeletedNo ValueNo ValueNull

Thursday, June 7, 2012

Sharepoint 2010: Deactivate and Activate Feature with Power Shell

Sometimes, you can have trouble with feature upgrade in your site.
Especially if you upgrade event receiver, adding new trigger.
If you have many sub site using this feature, you can use Power Shell to deactivate and activate feature.

This mine:


[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
$rootUrl = "http://[SERVERNAME]"
$site = Get-SPSite $rootUrl
foreach($web in $site.AllWebs)
{
  $url = $web.Url
  if($url -ne $rootUrl){
   foreach($feature in Get-SPFeature -Web $url)
   {
    $featureName = $feature.DisplayName
    if($featureName -eq "FEATURE NAME")
    {
      "Disable and Enable feature $featureName in $web"
      Disable-SPFeature -Identity FEATURENAME -Url $url -Confirm:$false
      Enable-SPFeature -Identity  FEATURENAME -Url $url
      break;
    }
   }
  }
}

Sharepoint 2010 Globally Reusable Workflows does not update WF instance in Subsite if re-published: PS Script save me

I defined a Globally Reusable WF for a custom Content Type in root site, with a custom form with InfoPath.
I defined a sub site with a list using the global WF template created for its Content Type.
Everything works without problems.

Now I need to change the WF (both in form and in the process).
BUT..
If I edit only the form with InfoPath and then I publish the form, I see correctly the new form in WF on subsites.
If I change the WF logic too (any actions) and publish WF (in root site), changes are not perceived by WF on subsites.
WF on subsite is updated only if, on subsite, I open WF to change (from browser) and save it.

I expect that you can update all WF in subsite using template in root site, without having to reopen and resave each WF in each subsite.
I don't understand if it's a bad configuration or a issue on Globally Reusable WF.

(I opened question in Technet Forum, here)

UPDATE: Sometimes, I update a WF (form and logic) and logic has been correctly published in all web site, but form does not show my modification...

So, unique solution I found for all my subsites is to delete workflow association and recreate it, for each site... But it's a long task, depend on how many subsites you have.

I write this powershell script to automate removing and adding operation.
This helps me, but cannot solve problems..
If you don't have access to Server to run PS Scripts, you cannot use this way...


[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
$urlRoot = "http://[SERVER]"
#array of workflow name to update
$wfNames = "Workflow Name 1"," Workflow Name 2", "Workflow Name 3"

$site = Get-SPSite $urlRoot

foreach($web in $site.AllWebs){

 $url = $web.Url

 #exept for root site (if needed)
 if($url -ne $urlRoot){

   foreach($wfName in $wfNames){

     "Adding workflow $wfName to $url"

     $list=$web.Lists["LISTNAME"]
     $taskList=$web.Lists["WF TASK LIST NAME"]
     $historyList=$web.Lists["WF HISTORY LIST NAME"]
     $ct=$list.ContentTypes["CONTENT TYPE"]

     "Search workflow $wfName"
     foreach($wf in $ct.WorkflowAssociations)
     {
       if($wf.Name -eq $wfName)
       {
         "Remove workflow $wfName"
         $ct.WorkflowAssociations.Remove($wf)
         break;
       }
     }

     "Now add workflow $wfName"

     $culture=New-Object System.Globalization.CultureInfo("en-US")
     $wfTemplate=$web.WorkflowTemplates.GetTemplateByName($wfName,$culture)

     "Get wf template"
     $associationWF=[Microsoft.SharePoint.Workflow.SPWorkflowAssociation]::CreateListContentTypeAssociation($wfTemplate, $wfName,$taskList,$historyList)

    "Add Workflow $wfName"
     $ct.WorkflowAssociations.Add($associationWF)
     $ct.UpdateWorkflowAssociationsOnChildren($true,$true,$true,$false)
  }
 }
 $web.Dispose()
}