Condividi tramite


Survey results for questions with multiple answers

This is a rather nice one ...
Considering the fact that I've been working in market research for some time before joining Microsoft, I can say that I'm quite used to the power and flexibility provided by some online questionnaire software (like ConfirmIT for instance - https://www.confirmit.com/).
WSS on the other hand was never designed to compete with such software, and the are many posts out there on the internet where users complain about the lack of built-in functionality when it comes to surveys.
What most of them do not understand is that WSS was designed to be a platform on which you can easily build and expand on. You can quite easily add your desired functionality at any point in time. So let's focus on the following example:

1. Create a new survey. Allow multiple responses from the same users.
2. Create a new question, and allow mutiple answers to it (A1, A2, A3).
3. Add the following answer to the survey: A1, A2.
4. Add the following answer to the survey: A3.

Now let's check the graphical summary for these answers.

Actual results:
A1: 0%
A2: 0%
A3: 50%
A1, A2: 50%

Expected results:
A1: 50%
A2: 50%
A3: 50%

So what can we do about it? Well, we could build a custom web part, and add some code like the following to it:

 using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

using System.Collections;

namespace SurveyWebPart {
  [Guid("a531d169-a9bd-4497-a14c-36147585cd73")]
  public class SurveyWebPart : System.Web.UI.WebControls.WebParts.WebPart {
    Label goOut;
    public SurveyWebPart() { }

    protected string GetListFromURL(string url) {
      string res = url.Substring(url.IndexOf("/Lists/") + 7);
      res = res.Substring(0, res.IndexOf("/"));
      return res;
    }

    protected void BtnCalcOnClick() {
      try {
        SPWeb myWeb = SPControl.GetContextWeb(this.Context);
        SPList myList = myWeb.Lists[GetListFromURL(this.Context.Request.Url.AbsoluteUri)];
        foreach (SPField fi in myList.Fields)
          if (fi.Type == SPFieldType.MultiChoice) {
            Hashtable answers = new Hashtable();
            foreach (SPListItem li in myList.Items) {
              string s = li[fi.Title].ToString().Substring(2);
              while (s.Length != 0) {
                string p = s.Substring(0, s.IndexOf(";#"));
                if (answers.ContainsKey(p))
                  answers[p] = Int32.Parse(answers[p].ToString()) + 1;
                else
                  answers.Add(p, "1");
                s = s.Substring(s.IndexOf(";#") + 2);
              } }
            goOut.Text += "<BR>&nbsp;" + fi.Title + "<BR>";
            foreach (DictionaryEntry di in answers) {
              goOut.Text += "&nbsp;" + di.Key.ToString() + "&nbsp;&nbsp;&nbsp;";
              goOut.Text += "<IMG src="https://blogs.msdn.com/_layouts/1033/images/Survey_Yes.bmp/%22" width=";
              goOut.Text += Int32.Parse(di.Value.ToString()) * 200 / myList.Items.Count + " height=10>";
              goOut.Text += "<IMG src="https://blogs.msdn.com/_layouts/1033/images/Survey_No.bmp/%22" width=";
              goOut.Text += 200 - Int32.Parse(di.Value.ToString()) * 200 / myList.Items.Count + " height=10><BR>";
            } } }
      catch (Exception ex) {
        goOut.Text = "<BR>&nbsp;" + ex.Message;
      } }

    protected override void CreateChildControls() {
      goOut = new Label(); goOut.Text = ""; this.Controls.Add(goOut); BtnCalcOnClick();
      base.CreateChildControls();
    } } }