in

SharePoint Blogs

The Best Place for SharePoint-related Blogs

JoeD

  • Using SharePoint Surveys for a Quiz - Part 2

    In Part 1, I showed how to configure a SharePoint survey to be used as a quiz.  In Part 2, I will show how to easily "grade" the quiz.  In our case, since we were using it as part of a contest, we will also see how to easily select the winner of the contest.

    After you create the survey for the quiz, but before you have users submit their responses, delete any test responses you have created so there are no responses on the survey.  Then take the survey and answer all the questions correctly (hopefully you know what the answers are supposed to be!).  This will make the first recorded response to the survey the "key" or correct answers to the quiz.  We will use this later to grade the quiz.

    Once all users have responded to the survey, it's time to do the grading.  Navigate to the survey's "overview" page.  In part 1, we renamed this page so others could not export the questions to Excel, so navigate to whatever you called the previouly named "overview.aspx" page.  In our case, we renamed it to "overview_admin.aspx".

    In the survey's toolbar, click on Actions and choose Export to Spreadsheet.  This will export the survey and all responses to Excel, with the questions as column headings and each response as a row.

    Find the column of the last question in the survey.  This is not the last column - SharePoint exports two useless columns at the end labeled Item Type and Path (I have yet to find a good use for these).  For example, my survey has 26 questions, so the last question is in column AA.

    Now, assuming the correct answers are in the first response (row 2), paste a formula like this in row 3, in the cell after the last column (the Path column):

     =SUMPRODUCT((B3:AA3=$B$2:$AA$2)*(B3:AA3<>""))

    For your survey, replace AA in the formula with the column ID of the last question in your survey.

    When you paste it in the cell, it will automatically repeat for each survey response.  You should see a number appear for each survey, indicating the number of correct responses.  As a check, the number in row 2 for this column should equal the number of questions in your survey.

    That's it! Your quiz is graded.  The name of each user responding is in column A, and their score is in the last column.

    To find the best scores, click on the drop down arrow in the new column heading and choose Sort Largest to Smallest.  The person's name in cell A3 has the highest score.  (You would also need to check for ties.)

     

  • Using SharePoint Surveys for a Quiz - Part 1

    Our company recently had a fundraising drive for a charity.  The people on the fundraising committee came up with an idea to raise some money and have a little fun - we would have a trivia contest for employees.  You would pay a small fee to enter, with the best score winning a prize, and the proceeds would go to the charity.

    I suppose there are web sites out there that can host something like this, but my immediate throught was that we could use SharePoint's survey function to do this.  And with a little customization, it can handle the job.

    Some of the requirements we had are:

    • You can only take the quiz once.
    • You can't see the questions before you take the quiz.
    • You can't go back and change your answers once you submit them.
    • You only have 10 minutes to take the quiz.
    • Prevent "cheating" as much as possible.
    • Need a way to find the best score (shown in Part 2)

    Some of these things are handled out-of-the-box by SharePoint.  Others require customizations.  Others can't be overcome 100% and require a little trust...

    If you know of other ways to do some of these things without customizations, I would love to hear about them.

    Requirement: You can only take the quiz once.

    This can be handled by setting the survey option "Allow multiple responses?" to No in the survey settings in SharePoint (set it when creating the survey or later using the link "Title, description and navigation" in the Survey Settings.

    Requirement: You can't see the questions before you take the quiz.

    This one is somewhat difficult to overcome.  It depends how secure you want things to be and how savvy your users are.

    First, in Survey Settings -> Advanced settings, set the Item-level Permissions to:

    Read access: Only their own
    Edit access: Only their own

    This prevents non-admin users from seeing the responses from any other user who has already responded to the survey.  So they won't be able to see the questions using "Show a graphical summary of responses" or "Show all responses" when clicking on the survey.  Those two links on the survey's "overview.aspx" page will only show the user's responses, and until the user has taken the survey there will be nothing to show.

    However, there is still a hole... On the "overview.aspx" page (which is the 'landing page" you see when you click on the list in "View All Site Content"), there is an option under the Actions menu for "Export to Spreadsheet".  That will create an Excel spreadsheet with the survey questions in the headings of the columns even if the user has not responded to the survey yet.  The contents of the spreadsheet will be empty, but the questions will be in the column headings. So a savvy user could use this to see the questions prior to taking the survey.

    The only way I have found to avoid this is to drop the survey as a web part on a site or web part page, and set the Toolbar Type of the web part to Summary Toolbar and change the Chrome Type to None.  Then there will be no toolbar at the top with the Actions method.  You need to change the Chrome Type to None, or users will be able to click on the header of the web part and get to the survey's landing page (overview.aspx). Point users to this site/page as the method to take the survey.

    This does not entirely solve the problem however. The user can still click on "View All Site Content" and get to the overview.aspx page from there by clicking on the link to it in the Surveys section on the viewlists.aspx page.

    One way to solve that is to hide the "View All Site Content" link.  You can do that by dropping a Content Editor Web Part (CEWP) on the page and use the Source Editor button to put this in the web part:

    <style>
    .ms-quicklaunchheader { display: none }
    </style>

    Change the Chrome Type of the CEWP to none and save it.  The "View All Site Content" link will now be gone!  (When you need to get to it, you need to add "_layouts/viewlsts.aspx" to the site's URL.

    Of course, if you have users who really know their SharePoint, they will be able to still get to the View All Site Content page (viewlsts.aspx) or the survey's overview.aspx page by finding the URL to the site or survey and changing the URL to navigate to it.

    In my company's case, we do not really have any non-admin users who know SharePoint well enough to do this, so hiding the "View All Site Content" link is sufficient for us.  But if you do have advanced SharePoint users, my recommendation is to rename overview.aspx for the survey to another name, like "overview_admin.aspx" using SPD.  Then if you wish, create a new overview.aspx page with nothing on it or some kind of message for anyone navigating to it.  Then the only way a user could get to the survey's original overview.aspx page is if the user knew the new name you gave it.  (You also need to remember it because you will need it to get the survey results.)

    There is yet another way the user would be able to see the answers without taking the survey, and that is to use the Respond link to take the survey and then click the Cancel button after reading the questions.  SharePoint doesn't record the response to the survey until the user clicks the Finish button.  So we need a way to disable or hide the Cancel buttons (there are two).

    This can be accomplished using SPD to edit the survey's NewForm.aspx page, which is the page the user sees when they respond to a survey.  Add this Javascript to the page, just after the closing </table> tag after the closing </WebPartPages:WebPartZone> tag:

    <script type="text/javascript">
    function hideCancel()
    {
        var e = document.getElementsByTagName("input");

        for(var i = 0; i < e.length; i++)
            if (e[i].type == 'button' && e[i].value == 'Cancel')
                e[i].style.visibility = "hidden";
    }
    hideCancel();
    </script>

    This code looks for all input tags that are buttons and have the value (button name) of "Cancel", and sets their visibility to hidden.  This will find both Cancel buttons and hide them, so the user now cannot cancel out of the survey once they start it. 

    There is still one more way the user can see the questions without taking the survey - if the user clicks Respond link to take the survey, then clicks the Back button or closes the browser, SharePoint does not record that the survey was taken.  So a user could click Respond, read the questions, click Back or close the browser, do some research, then take the quiz again with their new knowledge.

    This can be prevented by submitting the survey results automatically when the "onbeforeunload" event fires in Internet Explorer.  Note that this technique may not work with some browsers; some do not support this event.  But we are using IE only, so it works in our case.

    By submitting the results when "onbeforeunload" fires, clicking the back button or closing the browser will be trapped and the user won't be able to take the survey again.  We explain this in the "rules of the game" - we tell them they must finish the quiz once they start it.

    Trapping and submitting the results with "onbeforeunload" is tricky.  First, the survey form does not have a "submit" button, therefore the form "submit()" function cannot simply be called to submit the results.  We need to "click" the Finish button. In order to "click" the Finish button, we need to find it on the page.

    Second, "onbeforeunload" will fire any time the page is left, including when the user really clicks the Finish button.  If the user navigates off the page without clicking Finish, we want to display a message to let the user know that they screwed up, but we don't want that message to display when they correctly click the Finish button.  To do this, we need to insert some Javascript code to disable the onbeforeunload event (set it to null) when the Finish button is really clicked.  And there are two Finish buttons on the page, one at the top and one at the bottom.  We need to do this to both of them.

    This Javascript code will accomplish that.

    <script type="text/javascript">

    function findFinish(which)
    {
       var btn = null;
       var count = 1;
       var e = document.getElementsByTagName("input");

       for(var i = 0; i < e.length; i++)
       {
          if (e[i].type == 'button' && e[i].value == 'Finish')
          {
             if (count == which)
             {
                btn = e[i];
                break;
             }
             else
             {
                count++;
             }
          }
       }
     
       return btn;
    }
    function insertSubmitEvent()
    {
       var btn = findFinish(1);
       if (btn != null)
       {
          if (typeof btn.onclick == "function")
          {
             var oldClick = btn.onclick;
             btn.onclick = function() { window.onbeforeunload = null; oldClick(); }
          }
       }
     
       var btn2 = findFinish(2);
       if (btn2 != null)
       {
         if (typeof btn2.onclick == "function")
         {
            var oldClick = btn2.onclick;
            btn2.onclick = function() { window.onbeforeunload = null; oldClick(); }
         }
       }

    }
    function forceSubmit()
    {
       alert('Since you clicked off the page, your answers will now be recorded - you were warned!');
       var btn = findFinish(1);
       if (btn != null)
         btn.click();
    }
    insertSubmitEvent();
    window.onbeforeunload = forceSubmit;
    </script>

    This code finds both Finish buttons and inserts code in each button's "click" event to disable the "onbeforeunload" event.  This is so a "real" click of the Finish button does not execute our code.  We only want our code to execute when the user tries to leave the page in some way other than the Finish button.

    Next it sets the window's "onbeforeunload" event to our function, which tells the user that their answers are now going to be recorded since they tried to leave the page.  Then it finds the first Finish button and "clicks" it.  (The "onbeforeunload" event won't fire again because the "click" event disables it when it executes.)

    Requirement: You can't go back and change your answers once you submit them.

    I have found no way to do this in the out-of-the-box surveys in SharePoint.  At first I thought I could create a new Permission Level that gave only Add and View permission (no Edit or Delete permission).  I did this and assigned that Add-and-View permission level to the appropriate group for the survey.  But it always results in an Access Denied error when a user tries to respond to the survey.  It would not allow the users to respond to the survey unless they had Edit permission.

    That makes no sense to me - the user is adding a response - why do they need Edit permission?

    Since that was out as an option, there was only one thing I could think of - insert some Javascript code in the survey's EditForm.aspx to redirect them out of that form if they tried to change their answers after submission.

    Using SPD, I opened the survey's EditForm.aspx and after the </style> tag, I added this code:

    <script type="text/javascript">
    alert("Sorry, you cannot change your answers once you have finished the quiz.");
    window.location = "/SomeLocation/In/SharePoint";
    </script>

    All this does is display a message, then redirect somewhere else.  No editing allowed.

    Requirement: You only have 10 minutes to take the quiz.

    We want to put a time limit on the amount of time a user had to take the quiz.  This should discourage them from taking the time to "get a lifeline" by calling or asking someone else, or from firing up a laptop to look up an answer on the web.

    Of course, there is nothing built into SharePoint surveys to handle this, but it can be done with a little Javascript code insert into the survey's NewForm.aspx, which is the page the user sees when they respond to a survey.

    We can use the Javascript setTimeout() function to fire off an event after a certain amount of time. In our case, we want to fire an event after 10 minutes.  But do what?  We want to submit the survey results - but the Finish button is not a "submit" button, so we can't use the submit() function of the form.  We need to "click" the Finish button.  We can do that with some Javascript - we need to first find the Finish button, then click it.  So add this code to NewForm.aspx, just after the closing </table> tag after the closing </WebPartPages:WebPartZone> tag:

    <script type="text/javascript">

    function findFinish()
    {
        var btn = null;
        var e = document.getElementsByTagName("input");

        for(var i = 0; i < e.length; i++)
        {
            if (e[i].type == 'button' && e[i].value == 'Finish')
            {
               btn = e[i];
               break;
            }
        }
     
        return btn;
    }
    function endQuiz()
    {
        alert('Sorry, your time is up!  Your answers will now be recorded.');
     
        var btn = findFinish();
        if (btn != null)
          btn.click();
    }
    setTimeout("endQuiz()",60000*10);

    </script>

    This code will execute the endQuiz() function after 10 minutes (60000 milliseconds = 1 minute, times 10).  endQuiz() displays a message with alert(), then finds the Finish button by looking for an input tag that is a button with the value (label) "Finish", then clicks it, submitting the survey results.

    NOTE: You must be sure that no questions are set up as requiring an answer.  If you have any that are required, it will kick the form back open and wait for the user to answer the required questions, defeating the purpose of the timeout.

    Requirement: Prevent "cheating" as much as possible.

    As explained at the beginning of this post, this is a trivia quiz for fun, but there is a prize involved.  So we want to take some measures to prevent "cheating", but we aren't talking about doing the SAT's, bar exam, or medical boards here.... We just want to make it somewhat difficult, and there are a few easy steps we can take.

    First, we can prevent the user from printing the questions on the browser page (perhaps to give them to a partner in crime).  Insert this just after the closing </table> tag after the closing </WebPartPages:WebPartZone> tag:

    <style type="text/css" media="print">
    BODY { display:none; visibility:hidden; }
    </style>

    This uses CSS to set the entire body's content to hidden for the media type "print".  So if the print button in the browser is clicked, the page will be blank. (There is no way I can see to prevent the PrintScreen key from being used to capture a screen image, so there is still that option - again, we are just trying to make things difficult, it's not foolproof.)

    Second, we can disable the right-click context menu to prevent Select All and Copy, so these can't be used to copy the questions to the clipboard.  We can also capture the "SelectStart" event and short circuit it, which should stop Control-A being used to select everything on the page (to then copy with Control-C).  These measures work in Internet Explorer, but may not work with other browsers.  In our case, we use IE only.  So add this Javascript code to NewForm.aspx:

    document.body.oncontextmenu = function() {return false;}
    document.body.onselectstart = function() {return false;}

    The third and final measure we can take is to prevent users from trying to "Google" some answers.  In a way, the time limit helps with this.  If you have enough questions in the quiz and an aggressive time limit, trying to look up answers will end up taking too much time and you will have a few right answers, but many will be left unanswered.

    We can't prevent the user from opening other browser windows or tabs, but we can detect whether our survey page loses focus, meaning the user possibly tried to look something up.  It could be they were doing something innocent like reading an e-mail, but as part of our rules, we are telling the users that once they start, they must stay on that page and finish the entire quiz.  Clicking off the page will automatically submit what they have answered so far.

    The loss of focus on the page can be detected in Internet Explorer with the "onblur" event.  It's a strange name, but it's defined in the documentation as "when the object loses the input focus".  If we trap this event on the "window" object, we can tell when the current browser window loses focus, meaning the user clicked off the page and tried to do something else.  If this happens, we want to submit the current answers by "clicking" the Finish button.  This works exactly the same way as how we trapped the "onbeforeunload" event above.  Just do the same thing for "onblur".

    Summary

    If you want all of the measures described above to be taken, do the following: 

    1. Set "Allow multiple responses" to No.

    2. Set Item-level Permissions for Read and Edit to "Only their own".

    3. Put the survey on a page as a web part, and set the web part to use the Summary toolbar and Chrome Type of None.

    4. Use the Content Editor Web Part on that page to hide "View All Site Content" and/or rename the overview.aspx page for the survey.

    5. Edit the survey's EditForm.aspx page and add the Javascript given above to redirect away from it so answers cannot be changed.

    6. Add the following code to the NewForm.aspx page, after the closing </table> tag after the closing </WebPartPages:WebPartZone> tag, to time the response, prevent navigation away from the page, and prevent copying or printing:

    <style type="text/css" media="print">
    BODY { display:none; visibility:hidden; }
    </style>
    <script type="text/javascript">

    function findFinish(which)
    {
        var btn = null;
        var count = 1;
        var e = document.getElementsByTagName("input");

        for(var i = 0; i < e.length; i++)
        {
            if (e[i].type == 'button' && e[i].value == 'Finish')
            {
                if (count == which)
                {
                    btn = e[i];
                    break;
                }
                else
                {
                    count++;
                }
            }
        }

        return btn;
    }
    function hideCancel()
    {
        var e = document.getElementsByTagName("input");

        for(var i = 0; i < e.length; i++)
            if (e[i].type == 'button' && e[i].value == 'Cancel')
                e[i].style.visibility = "hidden";

    }
    function insertSubmitEvent()
    {
        var btn = findFinish(1);
        if (btn != null)
        {
            if (typeof btn.onclick == "function")
            {
                var oldClick = btn.onclick;
                btn.onclick = function() { window.onbeforeunload = null; window.onblur = null; oldClick(); }
            }
        }

        var btn2 = findFinish(2);
        if (btn2 != null)
        {
            if (typeof btn2.onclick == "function")
            {
                var oldClick = btn2.onclick;
                btn2.onclick = function() { window.onbeforeunload = null; window.onblur = null; oldClick(); }
            }
        }
    }
    function endQuiz()
    {
        alert('Sorry, your time is up! Your answers will now be recorded.');

        window.onbeforeunload = null;
        window.onblur = null;
        var btn = findFinish(1);
        if (btn != null)
            btn.click();
    }
    function forceSubmit()
    {
        alert('Since you clicked off the page, your answers will now be recorded - you were warned!');
        var btn = findFinish(1);
        if (btn != null)
            btn.click();
    }

    setTimeout("endQuiz()",60000*10);
    insertSubmitEvent();
    hideCancel();
    window.onbeforeunload = forceSubmit;
    window.onblur = forceSubmit;
    document.body.oncontextmenu = function() {return false;}
    document.body.onselectstart = function() {return false;}

    </script>

    In part 2, we will look at how to easily "grade" the quiz and find out who got the best score.

     

  • Displaying Users with Presence in XSLT Data View

    In a list, you can create a field of type "Person or Group" and set the "Show data" option to "Name (with presence)".  When the field displays the user's name, it shows the Office Communicator presence "globe" to the left of the name.

    If you use SharePoint Designer (SPD) to convert a List View to an XSLT Data View, fields that display as "Name (with presence)" do not display correctly.  Instead you see HTML tags that would display the name with the presence globe.

    You can fix this by switching the SPD view to the Code (or Split) view.  Find the XSL code that will display the name field:

    <!--PM Responsible--><TD Class="{$IDAEHOAF}"><span><xsl:value-of select="@PM_x0020_Responsible" /></span></TD>

    In the xsl:value-of tag, add disable-output-escaping="yes":

    <!--PM Responsible--><TD Class="{$IDAEHOAF}"><span><xsl:value-of disable-output-escaping="yes" select="@PM_x0020_Responsible" /></span></TD>

    SPD adds this attribute for some fields, but not all.  You need it for any field that may be rendered by Sharepoint as HTML.

    I've found that disable-output-escaping also needs to be added for lookup fields.  Values in lookup fields are rendered as hyperlinks to the list item in the lookup list.  If the value in the lookup field contains special HTML characters (such as &), they are rendered as the "escaped" representation (such as &amp;).  For example, the value "T&M" would display as "T&amp;M" unless disable-output-escaping is added.

     

    Posted Mar 17 2008, 10:04 AM by joed with 5 comment(s)
    Filed under: , ,
  • Be Careful with the BDC "hurricane" (update) button...

    When you add a Business Data Catalog (BDC) column to a custom list, in the list view column headings you will see an icon with two green circular arrows next to the BDC column - it looks a little like the symbol for a hurricane.  This is the "BDC Update" (or "refresh" button).

    You need to be very careful with this button.

    When you click this button, it updates the BDC values in your list with the latest values from the BDC for every list item.

    Why is this necessary? When you use a BDC column in a list, the BDC-related values that you pull in along with the BDC value you enter are actually stored in the list and are not "live" values from the BDC.  They are stored at the time you save the list item (create or update).  So these values can become "stale" if they change in the database behind the BDC entity. 

    For example, Let's say I add a BDC value "Vendor" to my list for vendors from my back end ERP system. I also pull in the vendor's name, address, and phone number.  I add a list item and select a vendor from the BDC.  It brings along the vendor's name, address, and phone number and copies of these values get stored in the list.

    A month later, the vendor's phone number is changed in the ERP system.  However, that list item will still show the old phone number, even though the BDC is pulling data directly from the ERP system.  It will not automatically update existing list items with the new value (but new list items will get the updated value).

    The only way these values update in the list item are (1) if you edit and save the list item or (2) use the BDC Update button in the list view heading to refresh all list items.

    But there are three potential side effects of the BDC Update button that you need to keep in mind.

    • If you have Versioning enabled on your list (or document library), clicking this button will create a new version of every item in the list, regardless of whether the BDC value(s) actually changed.  This could affect you if you attach meaning to version numbers changing.
    • If you have Content Approval enabled on your list (or document library), clicking this button will set every item back to Pending regardless of whether the BDC value(s) actually changed.  This can be a killer! 
    • If you have workflows attached to the list that automatically execute when an item changes, the workflow will execute on every item in the list, regardless of whether the BDC value(s) actually changed.

    This can potentially be very dangerous.  For example, I had a situation where we had a list of over 1000 items and Content Approval was enabled.  Someone clicked the BDC Update button and it set every item's approval back to Pending!!  Not only did this require all of the items to be approved again, we had no easy way to determine the approval status of the items before they were all reset - we couldn't just blindly approve everything since it may not have been approved prior to the refresh.

    Likewise, if your "on update" automatic workflows do something like send e-mails, create tasks, etc. you can potentially get a large number of unwanted e-mails and tasks created or other data-changing side effects.

    Unfortunately, there appears to be no way to put any type of security restrictions on this button - anyone who can update list items will be able to click it.  It does warn you first, but users may not realize what may happen.

    We really need a way to restrict or hide this button.

     

     

  • BDC does not play well with AAM

    The Business Data Catalog user interface (in BDC web parts and List View web parts) does not play well with Alternate Access Mappings (AAM) in MOSS.

    When you add a BDC column to a custom list, you can check the option to link the BDC value to the profile page.

    When you display the items in the list in a List View or in a BDC web part, the BDC value will be a hyperlink that takes you to the "profile page" for that BDC value.

    You can also drop down the context menu to the left of the BDC value to display the profile page.

    This is an example of the profile page that displays:

    Now, if you note in the above example of the profile page, the URL shows "devmoss2007", which is the actual hostname of my development SharePoint server.  I can view the profile page by either clicking on the BDC value or dropping down the BDC context menu and choosing View Profile.

    Now let's try the same thing using Alternate Access Mapping (AAM), where we associate a different name with the MOSS server.  In this case, I am going to map the name "devmoss" to "devmoss2007".  This is done in Central Administration -> Operations -> Global Configuraiton - Alternate access mappings.

    Now I will go to the same list, but use the AAM name in the URL instead of the actual hostname of the server.

    Now when I click on the BDC value represented as a hyperlink:

    Instead of presenting the "profile" page, it goes to this URL and does nothing:

    It appears that the BDC value hyperlink is supposed to go to the _layouts/ProfileRedirect.aspx page, which then redirects to the "View Profile" page.  Except it does not do the redirect when the AAM is used to access the MOSS site containing the list or BDC web part. 

    Dropping down the context menu to the left of the BDC value and choosing View Profile does work with AAM however.  So the problem is not with the BDC View Profile page, it is with the ProfileRedirect.aspx page.

     

    Posted Feb 21 2008, 09:16 AM by joed with 1 comment(s)
    Filed under: , ,
  • Break Outlook with SharePoint - Part 2

    In my last post, Break Outlook with SharePoint - Part 1, I showed how Outlook crashes when you create a SharePoint Meeting Workspace from the Scheduling view of your Outlook Calendar.

    Part 2 shows a problem we are having with Outlook 2007 and SharePoint Task Lists.  I have reproduced this problem on a few systems here on our network, with both our development and production MOSS servers.  I'm not 100% convinced that it's a real bug in Outlook 2007 because I have not done more extensive trials outside of our network.  If anyone out there tries this and reproduces the same behavior, I would like to hear about it.

    This is fairly simple to reproduce here.

    1) In SharePoint, go to some site with a Tasks list on it, where the Tasks list is configured to send e-mail when someone is assigned a task (found under Advanced Settings on the list).  Also, this Tasks list should not be connected to Outlook (that is, you should not have used the Connect to Outlook option on the list's Action menu.)

    2) Create a task and assign it to yourself.

    3) Wait for the e-mail to arrive from SharePoint.  If you are using Outlook 2007, the e-mail will have two buttons at the top of the e-mail window (or preview pane): Connect to this Task List  and  Preview this Task List  (You don't get these with Outlook 2003.)

    4) These buttons are very useful.  This allows the recipient to easily connect Outlook to the Task List so it shows on Outlook's Tasks view.  However.... when we click on the Connect to this Task List button, Outlook goes into some sort of endless Send/Receive loop

    After clicking it, on the Outlook status bar at the bottom of the window, it either shows it forever "preparing" to Send/Receive or shows the Send/Receive progress percentage rising and falling, but it never finishes.  (I let it run all weekend and it never stopped.)  CPU usage on OUTLOOK.EXE pegs around 30% - 50% forever.  If you close Outlook, the OUTLOOK.EXE process never ends - you have to kill it with Task Manager.  And when you start Outlook again, the Send/Receive starts again and pegs the CPU around 30% - 50% again. Likewise, if you just cancel the Send/Receive task within Outlook, it looks like it stops doing it, but the OUTLOOK.EXE process is still churning away at 30% - 50% CPU time.

    The only way to stop it is to go to the Tasks view in Outlook and find the Task List you thought you were connecting to, right-click on it and delete it from Outlook.  Then close Outlook and kill OUTLOOK.EXE.  When you restart Outlook, it will not try to sync the list again.

    I have found that if I go to the Task list in SharePoint and use the Connect to Outlook option on the Actions menu, that will work correctly.  But the new button available in Outlook does not work.  I've also tested with Outlook 2007 with and without SP1 (on the Office side) and neither work.  I am not running SP1 on the MOSS side.

    At least this does not work here - I'd like to hear whether or not it works for you.

     

  • Break Outlook with SharePoint - Part 1

    There is a bug with creating SharePoint Meeting Workspaces in Outlook that crashes Outlook hard.  Interestingly, this bug is in both Outlook 2003 and Outlook 2007.

    Here's how you can see it happen.  Open Outlook and switch to the Calendar.  Right-click on a time and choose New Meeting Request.

    In the New Meeting window, switch to the Scheduling view.

    Now click Meeting Workspace.

    If necessary, use Change Settings and select a SharePoint site.

    Then click the Create button to create a new Meeting Workspace.

    The progress bar will pulse for a short while, then Outlook bombs with an exception.

    I've tried this on multiple PC's with Outlook 2003 and 2007 and Outlook always crashes.  It works when you create the Meeting Workspace from the Appointment view, but crashes when it is created from the Scheduling view.

    So the workaround is to be sure to create the workspace from the Appointment view - but this is difficult to explain to end users because they often use the Scheduling view and will want to do it from there.

    I posted something about this in the MS managed newsgroups and I was told that this was scheduled to be fixed in Office 2007 SP1, but was pulled because the fix was "non-trivial".  (I suppose we are only to expect "trivial" things will be fixed....)

    Hopefully, we'll see a fix for this.... someday.

    Next, I'll show a different way Outlook gets hosed in conjunction with SharePoint - at least it does for me...

     

  • Avoid using hyphens in site column names!

    There appears to be a bug in MOSS 2007 when you use site columns with hyphens in the name of calculated fields.

    This only seems to occur with site columns, not in custom list columns (created in the list, not from site columns).

    Here is an example - I have a custom list with a column named Test-Field (defined as Number, although it doesn't matter).  Then I create another column named DoubleIt, defined as [Test-Field]*2.

    Then I edit the properties of the DoubleIt field and it shows me my original formula: =[Test-Field]*2.  Looks good.

    Now instead, I want to create Site Columns.  I create a site column named Test-SiteCol (again defined as Number, but doesn't matter).  Then I create another site column named SiteDoubleIt, defined as [Test-SiteCol]*2.

    Then I edit the properties of my new SiteDoubleIt site column that I just created (above) and it shows the formula: =#NAME?-#NAME?*2  !!!

    Yikes!  It strips out the [ ] delimiters and appears to view the hyphen as a minus operator and thinks each side of the hyphen is an invalid column name reference.

    So... don't use hyphens in site column names if you plan on ever using them in calculated columns.

     

  • Display a "New!" indicator in the Content Query Web Part

    I am using the Content Query Web Part (CQWP) to display news items from news subsites.  There are a few capabilities missing from the CQWP that were present in the old SharePoint 2003 News web part.  One of them is the display of the "New!" indicator next to items recently added.

    You can get the CQWP to dipslay this indicator by editing the style templates for the web part.

    To do this, you will need to use SharePoint Designer (SPD).  In SPD, open your top level site and expand Style Library, then XSL Style Sheets.  Look for ItemStyle.xsl.

    ItemStyle.xsl holds the XSL templates that the CQWP uses to render data.  Before making changes, it's probably a good idea to make a copy of it by right-clicking on it and using Copy, then Paste.  If you screw up your ItemStyle.xsl file, you may get errors in any CQWP throughout your sites.

    Double-click on ItemStyle.xsl to edit it and choose to check it out.

    ItemStyle.xsl contains a series of templates.  Each template corresponds to an Item Style in the drop down in the CQWP properties.

    For example, the in the out-of-the-box ItemStyle.xsl, the first template:

    <xsl:template name="Default" match="*" mode="itemstyle">

    corresponds to the "Image on left" style in the Item Style drop down in the CQWP.  The next template:

    <xsl:template name="NoImage" match="Row[@Style='NoImage']" mode="itemstyle">

    corresponds to the "Title and description" style.

    You can either change one of the standard item styles or you can create a new style.  You may want to create a new style if you only want the CQWP to display the "New!" indicator when you choose (by selecting your new style).  If you change one of the standard templates, it will affect all of the CQWP's thoughout the site collection.

    To create a new template, highlight and copy one of the existing templates, then paste it back into the file.  Then change the template name and match attributes to give it a unique name.  When you check in the ItemStyle.xsl file, you will see your new style as an option in the CQWP's Item Style drop down list.

    Let's say we want to change the "Title and description" style so it displays the "New!" indicator anywhere it is used.  The template name for this style is "NoImage".

    The first thing we need to do is figure out when to display it.  We could use some fancy XSL to compare the Created Date of the item to the current date and do some date math to see if it has been created within (say) the last 24 hours.

    But this is not necessary - SharePoint will do this for us!

    SharePoint comes with an XSLT extension object that is normally used in Data View Web Parts (a.k.a. Data Form Web Parts).  But we can use those extensions in our ItemStyle.xsl also.

    The functions in the XSLT extension object are described here.

    The function we can use is ddwrt:IfNew().  When passed a date/time, it will return true if the date/time is less than two days old.

    In order to use the extension object functions, we need to add the namespace to the ItemStyle.xsl file.  At the top of the file, it declares a number of namespaces, such as:

      xmlns:x="http://www.w3.org/2001/XMLSchema"
      xmlns:d="
    http://schemas.microsoft.com/sharepoint/dsp"
      xmlns:cmswrt="
    http://schemas.microsoft.com/WebParts/v3/Publishing/runtime"
      xmlns:xsl="
    http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"

    Add the "ddwrt" namespace in this mix:

      xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"

    Now we need to add some code to the template so it displays the "New!" indicator, which is a GIF found in the file "_layouts/1033/images/new.gif" (this may have a different location for languages other than English).

    Since we are changing the "NoImage" style, look for the start of that template:

        <xsl:template name="NoImage" match="Row[@Style='NoImage']" mode="itemstyle">

    Find the section of the template that generates the anchor tag (<a>) for the link to the item and displays the description:

            <div id="linkitem" class="item link-item">
                <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
                <a href="{$SafeLinkUrl}" mce_href="{$SafeLinkUrl}" target="{$LinkTarget}" title="
    {@LinkToolTip}">
                    <xsl:value-of select="$MyDisplayTitle"/>
                </a>
                <div class="description">
                    <xsl:value-of select="@Description" />
                </div>
            </div>

    We want to put the "New!" indicator just after the title of the item.  So change this section so it reads (new part in bold):

            <div id="linkitem" class="item link-item">
                <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
                <a href="{$SafeLinkUrl}" mce_href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}">
                    <xsl:value-of select="$MyDisplayTitle"/>
                </a>
                <xsl:if test="ddwrt:IfNew(string(@Created))">
                    <img src="/_layouts/1033/images/new.gif" alt="New" />
                </xsl:if>
                <div class="description">
                    <xsl:value-of select="@Description" />
                </div>
            </div>

    Save the file, then check it in.  Now anywhere you use the CQWP with the "Title and description" style, it will display a "New!" indicator if the item was added within the last two days.

     

  • SharePoint 2008 Conference Session Details Available!

    Session details for the SharePoint 2008 Conference in Seattle on March 3-6 are now available!

    For each track, you can "vote" on each session so they can plan room size and scheduling.

    I registered for this several months ago (got the early bird rate) without knowing much about the content.  So I've been patiently waiting (and waiting) for some details to be released.  Then they sprung the Office Developer's Conference in San Jose in Feb. after I already registered for the Seattle conference.  But I stuck with the Seattle conference.  I'm really looking forward to it.

     


Need SharePoint Training? Attend a SharePoint Bootcamp!

Posts (c) their respective authors. Everything else (c) 2007 SharePoint Experts