Wednesday, April 17, 2019

Edit page issues with Full control permissions

Hi All,

I was struggling with an issue where the user couldn't able to edit the home page of the site despite having full control permissions to the site via. Owners group. For the meanwhile, I've added user to Site Collection Admin group. But that is not a proper solution to the issue.

I deep dive through internet to identify the root cause. After lot of research, I got to know that if there are no permissions for 'Master Pages and Page Layouts' library then other than site collection administrator no one can edit the pages.

I checked the same to the site and observed that there are unique permissions for 'Master Pages and Page Layouts' library and no one other than site collection administrator can see its content. I made the library inherit permissions from parent and removed the user from site collection admin group as I did earlier. Luckily, it worked and user can able to edit the page without having herself to get added in site collection administrator's group. :)

Thanks,
Kunal Basu

Tuesday, April 2, 2019

Your account is in a bad state - issue

Hi All,

I was facing couple of issues in my project. Here are the following-


  1. User is unable to open the SharePoint Online site in SharePoint Designer. The moment user is trying with his credentials, he received the error message - "Your account is in bad state".
  2. User is trying to update in InfoPath list form by making changes in template.xsn file for that list. He made the changes but when he's trying to publish the form - he get's the error: "Your account is in bad state".

While analyzing the issue, I got to know that legacy authentication is disabled for SharePoint online sites. Hence, modern authentication is enabled. While SharePoint Designer wasn’t natively designed to work with Modern Authentication (ADAL) there are updates available that allow it to work.Most Office 2013 applications will be able to successfully use modern authentication once the EnableADAL=1 registry key has been set. See the below link for the article.



You can refer to the below link for InfoPath related issue as the root cause is same for both SPD and InfoPath Designer.



Thanks,
Kunal

Wednesday, December 12, 2018

Archive documents from site using PowerShell

Hi All,

Recently, I worked on a PowerShell script to archive documents from multiple document libraries to local machine. It was a SharePoint 2010 site and links for all the documents are stored in a CSV file. There were about 9K files. The script worked well but it has some limitations. Within the link, any folder name/file name can't have commas (,) otherwise it won't create a structure in local machine. All the documents will be archived in local machine within the folder structure being created from the URL.

Here's the script below.

Add-PSSnapin Microsoft.SharePoint.PowerShell


$Files = Import-Csv "C:\Microsoft PowerShell\GDWFilesTask\GDW Files task\LessFiles.txt"

$TargetPath = "E:\GDW Files"

$wc = New-Object System.Net.WebClient
$wc.UseDefaultCredentials = $true

ForEach ($File in $Files){ 
  
  $FPath = $($File.Path)

  $FolPath = $FPath

  $String = $FolPath.ToString()

  $String -replace ',',' '
  

  [System.Collections.ArrayList]$ArrayList = $String.split("/")
  $ArrayList[0] = $TargetPath;
  $ArrayList[2] = "GDW"
  $ArrayList.RemoveAt(1)
  $ArrayList = $ArrayList -notlike "*.*"

  $b = ($ArrayList -join "\")

  New-Item -ItemType directory -Path $b  

  $FileName = Split-Path $FPath -leaf  

  $output = $b +"\"+ $FileName

  $wc.DownloadFile($FPath, $output)

  #write-host $FPath -ForegroundColor Green
  #write-host $output -ForegroundColor Yellow

  write-host $FileName " is downloaded.`n" -ForegroundColor Yellow
  
}


LessFiles.txt
Path
http://gdw.myaccobrands.com/Teams/BusinessTransformation/Restructuring/2012 Restructuring/PFS Model Change Phase III Tournis John Severance Calc Estimator 10.12.12.xls
http://gdw.myaccobrands.com/Processes/TPB/Documents/Audit/Projects/PROJ-61-Canada Fin/Oracle Programs Freight Distribution allocation logic into GDW for Canada.xlsx
http://gdw.myaccobrands.com/Teams/BusinessTransformation/Restructuring/2013 Restructuring/US Ops Reorg RPA-2013-15 Restructuring Project Approval Form_OPS May 10 2013.xlsx
http://gdw.myaccobrands.com/Teams/BusinessTransformation/Restructuring/2013 Restructuring/IT Restructuring RPA-2013-14 Restructuring Project Approval Form_IT April 29 2013.xlsx
http://gdw.myaccobrands.com/Teams/BusinessTransformation/Restructuring/2013 Restructuring/Canada Call Center Restructuring Project Approval Form - March 18 2013.xlsx
http://gdw.myaccobrands.com/Teams/BusinessTransformation/Restructuring/2013 Restructuring/CAN Footprint Phase II Boulder Final DCF Model - March 18 2013.xls


I followed the below references to develop the code

http://keith-wood.name/countdown.html
https://www.w3schools.com/howto/howto_google_translate.asp
http://www.openxrest.com/translatejs/
https://www.script-tutorials.com/demos/42/index.html
https://social.technet.microsoft.com/Forums/office/en-US/1351c3ed-e673-4d6c-ba3b-27a50ced7e1a/translate-sharepoint-custom-list-forms?forum=sharepointgenerallegacy

https://www.c-sharpcorner.com/UploadFile/mahesh/how-to-add-items-to-a-dictionary-with-C-Sharp/


Thanks,
Kunal

Thursday, August 30, 2018

Language translator in JavaScript

Hi Folks,

I got a requirement to translate SharePoint list form to multiple languages. I tested with translating from English to Portuguese and German. We can add further languages later. I took use of the link to implement the translation. It is good but I faced issues in translating the text in buttons as for buttons, it is of 'input' type and we need to translate the values stored in those input controls. Also, I've to use a SharePoint list which will have the translations based on respective word in list form. So I've to make changes to the translate.js file referred in the above link to extend the functionality.

Please see below for original and translated form.
Original Form

Translated Form


The JavaScript written in the page is mentioned here:
<script type="text/javascript" src="../../SiteAssets/Scripts/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="../../SiteAssets/Scripts/jquery.translate.js"></script>
<script type="text/javascript" src="../../SiteAssets/Scripts/Dictionary.js"></script>
<script type="text/javascript">

$(function() {

$(".js-category").find("label").each(function(){
var text = $(this).text();
$(this).empty().append( $("<span></span>").addClass("trn").text(text) );
});
$(".js-category").find("select option").each(function(){
$(this).addClass("trn");
});
$(".js-category2").find("label").each(function(){
var text = $(this).text();
$(this).empty().append($("<span></span>").addClass("trn").text(text));
});
$(".js-category3").find("label").each(function(){
var text = $(this).text();
$(this).empty().append( $("<span></span>").addClass("trn").text(text));
});
$(".btnSaveCancl").find("input[type=button]").each(function(){
$(this).addClass("trn");
})
$("nobr").each(function(){
var text = $(this).text();
$(this).empty().append($("<span></span>").addClass("trn").text(text));
//alert(text);
});

});
</script>




The link suggested to add <span class="trn">Your_Text</span> to translate the text. It could able to translate the field labels but not the text which is generated dynamically in my SharePoint fields. So I had to add class to the td's and add JavaScript to add the span dynamically. Please check below.


The jquery.translate.js file referred externally is mentioned below.
/**
 * @file jquery.translate.js
 * @brief jQuery plugin to translate text in the client side.
 * @author Manuel Fernandes
 * @site
 * @version 0.9
 * @license MIT license <http://www.opensource.org/licenses/MIT>
 *
 * translate.js is a jQuery plugin to translate text in the client side.
 *
 */

(function($){
  $.fn.translate = function(options) {

    var that = this; //a reference to ourselves
    var settings = {
      css: "trn",
      lang: "en"/*,
      t: {
        "translate": {
          pt: "tradução",
          br: "tradução"
        }
      }*/
    };
    settings = $.extend(settings, options || {});
    if (settings.css.lastIndexOf(".", 0) !== 0)   //doesn't start with '.'
      settings.css = "." + settings.css;
       
    var t = settings.t;

    //public methods
    this.lang = function(l) {
      if (l) {
        settings.lang = l;
        this.translate(settings);  //translate everything
      }
        
      return settings.lang;
    };


    this.get = function(index) {
      var res = index;
 var _l = settings.lang;
      try {
        //res = t[index][settings.lang]; //takes object
        
        for(var item in t[index]){ //takes array of objects
        if( t[index][item].hasOwnProperty(_l) ){ 
        res = t[index][item][_l];
        break;
        }
        }     
      }
      catch (err) {
        //not found, return index
        return index;
      }
      
      if (res)
        return res;
      else
        return index;
    };

    this.g = this.get;


    
    //main
    this.find(settings.css).each(function(i) {
      var $this = $(this);

      var trn_key = $this.attr("data-trn-key");
      if (!trn_key) {
        trn_key = ($this.is('input') && $this.attr('type')==='button') ? $this.val() : $this.html();
        $this.attr("data-trn-key", trn_key);   //store key for next time
      }
if($this.is('input') && $this.attr('type')==='button'){
$this.val(that.get(trn_key));
}
else{
 $this.html(that.get(trn_key));
}
    
    });
    
    
return this;

  };
})(jQuery);



For button, I had to modify the code with these steps.

This helped me to create a basic prototype for translation.

I created Dictionary.js to read translations from a SharePoint list and perform translation to the SharePoint list form.

var dict = '{';
var _t;
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', RetrieveListItems);

function RetrieveListItems(){
var clientContext = SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle('Translation');
var caml = new SP.CamlQuery();
caml.set_viewXml("<View />");
listItemCollection = oList.getItems(caml);
clientContext.load(listItemCollection);
clientContext.executeQueryAsync(onRequestSucceeded, onRequestFailed);
}

function onRequestSucceeded(){
var count = listItemCollection.get_count();
//alert(count);
var listEnumerator = listItemCollection.getEnumerator();
while(listEnumerator.moveNext()){
var listItem = listEnumerator.get_current();
var key = listItem.get_item('Title');
var val = listItem.get_item('Value');
var ger = listItem.get_item('German');
//alert(key+' , '+val);
var item_dict = '"'+key+'":[{"pt":"'+val+'"},{"en":"'+key+'"},{"ge":"'+ger+'"}],';
dict = dict + item_dict;
//alert(dict);
}
dict = dict.substring(0, dict.length-1) + '}';
var newList = JSON.parse(dict);
_t = $('body').translate({t: newList});
console.log(dict);
 $(".lang_selector").click(function(ev) {
 
    var lang = $(this).attr("data-value");
    //alert(lang);
    _t.lang(lang);

    console.log(lang);
    ev.preventDefault();
  });

}

function onRequestFailed(sender, args){
alert('Error: ' + args.get_message());
}



The new jQuery.translate.js takes an array of objects unlike the previous object as we couldn't able to create dynamic dictionary and had to create string array in specific format. Then we parse it as JSON and transferred the object array for translation.




Thanks,
Kunal

Tuesday, August 28, 2018

Update multi-value lookup fields from source to destination lists.

Hi Folks,

I would like to share my experience on updating the multi-value lookup field values from source list to multi-value lookup field in destination list.
I tried several things but one thing is sure, we cannot achieve it using SharePoint 2013 workflow 'Update List item' step. I had to include SharePoint 2010 WF within SharePoint 2013 WF. Also, I need to keep current item's lookup field type as 'string' to make it work.


'Update IT Systems' is SharePoint 2010 WF which I started within SharePoint 2013 WF. Please see below.

It resolved my issue. The big part is none of the blogs in google have provided a working solution. So, I am writing this blog to save some lives :-).

Thanks,
Kunal

Friday, December 22, 2017

Customize the Printable view of a SharePoint list form

Hi Folks,

I got a task to customize the print view of 'DispForm.aspx'. I've utilized '@print media' query to achieve the functionality.I created a custom CSS file to add the '@print media' query.

The CSS file look as below.
#logo img{
display:none;
 }
 h2
 {
font-weight:bold;
 }
h3
{
font-weight:bold;
}
#tabHead
{
display:none;
}
#tabFooter img{
display:none;
}

@media print 
{
 nobr
 {
  font-weight:bolder;
  font-size:22px;
  font-family:Arial;
 }
 .ms-formbody
 {
font-size:22px;
font-family:Arial;
 }
 #logo img
 {
display:block;
height:80px;
direction:ltr;
top:auto;
 }
 .ms-standardheader
 { 
background-position:center;
text-align:left;
 }
 #tabPos > tbody:nth-child(2)
 {
padding-right:15px;
`}
 #tabPos
 {
text-align:left;
border:2;
width:80%;
 }
 #WebPartWPQ2 > table > tbody > tr:nth-child(3) > td
 {
 }
 .hideField
 {
display:none;
 }
 #WebPartWPQ2 > table > tbody > tr:nth-child(4) > td > table
 {
display:none;
 }
 #tabHead
 {
display:table-cell;
font-size:24px;
font-family:Arial;
 }
 #tabFooter img
 {
display:block;
 }
}

The print view would be displayed as shown below.












It helped me a lot and we can use it for future purpose.

Thanks,

JS Link use to display image hyperlink to List view column

Hi All,

I had a task to display an image hyperlink for the list view column. By clicking the image it will navigate to a page which is styled in print view of page.

At first, I added a single line of text field - PrintForm. Then I create a custom standard view- Print View. 'PrintForm' will be available in 'PrintView.aspx'.
I edit the page at first and then edit the web part which contains the web part.
I wrote a small JS code to achieve the functionality.

SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function() {

SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
  Templates: {
Fields: {
           'PrintForm': {'View':function(ctx) {         
           return String.format("<a href='<CustomizedDisplayForm>.aspx?ID={0}' target='_blank'><img src='<ImageUrl>' width='42' height='42'></a>",  ctx.CurrentItem.ID);
}}

        }//Fields
  }//Templates
});
})


Once I completed the JS code, I appended the path of .js file to JS link in Miscellaneous section. After I saved the changes, the view would like as shown below.






Thanks for reading my post, I'll write another for print section.