Joe's profileMack Twenty-four SevenPhotosBlogLists Tools Help

Blog


    May 14

    How to Move a SharePoint Site

    I had occasion to move a SharePoint site (technically, it was a sub site) from one location to another today.  I am sure that there are several other folks that have put similar posts to this out in the blogosphere, but for those regular visitors to The Mack Page, I thought I would give you something small to put in your kit bag.

    Scenario:  You need to move a SharePoint site from one place to another.  For the purposes of this exercise, I am moving a site titled SharePoint Training, with a URL of http://wss.tpg.local/IT_Team/SPTng from the “IT_Team” site to the “Training” centralized site, which is located at the same level as the IT team site.

    Tool:  The quickest and easiest way to accomplish this task is to use the STSADM tool, specifically the export and import operations.

    Steps:  Enough lead-in B.S.  This is a simple one, so let’s get right to it.

    1.  Create a blank site at the destination.  For this example, I did the following:

    a.  Navigate to the Training site

    b.  Click Site Actions

    c.  Select Create

    d.  Select Sites and Workspaces under the Web Pages column

    e.  Type a Title (“SharePoint Training”)

    f.  Type the new site’s URL (“http://wss.tpg.local/Training/SPTng”)

    g.  Select the Blank Site template under the Collaboration tab

    h.  Click the Create button

    2.  Logon to a server in your farm as a user with the appropriate permissions.  Since both the source and destination of this site are under the same site collection, I logged on as a member of the Site Collection Administrators group.

    3.  Open a command prompt and browse to the “BIN” folder under the “12 HIVE”.  For default installations, it is found here:  C:\Program Files\Common Files\Microsoft Shared\web server extensions\BIN.

    NOTE:  If you have not already done so, it is a good idea to set up an Environment Variable on the servers in your farm that you can use to navigate directly to the “12 HIVE”.  I usually set up a variable named simply “12” and map it to “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12”.  After you create the variable, you need only type “cd %12%”  from the command line to go straight to the hive.

    4.  Run the export using STSADM.  I almost always use the –includeusersecurity parameter when I do an export/import operation to preserve the user and group security settings for the site.  The command I used for this particular scenario looked like this: 

    stsadm –o export –url http://wss.tpg.local/IT_Team/SPTng –filename E:\MOSS_Staging\SPTng_Export.cmp –includeusersecurity

    5.  Navigate to the location where you saved the export file and make sure that it is there.  If interested, you can also explore the log file there as well.  It should be pretty easy to identify, as it has the format:  <<exported file name>>.export.log.  For my example, it was named:  SPTng_Export.cmp.export.log

    6.  Run the import using STSADM.  Just like when exporting, I make it standard practice to include user security.  The import command I used for this scenario looked like this: 

    stsadm –o import –url http://wss.tpg.local/Training/SPTng –filename E:\MOSS_Staging\SPTng_Export.cmp –includeusersecurity

    7.  That’s it.  You are done.  As you would expect, the import operation will put a log file in the same location as the export log file, and it will also be very intuitively named.

    If you have any issues along the way, you should be able to see what is happening in the command line window (as long as you do not use the –quiet parameter), as well as the log files.

    For more information about the parameters available, you can simply type stsadm –o <<operation name>> (e.g. stsadm –o export) with no parameters.  Alternatively, you can check out the stsadm page on Microsoft TechNet.

    February 11

    Implicit Documents – Knowledge Management Zen with Microsoft (Step 0 of 10)

    This the first of several related posts I am going to use to start exploring a concept I have had for some time – implicit documents.  Without getting too far down in the weeds yet regarding definitions (wait for Step 1 later this week), let’s just say that an implicit document represents the concept of a completely and totally virtual document…that is to say, a document made up entirely of a series of references to other objects within a corporate knowledge management structure, such as boiler plate text, graphs, charts, logos, etc.  Also in Step 1, a quick tour of how I arrived at the term “Implicit Document”, and how it differs from other similar terms you may have heard, such as “Virtual Document” and “Compound Document”. 

    For those of you that are interested, here is the working outline for the steps I will hopefully conquer as I progress through this series.  Once a future step becomes active, I will replace the bulleted text below with a link to the appropriate article for that step.

    • Step 0:  Welcome and Outline
    • Step 1:  Setting the Table – Background Information, Technology Levelsetting and Real-world Applications
    • Step 2:  High-Level Solution Design
    • Step 3:  Development Environment Set-Up
    • Step 4:  Data Warehouse and Dimensional Model
    • Step 5:  Making Time – Working with the Time Dimension
    • Step 6:  Rapid Application Development in SharePoint – Just an Introduction
    • Step 7:  Using BDC Columns
    • Step 8:  Building the Microsoft Word Template
    • Step 9:  Bringing it All Together – Document Generation
    • Step 10:  Reporting and Auditing

    I hope to be able to provide at least 2 blog posts in this series per week, which would hopefully get us to the end somewhere around the middle of March.  Please check back often to see the latest, or feel free to sign up for our RSS Feed.

    February 10

    Don’t Fear the SharePoint Reaper

    Lately, I have been increasingly asked to come up with something that looks like a value proposition for selling SharePoint to potential customers.  Luckily, I had already thought about this one, so it was kind of easy for me to make the transition from how we used to sell SharePoint way back in 2007 and 2008.

    You see, back then, in the good old days, you basically had to show up, say “I want to be your SharePoint guy – here are my rates” and start preparing the Statement of Work.  There was a huge line of folks wanting SharePoint up and running, most probably because someone sold it to them as part of their Microsoft Enterprise Agreement (EA) and it was supposed to help them “get with the program” in terms of cutting edge technology in the enterprise.  Selling SharePoint in 2007 was kind of like shooting fish in a barrel, or to use a more appropriate analogy, owning a successful software company in 1995…if you could not do it, you should be checked for a pulse and seek a different career path.  Then, we had the little matter of the economy sliding down the drain faster than Kellogg’s dropped Michael “Are You Holding?” Phelps…and it has become necessary to actually have a story to tell and maybe (heaven forbid) use some selling skills.

    SharePoint is, for lack of a better or more politically correct term, the “hatchet” companies are looking for as they “right-size” their way to increased buoyancy in these trying times.  Think of SharePoint as Sir Anthony Hopkins in The Efficiency Expert and The Two “Bobs” from Office Space, all rolled into one awesome product…designed to maximize your ability to achieve “The Four Rights” of good knowledge / information / content management.

    Let’s walk through a quick example for the sake of illustration.  We will use numbers that make the math easy…your individual mileage may vary, depending on your corporate structure and culture, but hopefully you will be able to see the potential when we are done.

    You have 5 accountants in your company.  On average, each of them spends around 20 hours per week doing their actual job (counting beans and crunching numbers), 5 hours per week dealing with e-mail / meeting requests, 7 hours per week in meetings, and 8 hours per week trying to find information on your dearth of corporate systems, network fileshares, their individual hard drive, e-mail archives, etc., etc.

    You implement SharePoint, and the numbers start to swing in your favor.  The table below presents a conservative estimate:

      Before SharePoint After SharePoint
    Job Performance 20 hours 30 hours
    E-mail / Meeting Requests 5 hours 2.5 hours
    Meetings 7 hours 3.5 hours
    Looking for Information 8 hours 4 hours

     

    So, after implementing SharePoint, the accountants can spend about 50% less time looking for information, 50% less time in meetings, and 50% less time dealing with e-mail / meeting requests.  The net result is that each accountant has 10 more hours per week, and 500 more hours per year, to spend doing their job.  So, for 5 accountants, that amounts to 2500 hours per year of extra work they can do after implementing SharePoint.

    Here comes the very unpleasant part, at least for one of the accountants.  If SharePoint has gained you an average of 500 hours per accountant per year, then it stands to reason that you now only need to have 4 accountants, working more efficiently, as a direct result of implementing SharePoint, to accomplish the same amount of work that 5 accountants are doing now.

    Let’s keep the momentum going here – once again, we will make the numbers easy.  Let’s say you have 500 employees, 50 of which are in management and mission critical positions…we will leave them alone for now.  So, of the other 450 employees, let’s extrapolate our 20% force optimization as a result of a properly waged SharePoint implementation, and say that you can eliminate up to 90 positions, with a 0% drop in work performed.  Once again, let’s keep the math easy and say that the average yearly salary of those 90 employees is $40,000.  SharePoint has just brought you a savings of $360,000…and that does not include:

    • the additional costs for each consolidated job, such as medical benefits, 401K matching, etc.
    • the possibility of consolidation in the management ranks as a result of having fewer employees
    • the financial impact of SharePoint on future operations, as employees start to use SharePoint to store and retrieve information, knowledge and content, further driving up efficiency and driving down the time required to be spent on things other than the core job function of each individual

    Once again, keeping things simple, let’s just say that it would not be unexpected for a proper SharePoint implementation at a 500-employee company to save 500,000 or more in the first 12 months after the initial SharePoint project, which will cost you around $50,000-100,000, based on the volume of content and resources required.  For larger companies, the cost of the SharePoint project will increase in a linear fashion, while the potential savings tend to increase exponentially.

    I almost feel like Vince Offer (the Sham-Wow and Slap Chop guy) – it practically sells itself.  Maybe I will get one of those stylish headsets like Vince and use some goop to spike up what’s left of my hair.

    So, SharePoint is not just a way to make your company more efficient…it is a bona fide way for you to consolidate company resources and trim excess positions that are only necessary because of current inefficiencies in process and knowledge quality / availability.  This is how SharePoint is starting to be billed, at least by the most savvy Microsoft Partners that know their customers and what they need in 2009 and beyond.

    So, to keep using the Office Space analogy, how can you protect yourself against becoming Michael Bolton or Samir Notgonnaworkhereanymore?  Well, that is simple.  Make SharePoint (or whatever Knowledge Management tool your company chooses) your friend.  Volunteer to be a content manager, user interface tester, etc.  Learn everything you can about the product and how to use it…in addition to gaining some skills with some cutting-edge technology, you might just be saving your job.

    February 09

    Validating "Choice" Fields in SharePoint Designer Workflow Forms

     

    I recently discovered a bug in SharePoint Designer Workflows whereby a "Choice" field that you denote as required (de-select the "Allow blank values" option in your SharePoint Designer Workflow form field options) is not exactly required on the form...as in, the validation is worthless. This blog post will attempt to help solve this issue for a couple of different options you may want to select or use when designing your Workflow Task forms in SharePoint Designer.

    For starters, let me say that I have merely built a small amount of extra validation onto some existing information I found in the blogosphere. The original and still penultimate article on how to manipulate SharePoint form fields using JavaScript is by Rob Howard, and can be found here: http://blogs.msdn.com/sharepointdesigner/archive/2007/06/13/using-javascript-to-manipulate-a-list-form-field.aspx.  I also found some good information in this thread from the MSDN forums, which uses Rob's ideas to specifically validate a "Choice" field in a SharePoint Designer Workflow Task Form: http://social.msdn.microsoft.com/Forums/en-US/sharepointworkflow/thread/0ad7fc3c-97a1-464e-ae89-c3133462dda8/

    The only problem I had with the information contained in the MSDN thread is that it is what I would call a little bit clunky in how it handles some of the validation, particularly the code that deals with Radio Buttons.

    Sidebar: If you want to go all the way with Radio Button validation, check out this article by Markuso: http://blog.markuso.com/posts/9/using-javascript-to-access-a-list-form-field-in-sharepoint-designer/

    OK, back on point. I wanted to come up with a way to implement validation within a form for multiple field types. As you would expect, since it is using JavaScript, I have run into many of the same issues that I mentioned as drawbacks to the code contained in the MSDN thread. Alas, it is one of the joys of JavaScript, especially on SharePoint. I have chosen to support the following validations in the first version...because that was the requirement I had for a client.

    • Choice DropDown - validate whether or not the user has selected an option in the DropDown control
    • Radio Buttons - validate whether or not the user has selected a radio button control 
    • Single Checkbox for Approved/Rejected - validate whether or not the user has selected one and only one checkbox to approve or reject...this code is a little specific and very clunky, but also common enough that it just might be useful "as is"
    • "Generic" Single CheckBox - validate whether the user has selected one and only one checkbox

    Step 1:  JavaScript Coding

    Here is the code that I came up with.  Once again, please be advised that it is a little bit clunky...but effective nonetheless.

    function validateField(fieldName)
    {
      var theForm = document.forms[0];
      for(var i=0; i < theForm.elements.length; i++)
      {
        if(theForm.elements[i].title == fieldName)
        {
          if(theForm.elements[i].value == "")
          {
            alert("You must select a value for " + fieldName + "!");
            return false;
          }
          return true;
        }
      }
    }
    
    function validateRadio(fieldName)
    {
      var theForm=document.forms[0];
      for(var i=0; i < theForm.elements.length; i++)
      {
        if(theForm.elements[i].type == "radio")
        {
          if(theForm.elements[i].checked)
          {
            return true;
          }
        }
      }
      alert("You must choose a value for " + fieldName + "!");
      return false;
    }
    
    function validateApprovalCheckbox(fieldName)
    {
      var theForm = document.forms[0];
      var approved = 0;
      var rejected = 0;
      for(var i=0; i < theForm.elements.length; i++)
      {
        if(theForm.elements[i].type == "checkbox")
        {
          if(theForm.elements[i].checked)
          {
            if(theForm.elements[i].parentElement.title == "Approved")
            {
              approved = 1;
            }
            if(theForm.elements[i].parentElelment.title == "Rejected")
            {
              rejected = 1;
            }
          }
        }
      }
      if(approved > 0)
      {
        if(rejected > 0)
        {
          alert("You must select only one value for " + fieldName + "!");
          return false;
        }
        return true;
      }
      if(rejected > 0)
      {
        return true;
      }
      alert("You must choose a value for " + fieldName + "!");
      return false;
    }
    
    function validateCheckboxSingle(fieldName)
    {
      var theForm = document.forms[0];
      var checkedCount = 0;
      for(var i=0; i < theForm.elements.length; i++)
      {
        if(theForm.elements[i].type == "checkbox")
        {
          if(theForm.elements[i].checked)
          {
            checkedCount = checkedCount + 1;
          }
        }
      }
      if(checkedCount > 1)
      {
        alert("You must select only one value for " + fieldName + "!");
        return false;
      }
      if(checkedCount == 0)
      {
        alert("You must choose a value for " + fieldName + "!");
        return false;
      }
      return true;
    }
    

    OK, now that THAT unpleasantness is taken care of, how the heck do we use it?

    Step 2:  Using the Code in SharePoint Designer

    First, open your form in SharePoint Designer and find an asp.net tag near the top that looks like this:  <asp:content id="content2" runat="server" contentplaceholderid="PlaceHolderMain"> and put the JavaScript code RIGHT after that.

    DO NOT FORGET TO ENCLOSE THE CODE IN A <script type="text/javascript" language="javascript"> tag!

    Now, we just need to fire off one or more of those functions when we click our "Complete Task" button on our form. 

    • Find the tag for the Complete Task button.  It should look something like this:  <input type="button" name="btnMarkSubmitted" value="Complete Task" onclick="javascript: {ddwrt:GenFireServerEvent...........
    • Change the "onclick" code to incorporate a check for one or more of the validations.  Since all of the validation functions return "false" or "true", it is pretty easy. 
      • Make it look something like this for a single validation:  onclick="javascript: if(validateField('ManagerApproval')) {ddwrt:GenFireServerEvent.......
      • If you want to have multiple validations, try this:  onclick="javascript: if(validateField('ManagerApproval') && validateCheckBoxSingle('AssignedBusinessUnit')) {ddwrt:GenFireServerEvent.........

    OK -- now for the extra long list of caveats for this "solution"...and the air quotes are no accident.  Make no mistake, this is a workaround if ever there was one.  And, like most workarounds of this type, there are certain things you will need to know before implementing it.  They are:

    1. If you have to make a change to the workflow task form, as soon as you click the "Finish" button in the "Custom Task Wizard" dialog box, and then click the "Finish" button on the "Workflow Designer" dialog box, SharePoint Designer is going to recreate the form from the information it knows about from the Workflow Designer, which has nothing to do with any custom JavaScript code.  The best way to solve this one is to save your code off somewhere and re-paste it into the new form after you make a change.
    2. Take a good look at the Radio Button validation code one more time...and you will see that it is going to give you a potentially false "true" validation result if it finds ANY radio buttons on the form that have been selected.  This is because within the radio button HTML code, you cannot get at anything that matches the fieldName variable to make sure you are checking the right thing.  If you don't believe me, set up a form with a Radio Button "Choice" field and do a "View Source" on it.  Anyway, what this means is that this code is truly only effective when there is only one radio button control on a form.
    3. Similar to #2 above, the code that checks for a single selection in Checkboxes will yield problems if you have multiple checkbox controls on the form.  If you select one and only one checkbox for MULTIPLE fields, then you will end up getting a false "false" validation result.

    Please feel free to expand upon this code and let me know what results you experience.