11. コメントつきアンケート

トップどんと来い! ASP.NET > 11. コメントつきアンケート

ビジュアル部品

掲示板を作ってしまった以上、他の Web アプリを食いつぶしてしまおうということで、比較的簡単そうな「アンケート」を作ることにしました。
それもただのアンケートでは面白くないので、「コメントつき」にして見たいと思います。

とはいえ、さして難しくはありません。実際作ってみて難しくありませんでした。
これまでに「カウンタ」「掲示板」という2大 Web アプリの製作を経ていますし、アンケートはカウンタに、コメントは掲示板と似たようなものですから、新しい知識は余り必要ありません。

今回は「掲示板」のように徐々にやっていくのではなく、コードのまとまりとして把握できるようやってみたいと思います。

まずは「配置」をしなければなりません。ビジュアル部品の配置です。私の場合は以下のようなコードにしました。
この部分はアンケートの種類によってどんどん変えても、ソースのコア(核心)ではないので自由にできますが、始めは以下のものに沿ってやってみましょう。

<html>
<head>
</head>
<body bgcolor="#e0e0e0">
 <form runat="server">
  <center>
   <h1>Message Enquete 
   </h1>
  </center>
  <center>TRICK の中で最も好きなキャラクターを教えてください。<br />
   よかったらコメントもどうぞ!! 
  </center>
  <center>
   <table border="1">
    <tbody>
     <tr>
      <td>
       チェック 
      </td>
      <td>
       <b>キャラクター</b> 
      </td>
      <td>
       投票数 
      </td>
     </tr>
     <tr>
      <td>
       <asp:RadioButton id="RadioButton1" runat="server" GroupName="groupBox1">
       </asp:RadioButton>
      </td>
      <td>
       <b>山田奈緒子</b> 
      </td>
      <td>
       <asp:Label id="Label1" runat="server">Label1</asp:Label></td>
     </tr>
     <tr>
      <td>
       <asp:RadioButton id="RadioButton2" runat="server" GroupName="groupBox1">
       </asp:RadioButton>
      </td>
      <td>
       <b>上田次郎</b> 
      </td>
      <td>
       <asp:Label id="Label2" runat="server">Labe2</asp:Label></td>
     </tr>
     <tr>
      <td>
       <asp:RadioButton id="RadioButton3" runat="server" GroupName="groupBox1">
       </asp:RadioButton>
      </td>
      <td>
       <b>矢部謙三</b> 
      </td>
      <td>
       <asp:Label id="Label3" runat="server">Label3</asp:Label></td>
     </tr>
    </tbody>
   </table>
  </center>
  <center>コメント: 
   <asp:TextBox id="TextBox1" runat="server" Width="388px"></asp:TextBox>
  </center>
  <center>
   <asp:Button id="Button1" onclick="Button1_Click" runat="server" Text="投票">
   </asp:Button>
  </center>
  <p>
   ▼コメント一覧 
  </p>
  <p>
   <asp:Label id="Label4" runat="server">Label</asp:Label>
   <br />
   &nbsp; 
  </p>
 </form>
</body>
</html>
おお、ビジュアル部品だけで結構長くなりましたね。全部は説明しませんが、ポイントを拾っていきましょう。ビジュアル部品とはいえ、ポイントは落ちているものです。

<asp:RadioButton id="RadioButton1" runat="server" GroupName="groupBox1">
</asp:RadioButton>
この RadioButton コントロールはアンケートの選択を行うためのものですが、このアンケートを作って初めて気づいたプロパティがあります。

GroupName プロパティ:
Windows アプリにおいて RadioButton は GroupBox とセットで使われることがよくありますが、Web アプリでは GropuBox がありません。
そのために代用するプロパティです。このプロパティに、同じグループの RadioButton は同じ文字列を割り当てます。ここでは1つしかグループはないので、「"groupBox1"」にしています。

このプロパティを設定しなければ同じページ内で複数の RadioButton を選択できてしまいます。必ず割り当てましょう。

<asp:Label id="Label1" runat="server">Label1</asp:Label>
アンケート結果は単体のラベルとして表示します。ここではアンケート項目は、
・山田奈緒子
・上田次郎
・矢部謙三
の3つですから、この結果を表示するラベルが Label1 から Label3 まで用意されています。

<asp:TextBox id="TextBox1" runat="server" Width="388px"></asp:TextBox>
掲示板と違う点は「コメント」であることです。複数行にわたるものよりも単一行のほうがコメントとして大きな役割を果たし、投稿しやすいものになります。そのため、TextBox は TextMode などをいじらずにそのまま配置します。

<asp:Label id="Label4" runat="server">Label</asp:Label>
なんだこれ、と思った方もおられるでしょう。掲示板でもそうでしたが、コメントの表示はたったラベル1個でやってしまいます。
この Text プロパティにコメントを割り当てれば表示する、そのような役割を果たします。

Page_Load

void Page_Load(object sender, EventArgs e) {
  if (!IsPostBack)
  {
   System.IO.StreamReader sr = new System.IO.StreamReader(Server.MapPath(".") + "\\elect.txt");
  
   string[] elect = new string[3];
  
   for(int i=0;i<=2;i++)
    elect[i] = sr.ReadLine();
  
   sr.Close();
  
   Label1.Text = elect[0];
   Label2.Text = elect[1];
   Label3.Text = elect[2];
  
   // 以下はコメント用
   System.IO.StreamReader sr_comment = new System.IO.StreamReader(MapPath(".") + "\\electcomment.txt");
   string comment;
   comment = sr_comment.ReadToEnd();
   Label4.Text = comment;
   sr_comment.Close();
  }
 }
いきなりコードですが、難しくないと思います。段落であるかのように行を空けていますので、それを参考にたどっていきましょう。

StreamReader の準備はもう飽きるほどしてきましたからいいでしょう。「elect.txt」は投票数を保存するためのものです。

次に配列がきました。配列が Web アプリでも使えることに少し感動したのですが、それはともかく3要素用意された「elect」配列は
・山田奈緒子
・上田次郎
・矢部謙三
の、投票結果を順番に入れていきます。まとまって扱うため、ばらばらの変数よりも配列のほうがいいです。

for(int i=0;i<=2;i++)
    elect[i] = sr.ReadLine();
elect.txt にはアンケートの項目順に1行ずつ結果を記述することにしますから、順番に配列に代入していきます。
その後、StreamReader はもう使わないのでクローズしましょう。これは Page_Load の中の最後でもかまいません。

次の3行はラベルに表示する部分です。この時点で表示は完了しています。これ以降はコメントを表示するプログラムです。

コメントは「electcomment.txt」を外部ファイルとします。この後は
1) 変数用意
2) 変数に最後まで読み込む
3) Label4.Text に割り当てて表示
4) StreamReader をクローズ
という単純な手順ですから、自分で把握しておきましょう。

Button1_Click -アンケート編-

Button1_Click イベントメソッドは長いので、2つに分けて解説します。
void Button1_Click(object sender, EventArgs e) {
  string[] elect = new string[3];
  // 下の変数はコメント用
  string electedItem = "";
 
  System.IO.StreamWriter sw = new System.IO.StreamWriter(Server.MapPath(".") + "\\elect.txt");
  elect[0] = Label1.Text;
  elect[1] = Label2.Text;
  elect[2] = Label3.Text;
 
  if (RadioButton1.Checked)
  {
   elect[0] = (int.Parse(elect[0]) + 1).ToString();
   electedItem = "山田奈緒子";
   RadioButton1.Checked = false;
  }
  else if (RadioButton2.Checked)
  {
   elect[1] = (int.Parse(elect[1]) + 1).ToString();
   electedItem = "上田次郎";
   RadioButton2.Checked = false;
  }
  else if (RadioButton3.Checked)
  {
   elect[2] = (int.Parse(elect[2]) + 1).ToString();
   electedItem = "矢部謙三";
   RadioButton2.Checked = false;
  }
 
  sw.Write("");
  sw.WriteLine(elect[0]);
  sw.WriteLine(elect[1]);
  sw.WriteLine(elect[2]);
 
  sw.Close();
  Label1.Text = elect[0];
  Label2.Text = elect[1];
  Label3.Text = elect[2];
まず、表示されているラベルの値から現在のアンケート結果を取得します。配列 elect はこのために利用されています。
また、変数 electedItem は選択されたキャラクターをコメントに表示するために使われる変数です。

if のハシゴはあまりキレイであるとはいえませんが、同じ働きをする if が項目数だけあります。
その中で RadioButton.Checked を false にしているのは、ボタンを押した後改めて表示されたときにチェックが残っていると「ちゃんと押せたのか?」と思ってしまうので、あえて消しています。

elect[0] = (int.Parse(elect[0]) + 1).ToString();
この部分は順番に解説しましょう。

まず、elect[0] には「山田奈緒子」を選択した人の数が string として入っています。string は計算処理はできません。よって、int 型に変換します。
ここで double は必要ありません。当然ですが、0.3 人などという投票数は絶対にありえないため、int でいいのです。

変換した後、1 を足します。足さなければ押しても押しても投票されません。
elect[0] は string ですから、この配列に代入しなおすには string に戻す必要があります。ToString() がその変換部分にあたります。


else if のあとは「ファイルへの書き込み」「ラベルへの表示し直し」のコードです。
ファイルの書き込みはこれまで
Write()
を使ってきましたが、1行ずつ書き込みたいので
WriteLine()
とします。エスケープシーケンスを用いてもできますが、わかり易いのでいいでしょう。

StreamWriter をクローズするのをお忘れなく。

Button1_Click -コメント編-

コメントの部分は掲示板と同じです。掲示板よりらくだと思います。
// 以下はコメント用
  System.IO.StreamWriter sw_comment = new System.IO.StreamWriter(Server.MapPath(".") + "\\electcomment.txt");
  string comment;
  string text;
  string plus;
 
  comment = Label4.Text;
  text = TextBox1.Text;
  plus = "\r\n<hr><b>" + electedItem + "</b> <font size=\"2\">投票時間 : " + 
      System.DateTime.Now.ToUniversalTime().AddHours(9).ToString() +
      "</font><br>" + text;
 
  if (TextBox1.Text == "")
   plus = "";
 
  comment = plus + comment;
  plus = "";
  Label4.Text = comment;
 
  sw_comment.Write("");
  sw_comment.Write(comment);
  sw_comment.Close();
 
  TextBox1.Text = "";
 }

</script>
特に注意点はありません。
System.DateTime.Now.ToUniversalTime().AddHours(9).ToString()
による日時取得を再確認してもらえれば復習になります。

ということで、ここに記したコードを貼り付けていけばアンケートになりますが、まとまった形でコードを提供しておきます。
これでアンケートも終わってしまいましたから、今度は別の Web アプリに挑戦してみたいと思います。何にするかは気分で決めると思いますが、あとはダウンロードカウンターとかパスワードとか小技的なものになりますかね。

All Source:
<%@ Page Language="C#" %>
<script runat="server">
 void Page_Load(object sender, EventArgs e) {
  if (!IsPostBack)
  {
   System.IO.StreamReader sr = new System.IO.StreamReader(Server.MapPath(".") + "\\elect.txt");
  
   string[] elect = new string[3];
  
   for(int i=0;i<=2;i++)
    elect[i] = sr.ReadLine();
  
   sr.Close();
  
   Label1.Text = elect[0];
   Label2.Text = elect[1];
   Label3.Text = elect[2];
  
   // 以下はコメント用
   System.IO.StreamReader sr_comment = new System.IO.StreamReader(MapPath(".") + "\\electcomment.txt");
   string comment;
   comment = sr_comment.ReadToEnd();
   Label4.Text = comment;
   sr_comment.Close();
  }
 }
 
 void Button1_Click(object sender, EventArgs e) {
  string[] elect = new string[3];
  // 下の変数はコメント用
  string electedItem = "";
 
  System.IO.StreamWriter sw = new System.IO.StreamWriter(Server.MapPath(".") + "\\elect.txt");
  elect[0] = Label1.Text;
  elect[1] = Label2.Text;
  elect[2] = Label3.Text;
 
  if (RadioButton1.Checked)
  {
   elect[0] = (int.Parse(elect[0]) + 1).ToString();
   electedItem = "山田奈緒子";
   RadioButton1.Checked = false;
  }
  else if (RadioButton2.Checked)
  {
   elect[1] = (int.Parse(elect[1]) + 1).ToString();
   electedItem = "上田次郎";
   RadioButton2.Checked = false;
  }
  else if (RadioButton3.Checked)
  {
   elect[2] = (int.Parse(elect[2]) + 1).ToString();
   electedItem = "矢部謙三";
   RadioButton2.Checked = false;
  }
 
  sw.Write("");
  sw.WriteLine(elect[0]);
  sw.WriteLine(elect[1]);
  sw.WriteLine(elect[2]);
 
  sw.Close();
  Label1.Text = elect[0];
  Label2.Text = elect[1];
  Label3.Text = elect[2];
 
  // 以下はコメント用
  System.IO.StreamWriter sw_comment = new System.IO.StreamWriter(Server.MapPath(".") + "\\electcomment.txt");
  string comment;
  string text;
  string plus;
 
  comment = Label4.Text;
  text = TextBox1.Text;
  plus = "\r\n<hr><b>" + electedItem + "</b> <font size=\"2\">投票時間 : " + 
      System.DateTime.Now.ToUniversalTime().AddHours(9).ToString() +
      "</font><br>" + text;
 
  if (TextBox1.Text == "")
   plus = "";
 
  comment = plus + comment;
  plus = "";
  Label4.Text = comment;
 
  sw_comment.Write("");
  sw_comment.Write(comment);
  sw_comment.Close();
 
  TextBox1.Text = "";
 }

</script>
<html>
<head>
</head>
<body bgcolor="#e0e0e0">
 <form runat="server">
  <center>
   <h1>Message Enquete 
   </h1>
  </center>
  <center>TRICK の中で最も好きなキャラクターを教えてください。<br />
   よかったらコメントもどうぞ!! 
  </center>
  <center>
   <table border="1">
    <tbody>
     <tr>
      <td>
       チェック 
      </td>
      <td>
       <b>キャラクター</b> 
      </td>
      <td>
       投票数 
      </td>
     </tr>
     <tr>
      <td>
       <asp:RadioButton id="RadioButton1" runat="server" GroupName="groupBox1">
       </asp:RadioButton>
      </td>
      <td>
       <b>山田奈緒子</b> 
      </td>
      <td>
       <asp:Label id="Label1" runat="server">Label1</asp:Label></td>
     </tr>
     <tr>
      <td>
       <asp:RadioButton id="RadioButton2" runat="server" GroupName="groupBox1">
       </asp:RadioButton>
      </td>
      <td>
       <b>上田次郎</b> 
      </td>
      <td>
       <asp:Label id="Label2" runat="server">Labe2</asp:Label></td>
     </tr>
     <tr>
      <td>
       <asp:RadioButton id="RadioButton3" runat="server" GroupName="groupBox1">
       </asp:RadioButton>
      </td>
      <td>
       <b>矢部謙三</b> 
      </td>
      <td>
       <asp:Label id="Label3" runat="server">Label3</asp:Label></td>
     </tr>
    </tbody>
   </table>
  </center>
  <center>コメント: 
   <asp:TextBox id="TextBox1" runat="server" Width="388px"></asp:TextBox>
  </center>
  <center>
   <asp:Button id="Button1" onclick="Button1_Click" runat="server" Text="投票">
   </asp:Button>
  </center>
  <p>
   ▼コメント一覧 
  </p>
  <p>
   <asp:Label id="Label4" runat="server">Label</asp:Label>
   <br />
   &nbsp; 
  </p>
 </form>
</body>
</html>