Determine Who Last Modified an InfoPath Form in SharePoint

There are articles on Google that help you add a field to an InfoPath form so that you can display who last modified it.  Great.  However, I needed to find out who had last edited (and thoroughly screwed up) an InfoPath form on a specific list in our SharePoint 2010 environment.   It takes a little digging.

First of all, you’re going to need to use SharePoint Designer 2010.   Open SPDesigner and navigate to your site.  Now select All Files at the bottom of the left navigation menu.  Then select Lists in the right-hand pane.  (Shown below)

Note: If you cannot see the All Files menu item as shown below, read this previous article.

SPDesigner-All-Files-Lists

Once you’ve selected Lists from the right pane, select your list.  It will take you to a screen that I find misleading.

InfoPath-List-modified

Note that the dates are way off.  I just made a change a few minutes ago and it’s not reflected here at all.  This information is three years old.  So ignore the findings on this page.

To dig deeper, click on the directory here NOT named Attachments. In this case the other list is Announcement, although yours will be different.

InfoPath-List-modified-correct

You should now see several .aspx files and one template.xsn.  The information on this page in the columns for Modified Date and Modified By are what you’ve been looking for.   Enjoy.

Posted in SharePoint 2010 by Doug.

SharePoint Designer 2010 “All Files” is Missing / Not Showing on Menu

I keep SharePoint Designer disabled ever since one malicious user caused a great deal of trouble two years ago.  We have over 15,000 users and the risk is just too great.  As you probably know, SharePoint Designer is enabled/disabled at the web application level and then at the site collection level (for some degree of granularity).  To keep life simple, I keep it disabled at the web app level and then selectively (and briefly) enable it when a user needs to make a change.  But first, they have to show me what they’ve done in the Test environment, where SPDesigner is fully enabled all the time.  If you demonstrate capability in Test, you get a window of time to do your magic in Production.  Let’s call this: Doug’s Very Effective SharePoint Designer Methodology.

Now to solve the issue at hand.  I had a need to enable SPDesigner at the web app level for a user.  The problem was that they could not see the All Files menu item that usually appears on the left menu.  You’ll notice that below Subsites in the menu below that it is blank where All Files should render.

SharePoint-Designer-2010-All-Files-Missing

The problem was caused by my laziness – I had simply selected the checkbox for Enable SharePoint Designer.

The solution is simple: when you enable SPDesigner at the web app level (by selecting the first checkbox to Enable SharePoint Designer), if you want the user to see the All Files menu item, make sure to also check the checkbox for Enable Managing of the Web Site URL Structure, as shown below.

SharePoint-Designer-WebApp-Settings

Then your menu should look like this, with the All Files menu item below Subsites.

SharePoint-Designer-2010-All-Files

Posted in SharePoint 2010 by Doug.

List View Web Part Paging Issue

One of my users has a SharePoint site with a list called Admin Tips, currently with 45 tips (list items).  She has a List View Web Part (LVWP) on the main site page to render this list, choosing a particular view to render for the web part.  The specific View she has chosen has the Item Limit set to 1.

View-Item-Limit

The result is that the tips show one at a time in this View.  Therefore, the LVWP on the main page which calls this view renders the tips one at a time.  Each tip has a “pagination” link at the bottom which is a fancy term for paging, both of which mean: you can go from one page (or tip) to another.  Most of the time you see this on the web as Back and Next buttons (or links).

Here’s how this specific LVWP renders on the main page:

LVWP-Main-Page

I clicked the arrow (above) which took me to Tip 2:

LVWP-Main-Page-2

And here is Tip 3:

LVWP-Main-Page-3

Notice how each tip shows arrows for going backward and forward to other tips.

Unfortunately, the numbers in between are wrong.  Knowing that there are 45 items in the list, the three tips should show “1 of 45”, “2 of 45”, and “3 of 45”.  Or simply 1, 2, and 3.  But definitely not 1-1, 2-2, and 3-3.  Why the hyphen and then a repeat of the tip number?  It doesn’t make sense.  So far, the only help I’ve been able to find on the Internet is to edit the XSLT and hope for the best.  Personally, I’m not interested in going that route.

My Solution

The important thing to note here is that the pagination issue is on the View.  The List View Web Part on the main page is simply rendering the View specified in the web part, so let’s focus on the View itself.  Go to the list and select the View that is being rendered in the web part.  Most likely, it will be All Items but if you’ve created another View and chosen it for the LVWP, then go to that View.  Notice that you’re on a specific .asp page rendered as <viewname>.aspx.

I figured I could solve this problem using CSS and I wanted a simple solution.  Seeing that I have the Back and Next arrows, I don’t really care if the user knows which precise tip they’re on.

I opened my browser in IE, navigated to the list, selected the View, and then launched IE Developer Tools by selecting the F12 button.  In the Developer Tools pane at the bottom I selected Find >> Select element by click.

I selected the section where the paging occurs:

Select-Element

Developer Tools tells me the code behind this element, including the exact CSS class:

DevTools-element

So I wrote a little script that will change this td.ms-paging element:




<style>
 td.ms-paging { 
	text-indent: -9999px;
	line-height:0;
}
 td.ms-paging:before { 
	text-indent:0;
	content:'Other Tips';
	display:block;
	line-height: initial;
}
</style>



I wish I could take full credit for this solution but I cannot.  I just put it all together.  I tried Option 1 from The WP Guru on this page but it did not work for me.  However, Option 2 worked like a charm.

I simply saved the above code to a .txt file and uploaded it to the Site Assets folder, then opened it and copied the url.

Next, I went to the main site page, added a Content Editor Web Part (CEWP) above the Admin Tip section (so the browser will process my CSS code first), and pasted in the link to the .txt file.

As a housekeeping tip, under Appearance, change the Chrome Type to None.  See below.

Chrome-Type

It works perfectly as far as I’m concerned.  I simply replaced the bad paging nonsense with the term “Other Tips” as you can see:

LVWP-Fixed

Clicking the arrow took me to Tip 2:

LVWP-Fixed-2

 

Now my users can navigate back and forth to other tips without being annoyed at the wacky pagination numbers that SharePoint renders.

Last, it’s up to you if you want to add this solution to the specific View on the list as well.  If you do, simply navigate to the list, select the specific View with the paging feature, add a CEWP at the top of the page, and paste in the link to your text file.  Don’t forget to change Chrome Type to None and you’ll be all set.

Posted in SharePoint 2010 by Doug.

Migrate a list to another site collection or web app

One of my users came to me today frustrated that he cannot find any information from Google about migrating a list from our Test environment to our Prod environment.  He says that most of the content is for 3rd party products.  He certainly doesn’t want to move it by hand.  Good news: the solution is easy.

This will work across site collections and even web applications. As you probably know, when you save a list as a template, it saves it to the Site Collection List Template Gallery, which means it’s only available to be deployed elsewhere in the Site Collection. The following steps will allow you to migrate a list to another site collection, or even another web application.

 

Summary of Steps

  1. Save the list as a template
  2. Go to the list template gallery and download it locally
  3. Navigate to the site collection list template gallery where you want the list to be
  4. Upload it to the gallery
  5. Deploy it to your desired site

 

Detailed Steps

1.  Save the list as a template

In your list, go to the List tab and select List Settings

List-Settings

Save the list as a template.

Save-list-as-template

2. Go to the list template gallery and download it locally

Click Site Actions, Site Settings

Site-Settings

Go to Top Level Site Settings (which is for the Site Collection)

Top-Level-Site-Settings

Under Galleries, Select List Templates

List-templates

Browse to the list template you just created and select the checkbox to the left of the name

Select-list-template

Select Download a Copy from the ribbon and save to your local machine

Download-list-template

3. Navigate to the site collection list template gallery where you want the list to be

Now, navigate to the site where you want the list to ultimately reside.

As before, go to Site Actions >> Site Settings >> Site Collection Administration: Go to top level site settings

Top-Level-Site-Settings

As before, go to Galleries: List Templates

List-templates

 

4. Upload it to the gallery

On the ribbon, select the Documents tab.

Now select the Upload Document button.

Upload-Document

The list template is now in the site collection gallery and will thus be available to you for deployment to your site.

 

5. Deploy it to your desired site

Navigate to the site where you would like the list.  Click Site Actions >> More Options

More-Options

I like to filter the Create page to just the lists.  Do this by clicking List under Filter By:

Filter-By

Select your list and deploy.  And you didn’t need a 3rd party tool at all.

Posted in SharePoint 2010 by Doug.

Change the URL for a List or Library in SharePoint

Create-New-Site

Provides for both a Site title as well as URL

Create-New-Site-with-Data

I prefer to use full words for the title and abbreviations for the URL.


In SharePoint 2010, when you create a new site, you provide both the Site Name and the Site URL.  If at any point you want to change either, it’s simple.  Just go to Site Actions >> Site Settings >> Look and Feel [section] >> Title, description, and icon.

Site-Title-Description-icon

However, when you create a new List or Document Library, you provide the name but you do not have anywhere to specify the URL.  The URL is generated by SharePoint from the name you provide.  Often, this has undesirable results.

  • The worst offender is spaces. Each space is converted to %20 in the URL string.
  • Dashes in the name are omitted in the url, so if you used them for splitting words, you’re out of luck.
  • Long list or document library names may be fine for displaying on the menu but they make for cumbersome, often needlessly long URLs.
  • If you’re several sub-sites deep, your spaces have been converted to %20, and you have long list or library names, coupled with long filenames, you run the risk of exceeding the 256 character limit.

 

The Solution That Doesn’t Work
If you attempt to rename the list or document library, it doesn’t change the URL at all.  You’re stuck with the original URL.  All you get is a changed Display Name.  Even when you use re-name in SharePoint Designer 2010 it doesn’t change the URL – just the Display Name (Title).

I mostly found quite unhelpful suggestions when I Googled this issue.

 

The Solution That Does Work
I finally found a solution that worked for me and it’s remarkably old-school.  One of the many sites posting the unhelpful re-name strategy had a gem hidden in it from a user named Todor Kisov.

His response was not marked as a solution but it worked for me, unlike the answer that was marked as a solution.  Go figure.

In a nutshell, here is what worked:

  1. Inside the Document Libary, select the Library tab
  2. Select Open with Explorer  
  3. Now in Windows Explorer, navigate up once to the site level
  4. You will now see a listing of the site contents, including the various document libraries as well as a folder called Lists
  5. Find the document library or list you wish to rename
  6. Right-click on it, and simply select Rename from the menu

 

Problem solved!

Posted in SharePoint 2010 by Doug.

SharePoint Constantly Prompts for Credentials

Some of our users are prompted for their username and password every time they visit sites in SharePoint.  It’s especially annoying if they’re logged in and attempt to navigate to another site, where they are prompted again and again.  The question has come up: “Why can’t SharePoint remember my username and password from one minute to the next?!?”

The answer is: it’s not SharePoint.  The culprit may be your browser settings and if so, the solution is two simple settings changes.  But first, an explanation.

If you’re using Windows authentication then this should be simple.  Your users have already “authenticated” into Windows when they logged into their machines.  If these same credentials are used for SharePoint, we simply need to tell your browser to pass along these credentials to SharePoint.  Otherwise, your browser will prompt for them each time.  Sound familiar?

I’m going to provide the settings for Internet Explorer in this article.  This solution should work for Chrome and Firefox as well since the Internet Settings apply to all three.  I’ll provide a general description of the solution here below.  Detailed instructions will follow these general instructions at the end (via a link).

Step 1
I recommend listing your SharePoint top-level domain in the Local Intranet zone in IE.  Some folks like to put their SharePoint domain in Trusted Sites and that will work too.  I’ve heard arguments on both sides so pick your poison.  But at least pick one of them.  Like I said, I recommend the Local Intranet zone.

Step 2
Once you’ve added your SharePoint top-level domain to the Local Intranet zone, update the zone Security Settings to automatically pass the user’s Windows credentials on to sites in this zone.

Microsoft has really pulled a fast one here.  The zone-specific Security Settings are accessed by clicking a button mislabeled as “Custom level…” for some reason.  See screenshot below.  The window that comes up, however, is correctly labeled Security Settings and specifies the zone selected.

Internet-Options-Custom-Level

Detailed instructions for this process are available as Steps 4 and 5 on this article previously published here on this site.

I hope this helps your users break free from the prompts!

Posted in SharePoint 2010 by Doug.

Send Email Alerts only on Business Days using SharePoint Timer Jobs with dynamic email templates

There is a very common business requirement where you need to send an email alert to customers after a particular number of days but only on business days. Business days means only Monday through Friday in most countries. It’s a bit tricky but can be accomplished with ease by following the example given below.

Requirements:
The user gets an alert after 21 days stating that his action is needed on something, say for example a credit card bill payment before it becomes over due.

Logic:
This is simple: Add 21 days from the date in which he made a payment and check whether today is the 21st day.

If “Yes” fire an alert, else do nothing.

DateTime dueDate = actualPaymentMadeDate.AddDays(21);

DateTime todayDateTime = DateTime.Now;

                        if (dueDate == todayDateTime )
                        {
                            Console.WriteLine("It is past 21 days");
                        }
                        else
                        {
                          Console.WriteLine("It is still not 21 days");
                        }

Now the second part is that you need to temporarily disable his card if he does not make a payment after 21 days.  However, this alert should be sent only on the 3rd business day after 21 days.

Logic:
If the difference is greater than 21 days, then add 21 days to the date in which the payment was made, then find out which day does this date fall under, i.e the day of the date when 21 days are added to the date in which the credit card payment was made. Then write a case statement which would add “n” number of days based on which day the 21st date is like the one shown below. Now for example if the day is Monday then 3 days are added to get the next 3rd business day and if today is that day, then an alert is sent by the timer job.


else if (differenceInDays > 22)
                        {
                            //add 21 days to the date in which the card was issues.
                            DateTime addedPaymentDate = actualPaymentDate.AddDays(21);
                            DateTime finalBusinessday;

                            //find out the day of this date.
                            string currentDay = addedPaymentDate.DayOfWeek.ToString();

                            //write a case if the day belongs to one of the cases, then what happens,
                            //like monday = add 3 days, tuesday add 3 days, wednesday 5 days,
                            string caseSwitch = currentDay;
                            switch (caseSwitch)
                            {
                                case "Monday":
                                    finalBusinessday = addedPaymentDate.AddDays(3);
                                    Console.WriteLine("Monday");
                                    break;
                                case "Tuesday":
                                    finalBusinessday = addedPaymentDate.AddDays(3);
                                    Console.WriteLine("Tuesday");
                                    break;
                                case "Wednesday":
                                    finalBusinessday = addedPaymentDate.AddDays(5);
                                    Console.WriteLine("Wednesday");
                                    break;
                                case "Thursday":
                                    finalBusinessday = addedPaymentDate.AddDays(5);
                                    Console.WriteLine("Thursday");
                                    break;
                                case "Friday":
                                    finalBusinessday = addedPaymentDate.AddDays(5);
                                    Console.WriteLine("Friday");
                                    break;
                                case "Saturday":
                                    finalBusinessday = addedPaymentDate.AddDays(4);
                                    Console.WriteLine("Saturday");
                                    break;
                                default:
                                    finalBusinessday = addedCardIssueDate.AddDays(3);
                                    Console.WriteLine("Sunday");
                                    break;
                            }

                            //get to find out the date after adding the days.
                            //if today is == to the obtained date in the previous step send email

                            var dateoffinalBusinessday = finalBusinessday.ToShortDateString();
                            string dateOftoday = todayDateTime.ToShortDateString();

                            if (dateoffinalBusinessday == dateOftoday)
                            {
                                DynamicAlerter(1, tcardHolderEmail, tcardNumber,
                                    DateTime.Now.ToString(), siteObj);
                            }
                        }

please see screenshots below:

Open Visual Studio 2010 and select New, Project… from the file menu

 

New timer Job

New timer Job

Select an empty SharePoint project and name it accordingly.

New timer Job

Once the project is created, then add a .cs file to it. Ensure that your cs file is named accordingly like
CompanyName_ModuleName_Urgent_Timer and inherits from SPJobDefinition class.

Farm solution

inheritence

Method explanations:

The Execute(Guid targetInstanceId) method calls the main method which is UrgentAction_SuspensionAlert(currentTCardList, site) with the list and the site as input parameters.

The UrgentAction_SuspensionAlert(SPList eventsListObj, SPSite siteObj) method takes the list, and site objects as input parameters and does the actual logic of finding

1: If the payment has crossed 21 days then is the 21st day today: then email is fired
2: If the payment has crossed 21 days then find the 3rd business day after the 21st day and if that day is today: fire an email alert to the user

The DynamicAlerter(int stage, string cardHolderEmail,
string accountNumber, string deadlineDate, SPSite site) gets the following as input parameters

stage : is it trying to go for an email alert in the first case > 21 days due payment
or the second case : 3rd business day
Account number : Credit card account number
dead line date : the date in which the payment should have been made
site: spsite object

The string[] BodyTemplateEmail(SPList list,
string retrievalquery) takes in list and CAML query input values and returns a string array that will contain the dynamic email body from a configurable list

The CardAudiListtEmailSave(SPWeb emlwebObj, subject, string bodyContent,
string recipient) take input parameters like subject, the replaced dynamic body content and the credit card holder email ID and saves all this data for audit purposes into a SharePoint list for future reference.

Below is the full code section.


namespace CompanyName_ModuleName_Urgent_Timer
{
    public class CompanyName_ModuleName_Urgent_Timer : SPJobDefinition
    {

        #region constant declaration
        public const string ISSUEDON = "IssuedOn";
        public const string CARDHOLDEREMAIL = "CardholderEmail";
        public const string CARDHOLDERNAME = "Title";
        public const string CARDNUMBER = "CardNumber";
        public const string CARDDEADLINEDATE = "DueAmountOnTermination";
        public const string JobName = "CompanyName_ModuleName_Urgent_Timer";
        public const int sitecollectionIndexPosition = 3;
        public const string listName = "Credit Card Data";

        #endregion

        public CompanyName_ModuleName_Urgent_Timer()
            : base()
        {

        }
        public CompanyName_ModuleName_Urgent_Timer(SPWebApplication webApp) :
            base(JobName, webApp, null, SPJobLockType.Job)
        {
            Title = JobName;
        }
/// <summary>
        /// The main execute method that calls the method urgent actions timer
        /// </summary>
        /// <param name="targetInstanceId"></param>
 public override void Execute(Guid targetInstanceId)
        {

            try
            {
                // Execute the timer job logic.
                SPWebApplication webApp = this.Parent as SPWebApplication;
                SPSite site = webApp.Sites[sitecollectionIndexPosition];

                using (SPWeb web = site.OpenWeb())
                {
                    SPList currentList = web.Lists[listName];
                    UrgentAction_SuspensionAlert(currentList, site);
                }

            }
            catch (Exception ex)
            {
                SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory
                    ("Urgent Actions Timer job Failure",
                    TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected,
                    "Failed in sending email alerts for more than 21 day pending jobs: "
                    + ex.Message, ex.StackTrace);
            }
        }
 /// <summary>
        /// This method  finds the difference between the date issues and current date
        /// then sends the appropriate email alert. If it is greater than 21 days urgent action email is sent
        /// if it is greater than 22 days, the suspension email is sent
        /// </summary>
        /// <param name="eventsListObj"></param>
        /// <param name="siteObj"></param>
private static void UrgentAction_SuspensionAlert(SPList eventsListObj, SPSite siteObj)
        {
            try
            {
                foreach (SPListItem eventListItem in eventsListObj.Items)
                {
                    DateTime todayDateTime = DateTime.Now;
                    if (eventListItem[ISSUEDON] != null)
                    {
                        string cardissuanceDate = eventListItem[ISSUEDON].ToString();
                        string cardNumber = eventListItem[CARDNUMBER].ToString();
                        string cardDeadlineDate = eventListItem[TCARDDEADLINEDATE].ToString();
                        string cardHolderEmail = eventListItem[CARDHOLDEREMAIL].ToString();

                        DateTime actualCardIssueDate = Convert.ToDateTime(cardissuanceDate);

                        string itemUrl = eventListItem.ParentList.ParentWeb.Site.MakeFullUrl
                        (eventListItem.ParentList.DefaultDisplayFormUrl + "?ID=" + eventListItem.ID);

                        TimeSpan timeDifference;
                        if (todayDateTime > actualCardIssueDate)
                        {
                            timeDifference = todayDateTime - actualCardIssueDate;
                        }
                        else
                        {
                            timeDifference = actualCardIssueDate - todayDateTime;
                        }

                        double differenceInDays = timeDifference.TotalDays;
                        if ((differenceInDays > 21) && (differenceInDays < 22))
                        {
                            DateTime addedCardIssueDateMain = actualCardIssueDate.AddDays(21);
                            DynamicAlerter(0, tcardHolderEmail, tcardNumber,
                                addedCardIssueDateMain.ToString(), siteObj);
                        }
                        else if (differenceInDays > 22)
                        {
                            //add 21 days to the date in which the card was issues.
                            DateTime addedCardIssueDate = actualCardIssueDate.AddDays(21);
                            DateTime finalBusinessday;

                            //find out the day of this date.
                            string currentDay = addedCardIssueDate.DayOfWeek.ToString();

                            //write a case if the day belongs to one of the cases, then what happens,
                            //like monday = add 3 days, tuesday add 3 days, wednesday 5 days,
                            string caseSwitch = currentDay;
                            switch (caseSwitch)
                            {
                                case "Monday":
                                    finalBusinessday = addedCardIssueDate.AddDays(3);
                                    Console.WriteLine("Monday");
                                    break;
                                case "Tuesday":
                                    finalBusinessday = addedCardIssueDate.AddDays(3);
                                    Console.WriteLine("Tuesday");
                                    break;
                                case "Wednesday":
                                    finalBusinessday = addedCardIssueDate.AddDays(5);
                                    Console.WriteLine("Wednesday");
                                    break;
                                case "Thursday":
                                    finalBusinessday = addedCardIssueDate.AddDays(5);
                                    Console.WriteLine("Thursday");
                                    break;
                                case "Friday":
                                    finalBusinessday = addedCardIssueDate.AddDays(5);
                                    Console.WriteLine("Friday");
                                    break;
                                case "Saturday":
                                    finalBusinessday = addedCardIssueDate.AddDays(4);
                                    Console.WriteLine("Saturday");
                                    break;
                                default:
                                    finalBusinessday = addedCardIssueDate.AddDays(3);
                                    Console.WriteLine("Sunday");
                                    break;
                            }

                            //get to find out the date after adding the days.
                            //if today is == to the obtained date in the previous step send email

                            var dateoffinalBusinessday = finalBusinessday.ToShortDateString();
                            string dateOftoday = todayDateTime.ToShortDateString();

                            if (dateoffinalBusinessday == dateOftoday)
                            {
                                DynamicAlerter(1, tcardHolderEmail, tcardNumber,
                                    DateTime.Now.ToString(), siteObj);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory
                    ("Credit Card Timer job Failure",
                    TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected,
                    "Failed in finding the difference of days logic: "
                    + ex.Message, ex.StackTrace);
            }

        }

 /// <summary>
        /// This method is for using a Dynamic Replaceable Email Body for the alerts sent & content retrieval method
        /// </summary>
        /// <param name="properties"></param>
        /// <param name="stage"></param>
private static void DynamicAlerter(int stage, string cardHolderEmail,
            string accountNumber, string deadlineDate, SPSite site)
        {
            try
            {
                DateTime today = DateTime.Now;
                DateTime deadline = today.AddDays(21);
                string[] emailProperties = new string[2];
                using (SPWeb web = site.OpenWeb())
                {
                    string formattedValue = string.Empty;
                    SPList list = web.Lists["CardEmailBodyTemplates"];
                    if (stage == 0)
                    {
                        emailProperties = BodyTemplateEmail(list, "URGENT - ACTION REQUIRED");
                        emailProperties[0] = emailProperties[0].Replace("{cardNumber}", accountNumber);
                        emailProperties[1] = emailProperties[1].Replace("{carddeadline}", deadline.ToString());
                    }
                    else
                    {
                        emailProperties = BodyTemplateEmail(list, "URGENT - TRAVEL CARD SUSPENSION");
                        emailProperties[0] = emailProperties[0].Replace("{cardNumber}", accountNumber);
                        emailProperties[1] = emailProperties[1].Replace("{carddeadline}", deadline.ToString());
                    }
                    SPUtility.SendEmail(web, true, false, cardHolderEmail, emailProperties[0], emailProperties[1]);
                    CardAudiListtEmailSave(web, emailProperties[0], emailProperties[1], cardHolderEmail);
                }
            }
            catch (Exception ex)
            {
                SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("Send Email",
             TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected,
             "Error in DynamicAlerter Method" +
             "for Card item event receivers: " + ex.Message, ex.StackTrace);

            }
        }
 /// <summary>
        /// Dynamic email Template body builder method
        /// </summary>
        /// <param name="list"></param>
        /// <param name="retrievalquery"></param>
        /// <param name="stage"></param>
        /// <returns></returns>
private static string[] BodyTemplateEmail(SPList list,
         string retrievalquery)
        {

            string[] dynamicEmailValues = new string[2];
            SPQuery query = new SPQuery();
            query.RowLimit = 10;
            query.Query = "<Where><Eq><FieldRef Name='Title' />" +
                "<Value Type='Text'>" + retrievalquery + "</Value></Eq></Where>";

            SPListItemCollection spItemColl = list.GetItems(query);
            if (spItemColl.Count > 0)
            {
                foreach (SPListItem item in spItemColl)
                {
                    dynamicEmailValues[0] = item["EmailSubject"].ToString();
                    dynamicEmailValues[1] = item["EmailMessageBody"].ToString();
                }
            }

            return dynamicEmailValues;

        }

 /// <summary>
        /// This method writes to the Card audit list the details of the every email sent
        /// </summary>
        /// <param name="emlwebObj"></param>
        /// <param name="subject"></param>
        /// <param name="bodyContent"></param>
        /// <param name="recipient"></param>
private static void CardAudiListtEmailSave(SPWeb emlwebObj,
            string subject, string bodyContent,
           string recipient)
        {
            try
            {
                SPList listObj = emlwebObj.Lists["Card Audit"];
                SPListItem itemObj = listObj.Items.Add();
                itemObj["Title"] = subject;
                itemObj["From"] = "CreditCardAlerts@guru.com";
                itemObj["To"] = recipient;
                itemObj["DateSent"] = DateTime.Now;
                itemObj["MessageBody"] = bodyContent;
                itemObj.Update();
            }

            catch (Exception ex)
            {

                SPDiagnosticsService.Local.WriteTrace(0,
                    new SPDiagnosticsCategory("List Timer job Failure",
                    TraceSeverity.Unexpected, EventSeverity.Error),
                    TraceSeverity.Unexpected,
                    "Failed in writing the email details to cardaudit list for past due date payments :"
                    + ex.Message, ex.StackTrace);

            }
        }

    }
}

I hope this scenario has been helpful.

Happy coding!
Guru V

Posted in SharePoint 2010 by Guru Venkataraman.

Access Denied for users with proper permissions

If you have encountered an Access Denied message in SharePoint although you have proper permissions to the site, page, list, or library, then it could be one of several reasons. Hopefully one of these several fixes will work for you.

Access Denied

Fix #1:

For the site or sub-site with the Publishing feature enabled, ensure all users have read access to the master page library.
Site Actions > Site Settings > Master pages and page layouts > Library tab > Library Permissions > Grant Permissions button. Add Authenticated Users with Read permission level as in the screenshot below.

Add-All-Authenticated-Users-to-SharePoint

Fix #2:

If you experience Access Denied on file upload or download, it may be your anti-virus settings.

The following folders may have to be excluded from antivirus scanning when you use file-level antivirus software in SharePoint. If these folders are not excluded, you may see unexpected behavior. For example, you may receive “access denied” error messages when files are uploaded.

  • Drive:\Program Files\Microsoft Office Servers\14.0\Data
    (This folder is used for the indexing process. If the Index files are configured to be located in a different folder, you also have to exclude that location.)
  • Drive:\Program Files\Microsoft Office Servers\14.0\Logs
  • Drive:\Program Files\Microsoft Office Servers\14.0\Bin
  • Drive:\Program Files\Microsoft Office Servers\14.0\Synchronization Service

Reference Links:

http://support.microsoft.com/kb/952167

http://www.symantec.com/business/support/index?page=content&id=TECH141492

http://blogs.msdn.com/b/chaun/archive/2013/08/01/do-we-really-need-to-set-antivirus-exclusions-up-for-our-sharepoint-servers.aspx

Thanks to Ripon Kundu for contributing to this section.

Fix #3:

You may also experience an Access Denied while uploading a file to a site that utilizes the Content Organizer feature  *and*  the site’s Drop Off Library has unique permissions.

The resolution is to make sure that users have Contribute access to a site’s Drop Off Library” per this article.

This solution, you may notice, bears a strong resemblance to Fix #1.  The takeaway here is to really mind your permissions.

Posted in SharePoint 2010 SharePoint 2013 by Doug.

How to check all checkboxes by default in a new SharePoint list form

Sometimes we are tasked with weird requirements and we go halfway around the world to get them done. Remember one thing: there is quite often a simple shortcut available. I have realized that JavaScript and JQuery are so powerful that they can make these shortcuts achievable for us in an amazingly small amount of time.

Our requirements were simple. They wanted a SharePoint list that has numerous checkboxes on the new item form and they wanted all the boxes to be selected on form load by default. The clients would then de-select a few based on what they wanted.

SharePoint allows only one check box to be selected by default on form load.  To achieve our goal, I wrote one single line of code that did the trick… eager to know how?  What are we waiting for… Lets dive!!!!

 

Step 1: Go to your list and add a choice control, as shown below

checkbox 1

Step 2: Provide options as shown below and observe that only one option can be selected as default. SharePoint does not allow you or give you the power to select multiple options by default on load in the choice menu although it still give you multi-select option manually.

checkbox 2

Step 3: Go back to the list and click on the new item and you would see the newform.aspx opened with only the first option that you selected to be checked by default on form load.

checkbox 3

step 4: Open notepad and put the following code into it and save this file with whatever name you want to on your desktop. Remember it should be a text file. In my case I named it multicheckerjqueryfile.txt for an example’s sake as shown below

<script src="http://ServerName/sites/SiteName/SiteAssets/jquery-1.10.2.min.js"></script>
<script src="http://ServerName/sites/SiteName/SiteAssets/jquery.SPServices-0.7.2.min.js"></script>
<script src="http://ServerName/sites/SiteName/SiteAssets/jquery.SPServices-0.7.2.js"></script>
<script type="text/javascript">
$(document).ready(function() {
//Get the current user
$("INPUT[type='checkbox']").attr('checked',true);
});
</script>

Logically what we are doing is getting the choice control through its html disguise and setting it “checked” property attribute to TRUE.

checkbox 5

step 5: Now upload this file to your site assets library as shown below along with the three other supportive  jquery library files. You can also download the latest version of  these files from the internet. For the rest of you who want it quickly, please pick it from our site. P.S: these are not the latest but ones sufficient enough to get you through this task.

checkbox 6

 

I have added these files that I used during my development. You can also download the latest files from the following site (http://jquery.com/download/)

jquery.SPServices-0.7.2

jquery-1.10.2.min

jquery.SPServices-0.7.2.min

checkbox 8

 Step 6: Once all the upload is done, type the url of the list and append the newform.aspx with it with some additional parameters. Once done, you should see the new form.aspx page, in editable state as shown below.

So your url should be like

http://servername:port number/Lists/list name/newform.aspx?PageView=Shared&ToolPaneView=2

checkbox 4

Step 7: Click on the “Add a Webpart” link and add a content editor web part. In the “Content Link” field, provide the location where you uploaded the text file that contains the logic. in my case it was

http://servername/siteassets/multicheckerjquery.txt as shown below

 

checkbox 7

Step 8: Click on the Apply button and then the OK button. Now refresh the page and you will see all the check boxes checked by default when the page is opened as shown below.

 

checkbox 9

Happy Coding 

Guru !!!

 

Posted in SharePoint 2010 by Guru Venkataraman.

Change hyperlink field value from http:// to file:// on a form

On list forms, SharePoint offers a lot of fields Out-of-the-Box plus you are free to create your own custom fields to accommodate requirements and customer data types.

Among the OOTB fields is the hyperlink field which requires either http or https.  Sometimes you want a link to a file somewhere (such as a shared drive) for which there is a UNC path but no http path.  We will use JQuery to convince SharePoint to accept UNC path names in the hyperlink field.  Lets jump into the topic right away.

Step 1: Add a new hyperlink column to your list. Name the hyperlink field as “testhyperlinkfield” or name it whatever you are comfortable with.

Field Name giving

Step 2: Download the necessary supportive Jquery library files from the internet and upload them to your Site Assets folder.

I have addded the files that i had used during my development. You can also download the latest files from the following site (http://jquery.com/download/)

jquery.SPServices-0.7.2

jquery-1.10.2.min

jquery.SPServices-0.7.2.min

 

Step 3: Open notepad and add the below lines of code and save the file as “hyperlinkrootchanger.txt

<script src="http://ServerName/sites/SiteName/SiteAssets/jquery-1.10.2.min.js"></script>
<script src="http://ServerName/sites/SiteName/SiteAssets/jquery.SPServices-0.7.2.min.js"></script>
<script src="http://ServerName/sites/SiteName/SiteAssets/jquery.SPServices-0.7.2.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("INPUT[title='testhyperlinkfield']").val('file://');
});
</script>

P.S. Remember to change servername and urls according to your server details

Step 4: Now upload this text file to your SiteAssets library. Copy the url of the location where the file is saved.

Step 5: Now navigate to your list and type the following in the url bar.http://Server Name/Lists/List Name/newform.aspx?PageView=Shared&ToolPaneView=2 the page that opens will enable you to add a web part. Add a content editor web part to this page. Now edit this webpart’s properties where in the “Content Link”  property give the location of where you saved the java script text file initially in the site assets library. once this is done, click on Apply and Ok button.
 
content link property
Now open the newform.aspx or try to open a new list item page and you should see the changes like shown below:final hyoper link root value changer

Happy Jquery scripting !!

Guru

Posted in SharePoint 2010 by Guru Venkataraman.