Tuesday, April 21, 2015

Alphabetical List Quick Filter Solution

The goal of this solution is to create an alphabetical filter at the top of a SharePoint list. Using this filter, we can click a letter and the list will be filtered by the first letter of the column on which the filter is applied.

Shows that a user can click on "K" and the list is sorted by the "Terms" column items that begin with the letter "K."


As typical in SharePoint, there is usually more than one way to solve an issue. The first way to create an A-Z quick filter is to "hard wire" the solution based on views created when you manually filter a column. For more information on how to do this, refer to:
However, JavaScript is the more versatile solution. The plus side of using JavaScript is that you can re-use this code on any site and any list without rewriting the code. 

The solution below is applicable to SharePoint 2010 and 2013, but can be applied to SharePoint 2007 using the code at Alphabetical List View Quick Filter by Boris Gomiunik. If you view Gomiunik's site, he goes into the nitty gritty details of the javascript, so I won't repeat his actions, as he does a great job explaining it! 

This post provides the instructions on how to implement the solution.
  1. Create your SharePoint list.
  2. Open Notepad, copy the code below, and paste it into a new file. (Thanks to Aleksandr for updating the code to SharePoint 2010/2013 requirements, as posted on PasteBin at Nilldot: SharePoint list alphabetic order.)

      <script type="text/javascript">
              function qs(paramName) {
                      var args = document.location.search.substring(1).split("&");
                      for(j = 0; j < args.length; j++) {
                              nameValues = args[j].split("=");
                              if(nameValues[0] == paramName) return nameValues[1];
                      }
                      return null;
              }
              var filterField = "FL";
              var filterValuesDelimiter = " - ";
      var filterValues = new Array
      ("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
              var selectedValueStyle = "font-weight: bold;";
      var filterDivStyle = "margin: 5px; font-size: 15px;";
              var filterLinks = new Array();
              for (var i = 0; i < filterValues.length; i++) {
                      filterLinks.push('<a ' + (qs("FilterValue1") == filterValues[i] ? 'style="' + selectedValueStyle + ' ' : '') + 'href="' + document.location.pathname + '?FilterField1=' + 
      filterField + '&FilterValue1=' + filterValues[i] + '">' + filterValues[i] + '</a>');
              }
              document.write('<div style="' + filterDivStyle + '">' + filterLinks.join
      (filterValuesDelimiter) + '</div>');
      </script>

  3. Save this file as .txt and upload it to the Site Assets library on the site where your list is saved. You may have to click Site Contents on the quick launch menu on the left to see the Site Assets library.
  4. Right click on the file now on SharePoint, and click Copy shortcut to get the URL of the file.
  5. On the page of the list you credit in Step 1, click the cog in the upper-right corner of the page, and click Edit page.

  6. Click Add a Web Part.

  7. In the Categories window, click Media and Content. Select Content Editor, and click Add.

  8. Click the drop-down arrow on the new Content Editor Web Part and select Edit Web Part.
  9.  
  10. In the Content Editor properties box, paste the URL for the *.txt file you copied in Step 3 in the Content Link field. Click Test Link to ensure the *.txt file opens. Click OK.
  11.  

  12. Click the Page tab and click Stop Editing.

  13. Activate the list menu by clicking somewhere in the list area (below the Content Editor Web Part, but not on a list link).
  14. Click the List tab, and List Settings.
  15.  

  16. Under the Columns section, click Create column.
  17.  

  18. Name the column FL (this is linked to the code line var filterField = "FL" above and stands for first letter). For the Column type, select Calculated (calculation based on other columns). In the Formula field, type =LEFT and double click the column name (in the Insert Column box) from which you want to grab the first letter. Add parentheses around the outside of the column name brackets, and remove the brackets. Click OK.

    For instance, in this example, I want to filter by the first letter of the Term column, so my formula looks like this:
  19.  

  20. Go back to the list page and test your alphabetical quick filter links!

39 comments:

  1. This is EXACTLY what I needed. This is the best walkthrough ever. And your code worked great! Thanks so much.

    Do you do SharePoint 2013 support or do you just blog?

    ReplyDelete
  2. I'm so glad it helped you! Right now, I just blog as I have three jobs, so I stay pretty busy. But feel free too reach out to me for help. I have more topics I need to add to the blog, so maybe I have a solution already.

    ReplyDelete
  3. I'm so glad it helped you! Right now, I just blog as I have three jobs, so I stay pretty busy. But feel free too reach out to me for help. I have more topics I need to add to the blog, so maybe I have a solution already.

    ReplyDelete
  4. Wow I'm sure you stay busy. Thanks, I'll probably take you up on that help :) Have a great week!

    ReplyDelete
  5. Quick question -- what would you suggest doing for instances where the first letter is a number or symbol? trying to use this for a list of companies, and some of the names do not begin with letters. Any help would be greatly appreciated!

    ReplyDelete
    Replies
    1. Ideally, it would be one section for all numbers, rather than a filter for each number

      Delete
    2. As a start, I created an additional calculated column to switch all numbers to # and tried adding # to the array, but for some reason it is not reading # in the filter.

      Delete
    3. Maybe you have found a solution already, but if you wanted to include numbers, you need to change the Script to include the numbers.

      If you look at the blue text you pasted to the text file, you see the alphabet - that is where you add the numbers in the same format:
      ("A","B", ... ,"Z", "1", "2", ..., "9", "0");
      Important to note that the list in sharepoint will show the letters first and then digits, but you can swap the order by changing the order in the script.
      Obviously if you do not want the letters, just delete them from the script.

      Similar to that you could extend the filter for the actual names: ("ACME", "APPLE", "IBM",...); but you would have to figure out a way to properly split those names into the FL column in sharepoint (like the =LEFT(Term) above splits the left most character into the FL column).
      You could try =LEFT(Term, SEARCH(" ",Term,1)) but you would need the sharepoint entries to contain a space after the company name.

      I am not sure it will totally work and you might have to fiddle around with that. Have a look at the official site as well: https://support.office.com/en-us/article/Split-text-into-different-columns-with-functions-49ec57f9-3d5a-44b2-82da-50dded6e4a68

      Delete
  6. This comment has been removed by the author.

    ReplyDelete
  7. This works pretty well and enables a tech savvy person to start playing around with the system.

    What I was wondering, is if there is a way to include a reset for the filter. As in a filter value that includes everything regardless of content.
    It feels like there is an easy answer, but I can't nail it.

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. I created an "ALL" link to reset the filter before the for loop. I'm having a hard time pasting that script here but essentially take the filtersLink.push line from within the forloop, paste it above the forloop starts and after document.location.pathname add "+ '">ALL<\/a>');" to finish the line. You'll have to remove the extra '\' before the /a>. I threw that in there to get this to take the HTML tag

      Delete
    3. Would you be able to share your code for the "All" link ? Thanks.

      Delete
  8. I used this:

    =IF(ISNUMBER(INT(LEFT(Term,1))),"1",LEFT(Term,1))

    to make my FL column contain the first letter OR contain a 1 if the first value is a number. Then I just added a "#" after A-Z that has the URL pointing to FieldValue1=1.

    This won't work with special characters but you could do nested IF statements with ISNONTEXT I'm guessing

    ReplyDelete
  9. Would you be able to email me the code you're referring to for the 'All' link?

    ReplyDelete
  10. In case anyone else is interested ... I was able to add the "All" link ... Follow Christel's steps above. Add an additional column (Drop down .. Default value "All") to your list and use the code below.

    --------------------------------------------------------------------------------

    <\\script type="text/javascript">
    function qs(paramName) {
    var args = document.location.search.substring(1).split("&");
    for(j = 0; j < args.length; j++) {
    nameValues = args[j].split("=");
    if(nameValues[0] == paramName) return nameValues[1];
    }
    return null;
    }


    var AllField = "All";
    var AllValuesDelimiter = " - ";



    var AllValues = new Array
    ("All -");
    var selectedValueStyle = "font-weight: bold; ";
    var AllDivStyle = "margin: 5px; font-size: 28px; ";
    var AllLinks = new Array();
    for (var i = 0; i < AllValues.length; i++) {
    AllLinks.push('<\/a ' + (qs("AllValue1") == AllValues[i] ? 'style="' + selectedValueStyle + ' ' : '') + 'href="' + document.location.pathname + '?AllField1=' +
    AllField + '&AllValue1=' + AllValues[i] + '">' + AllValues[i] + '<\/a>');
    }
    document.write('<\/div style="font-size: 28px !important;display: inline !important; float: left !important; padding-right:3px; " + ' + AllDivStyle + '">' + AllLinks.join
    (AllValuesDelimiter) + '<\/div>');


    //--------------------------------------------



    var filterField = "FL";
    var filterValuesDelimiter = " - ";


    var filterValues = new Array
    ("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
    var selectedValueStyle = "font-weight: bold;";
    var filterDivStyle = "margin: 5px; font-size: 28px;";
    var filterLinks = new Array();



    for (var i = 0; i < filterValues.length; i++) {
    filterLinks.push('<\/a ' + (qs("FilterValue1") == filterValues[i] ? 'style="' + selectedValueStyle + ' ' : '') + 'href="' + document.location.pathname + '?FilterField1=' +
    filterField + '&FilterValue1=' + filterValues[i] + '">' + filterValues[i] + '<\/a>');
    }

    document.write('<\/div style="font-size: 28px !important; color: #002b52 !important;display: inline !important; float: left !important;" + '+ filterDivStyle + '">' + filterLinks.join
    (filterValuesDelimiter) + '<\/div>');




    <\/script>

    ReplyDelete
  11. Hi
    thanks for this. It seems great. I did what you said and finally managed to get the alphabetic search display on my page
    Below it is a list I need to seach from alphabetically.

    But I get the below error when I click on an alphabet ----

    Unable to display this Web Part. To troubleshoot the problem, open this Web page in a Microsoft SharePoint Foundation-compatible HTML editor such as Microsoft SharePoint Designer. If the problem persists, contact your Web server administrator.


    Correlation ID:da3af39d-40c6-4000-0cbf-fdb247064042

    ReplyDelete
  12. On SharePoint 2016, I was not able to get my site to work until I changed the FL column calculation to =LEFT([Full Name]), hope this helps someone else:-jmw

    ReplyDelete
  13. I am using SharePoint 2016 and added the code above as follows:

    var filterField = "LEFT([Full Name]),";

    I get the A to Z text but I get the error below.

    I have tried both Content Editor and Script Editor. Same error.

    Any suggestions anyone?


    Unable to display this Web Part. To troubleshoot the problem, open this Web page in a Microsoft SharePoint Foundation-compatible HTML editor such as Microsoft SharePoint Designer. If the problem persists, contact your Web server administrator.

    Correlation ID:8bd02d9e-c0fa-d010-330f-0405a82d4cfb

    ReplyDelete
  14. Hi all, Thanks for the tip above for SharePoint 2016. I edited the line as follows:
    var filterField = "LEFT([Full Name]),";
    I get the A to Z text but I still get the error mentioned above. I tried both Content Editor and Script Editor, same error. Any suggestions anyone? Thanks.

    ReplyDelete
  15. Hi,
    Is it posible to use this for a libary? I can't get it to work!

    ReplyDelete
  16. It will not work for a library. The best thing to use for a library is metadata (columns of data) to sort by. If your library is very large, it may mean that you should consider splitting out your files into more than one library.

    ReplyDelete
  17. Does this work for a library view? I am getting this error:

    One or more field types are not installed properly. Go to the list settings page to delete these fields.

    Correlation ID:483e4a9e-50e0-5000-b68c-f98c3c953da0

    ReplyDelete
    Replies
    1. I don't believe this will work for a library.

      Delete
  18. Hey! Thanks for the walkthrough! It is really great.
    Does anyone have an idea how to gray the letters that have no list entry?

    ReplyDelete
    Replies
    1. You're welcome. That's a great question and would be a great addition. Hopefully someone knows.

      Delete
  19. Hi Christel,
    Just wanted to say thanks very much for the post. Also the additional contributors who fixed the syntax for SP2016 - excellent collaboration - I hope to use this for a People Search list that I am working on and initial tests with the code are great.

    ReplyDelete
  20. You're welcome! I'm so glad it will be helpful!

    ReplyDelete
  21. Thank you! I'm glad it is helpful!

    ReplyDelete
  22. Great work and thanks for sharing. I have a requirement of bringing multiple documents from multiple libraries and want them all to be viewed using A-Z on a single page. Is this possible with your solution?

    ReplyDelete
  23. Thank you Christal for the Content!
    I have a document library which includes files and folders. This script works well with filis but not for those files which is inside the folders. Any idea how I can change script to make it work?

    ReplyDelete
  24. Hey there! I'm trying to get this to work, but seem to be getting the following above my list?

    <%@ Page language="C#" MasterPageFile="~masterurl/default.master" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=16.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Import Namespace="Microsoft.SharePoint" %> <%@ Assembly Name="Microsoft.Web.CommandUI, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="ApplicationPages" Namespace="Microsoft.SharePoint.ApplicationPages.WebControls" Assembly="Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> -

    ReplyDelete
  25. Now getting:

    Cannot retrieve the URL specified in the Content Link property. For more assistance, contact your site administrator.

    ReplyDelete
  26. HI, Thanks for the code. Very helpful. QQ - When I click on the Alphabet, list is filtered, but the code refreshes the page and renders me to the top of the page. I need the control back to be at the list

    ReplyDelete
  27. Hello thanks for the code.
    It works on my blogspot page.
    But "how can I cal a specific category" of my blogger site?
    Thanks

    ReplyDelete
  28. This comment has been removed by the author.

    ReplyDelete