インストールレスプログラミング( ´ー`)

VBA , JavaScript , HTAなど 365アプリはインストール必要ですが、仕事に無いケースはほぼないから(・_・;)

アンケート けっこうできてきた。

一度はまりだすと,小説より面白いですね。ひたすらアンケートのやつやってました。

Excelのブックをアップする手段がないので,物自身は上げれませんが,

概要とコードを上げてみます。

f:id:chemiphys:20190111005459p:plain

図のように,エクセルのシートに設問のデータを入れると,htaを作り出すという仕組みです。原因不明の上部の空白がいまのとこまだ解決できていませんが,使えそうなレベルになってきています。

Excelのコードを載せます。

・ポイントがあるとするならば,ADODB.Streamを使うことでUTF-8で書き出している点
cssJavaScript部分は共通なのでそのあたりをヘッダやフッタとしてExcelシートにのせておいて,それをどんどん張り付けてる点
・それらの一部を変更したい場合はreplaceで対応しています。

あんまり特別なことはしていないですね。けっこう簡単にやりたいことができました。。

はてなブログ,簡単なファイルアップロード機能あったら,さらに便利なのになぁ( ´Д`)=3

Sub MakeText()
    Dim FileName As String
    FileName = ThisWorkbook.Path & "\" & "test.hta"
    
    Dim ADODBStream As Object
    Set ADODBStream = CreateObject("ADODB.Stream")
    With ADODBStream
        .Charset = "UTF-8"
        .Open
    End With
    
    Dim HeaderSheet As Worksheet: Set HeaderSheet = ThisWorkbook.Worksheets("ヘッダ")
    Dim FooterSheet As Worksheet: Set FooterSheet = ThisWorkbook.Worksheets("フッタ")
    Dim ConfigSheet As Worksheet: Set ConfigSheet = ThisWorkbook.Worksheets("アンケートシート")
    Dim 問題名配列文字列 As String, 問題タイプ配列文字列 As String
    
    Dim i, j, tmp, tmp2
    
    tmp = "[""No" & ConfigSheet.Cells(4, 1) & """"
    tmp2 = "[""" & ConfigSheet.Cells(4, 3) & """"
    i = 5
    Do While ConfigSheet.Cells(i, 1) <> ""
        tmp = tmp & ",""No" & ConfigSheet.Cells(i, 1) & """"
        tmp2 = tmp2 & ",""" & ConfigSheet.Cells(i, 3) & """"
        i = i + 1
    Loop
    問題名配列文字列 = tmp & "]"
    問題タイプ配列文字列 = tmp2 & "]"
    
    
    i = 1
    Do
        tmp = HeaderSheet.Cells(i, 1)
        If InStr(tmp, "【タイトル】") > 0 Then tmp = Replace(tmp, "【タイトル】", ConfigSheet.Cells(1, 2))
        If InStr(tmp, "【問題名配列】") > 0 Then tmp = Replace(tmp, "【問題名配列】", 問題名配列文字列)
        If InStr(tmp, "【問題タイプ配列】") > 0 Then tmp = Replace(tmp, "【問題タイプ配列】", 問題タイプ配列文字列)
        ADODBStream.writetext tmp, 1
        i = i + 1
        DoEvents
    Loop Until HeaderSheet.Cells(i, 1) = "--End--"
    
    '各要素
    i = 4
    Do While ConfigSheet.Cells(i, 1) <> ""
        ADODBStream.writetext "  <tr>", 1
        ADODBStream.writetext "    <td class=""setsumon"">" & ConfigSheet.Cells(i, 2) & "</td>", 1
        ADODBStream.writetext "  </tr>", 1
        ADODBStream.writetext "  <tr>", 1
        ADODBStream.writetext "    <td class=""kaitou"">", 1
                
        Select Case ConfigSheet.Cells(i, 3)
            
            Case Is = "radio"
                j = 6
                Do While ConfigSheet.Cells(i, j) <> ""
                    tmp = ConfigSheet.Cells(i, j)
                    ADODBStream.writetext "      <input type=""radio"" name=""No" & ConfigSheet.Cells(i, 1) & """ value=""" & tmp & """>" & tmp & "<br>", 1
                    j = j + 1
                Loop
            
            Case Is = "check"
                j = 6
                Do While ConfigSheet.Cells(i, j) <> ""
                    tmp = ConfigSheet.Cells(i, j)
                    ADODBStream.writetext "      <input type=""checkbox"" name=""No" & ConfigSheet.Cells(i, 1) & """ value=""" & tmp & """>" & tmp & "<br>", 1
                    j = j + 1
                Loop
            
            Case Is = "text"
                ADODBStream.writetext "      <input type=""text"" name=""No" & ConfigSheet.Cells(i, 1) & """ size=""45"" />", 1
            
            Case Is = "multi"
                ADODBStream.writetext "      <textarea name=""No" & ConfigSheet.Cells(i, 1) & """ rows=""5"" cols=""46"" ></textarea>", 1
        End Select
        
        ADODBStream.writetext "    </td>", 1
        ADODBStream.writetext "  </tr>", 1
        ADODBStream.writetext "", 1
        i = i + 1
    Loop
    
    i = 1
    Do
        ADODBStream.writetext FooterSheet.Cells(i, 1), 1
        i = i + 1
        DoEvents
    Loop Until FooterSheet.Cells(i, 1) = "--End--"
    
    ADODBStream.savetofile FileName, 2
    ADODBStream.Close
    
    
End Sub

excelファイルはアップできなくても,生成したコードぐらいは上げれるので,生成したコードを上げます。中身は推察されるはず

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>テストアンケート</title>
  <style type="text/css">
    table{border-collapse: collapse;}
    table,tr,td{border: solid 2px black;}
    td.bango{text-align: center;background-color: black;font-weight: bold;color: white;width:15px}
    td.setsumon{padding-left: 5px;font-weight: bold;background-color: black;color: white;width:400px}
    td.kaitou{padding-left: 20px;background-color: antiquewhite}
  </style>
  <script>
    
    function result(){
      var mondaiName=["No1","No2","No3","No4"]
      var mondaiType=["radio","check","text","multi"]
      var html=[]
      for (var i=0;i<mondaiName.length;i++){
        html.push(i+1 + "_" + getData(mondaiName[i],mondaiType[i])+"◇")
      }
      document.getElementById("answer").innerHTML=html.join("")
    }
    
    function getData(name,type){
      switch(type){
        case "radio":
        case "check":
          return getCheck(name);
          break;
        case "text":
        case "multi":
          return document.getElementsByName(name)[0].value.replace(/\r?\n/g,"■");
          break;
      }
    }
    
    function getCheck(name){
      var CHECK=document.getElementsByName(name)
      var tmp=""
      for(var i=0;i<CHECK.length;i++){
        if(CHECK[i].checked) tmp+="," +CHECK[i].value
      }
      return tmp.substring(1)
    }
  </script>
</head>

<body>
  <form name="form1">
  <table>

  <tr>
    <td class="setsumon">この中で一番好きな食べ物はどれか。</td>
  </tr>
  <tr>
    <td class="kaitou">
      <input type="radio" name="No1" value="カレー">カレー<br>
      <input type="radio" name="No1" value="ラーメン">ラーメン<br>
      <input type="radio" name="No1" value="うどん">うどん<br>
      <input type="radio" name="No1" value="そば">そば<br>
    </td>
  </tr>

  <tr>
    <td class="setsumon">好きなペットは何か。(複数えらんでいい)</td>
  </tr>
  <tr>
    <td class="kaitou">
      <input type="checkbox" name="No2" value="犬"><br>
      <input type="checkbox" name="No2" value="ネコ">ネコ<br>
      <input type="checkbox" name="No2" value="ハムスター">ハムスター<br>
    </td>
  </tr>

  <tr>
    <td class="setsumon">自分を動物に例えると。</td>
  </tr>
  <tr>
    <td class="kaitou">
      <input type="text" name="No3" size="45" />
    </td>
  </tr>

  <tr>
    <td class="setsumon">この変なアンケートについて感想をどうぞ。</td>
  </tr>
  <tr>
    <td class="kaitou">
      <textarea name="No4" rows="5" cols="46" ></textarea>
    </td>
  </tr>

  </table>
  <input type="button" href="#" value="送信する" onClick="result()"/>
  </form>

  <p>回答</p>
  <div id="answer"></div>
 </body>
</html>

アンケート部分の例を作ってみました。

どういうコードを吐き出させればいいのかを確かめるため,とりあえずアンケートフォームを作ってみました。

画面はこんな感じ
f:id:chemiphys:20190110192917p:plain

送信ボタンを押すと,

 <div id="answer"></div> 

にアンケートの結果をとりあえず出すように作りました。

最終的にはこれを望む場所に放り込むよう作ればいい。

フォーム内部もできるだけシンプルになるように作ってみた。できるだけタグをそぎ落として,必要最小限にし,構造ができるだけ似通うようにして,

マクロでコードを吐く部分が楽になるようにしてみた。

コードを載せます。JavaScriptもすこーしは慣れてきたかな。。

今回のものはhtmlのままでもちゃんといけますし,htaにしても動きます。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>無題ドキュメント</title>
  <style type="text/css">
    table{border-collapse: collapse;}
    table,tr,td{border: solid 2px black;}
    td.bango{text-align: center;background-color: black;font-weight: bold;color: white;width:15px}
    td.setsumon{padding-left: 5px;font-weight: bold;background-color: black;color: white;width:400px}
    td.kaitou{padding-left: 20px;background-color: antiquewhite}
  </style>
  <script>
    
    function result(){
      var mondaiName=["toi1","toi2","toi3","toi4"]
      var mondaiType=["radio","check","text","multi"]
      var html=[]
      for (var i=0;i<mondaiName.length;i++){
        html.push(i+1 + "_" + getData(mondaiName[i],mondaiType[i])+"◇")
      }
      document.getElementById("answer").innerHTML=html.join("")
    }
    
    function getData(name,type){
      switch(type){
        case "radio":
        case "check":
          return getCheck(name);
          break;
        case "text":
        case "multi":
          return document.getElementsByName(name)[0].value.replace(/\r?\n/g,"■");
          break;
      }
    }
    
    function getCheck(name){
      var CHECK=document.getElementsByName(name)
      var tmp=""
      for(var i=0;i<CHECK.length;i++){
        if(CHECK[i].checked) tmp+="," +CHECK[i].value
      }
      return tmp.substring(1)
    }
  </script>
</head>

<body>
  <form name="form1">
  <table>
    <tr>
      <td class="setsumon">1 授業は全体的にわかりやすいですか。</td>
    </tr>
    <tr>
      <td class="kaitou">
        <input type="radio" name="toi1" value="1">とても分かりやすかった<br>
        <input type="radio" name="toi1" value="2">分かりやすかった<br>
        <input type="radio" name="toi1" value="2">あまり分からない<br>
      </td>
    </tr>
  
    <tr>
      <td class="setsumon">2 好きな科目をいくつか選びなさい</td>
    </tr>
    <tr>
      <td class="kaitou">
        <input type="checkbox" name="toi2" value="国">国語<br>
        <input type="checkbox" name="toi2" value="英">英語<br>
        <input type="checkbox" name="toi2" value="数">数学<br>
        <input type="checkbox" name="toi2" value="理">理科<br>
        <input type="checkbox" name="toi2" value="社">社会<br>
      </td>
    </tr>
  
    <tr>
      <ul><td class="setsumon">3 一言メッセージ</td></ul>
    </tr>
    <tr>
      <td class="kaitou">
        <input type="text" name="toi3" size="45" />
      </td>
    </tr>

    <tr>
      <td class="setsumon">4 ご意見ご要望</td>
    </tr>
    <tr>
      <td class="kaitou">
        <textarea name="toi4" rows="5" cols="46" ></textarea>
      </td>
    </tr>
  </table>
  <input type="button" href="#" value="送信する" onClick="result()"/>
  </form>

  <p>回答</p>
  <div id="answer"></div>
 </body>
</html>

Excel側でテキストコードを吐き出すのも楽にできそうだったので,けっこう進んだ気がします。

アンケート作成 苦戦中です。 愚痴みたいなもの。

アンケートのHTAを最終的にはつくるべく,HTMLやJavaScriptと格闘中です。

あまりホームページ等作ったことはないので,このへんはツールの力でごり押ししていて,タグ打ちとかほぼしたことなくて未知の領域。

進まない進まない。。

ネットや本の力を借り,見た目は テキストボックス,ラジオボックス,チェックボックス,複数行入力できるフィールド等配置したものを作り,送信ボタンをつけてあげる。

そう,サーバーを立てれない環境でしかやっていなかった私にとって 不思議極まりなかったのが Submitボタンです。

送信てどこに送信してるの どんなもの送信してるの 細かい設定はどこでしてるのと

???????????

はてなの大行進の内容でした。


ですが,JavaScriptをやり始めてから,外部には何も出さずにJavaScriptでデータを受け取って望みの形に成型して望む場所に出す,ということが現実的になりました。

チェックボックス以外のエレメントに関しては,比較的簡単に制御はわかりましたが,複数選択で使えるチェックボックスについてはかなりてこずりました。

丸一日くらいはそれで引っかかってました。やっとなんとかなりそうではあります。そのうち触れることはあるかと。



わからないことばかりで,本当に困ったものですが,遅々とした歩みではありますが,なんか目標に歩けているようです。

見込みが立ってきたので,望むものを作る方向性だけ書き出しておくことにしました。

 1.Excelにアンケートの設問形式,設問の内容,選択肢を書き込めるシートを用意する。

 2.VBAでそれに従ったHTAのコードを作らせて,保存までさせる。

 3.できあがり ヽ(*´∇`)ノ

UTF-8文字コードVBAで保存させるってとこがよくわかってませんが,まぁたぶんできるはず。


form内のname属性を配列で取りたい,というのもずいぶん調べたんですが私には理解できませんでした。getAttributeとかでできるのかなぁと試していましたが,

デバッグの仕方もまだよくわかってないのでとても効率が悪い。

VBAのエディタのローカルウィンドウとかイミディエイトウィンドウが神様のように見えます。 (ノД`)

ただ,自分でどうせ設問のコードを吐き出すわけですので,

コードのどこかに配列できちんとname属性を記録しておけばそれに従って処理は可能なわけで,なんとかなるなとは思えています。

または,全エレメントの値を返させて後でゆっくり料理するというのもありですね。

JavaScriptに慣れていけばいろんな手段は思いつきそうですので,がんばろう。

まだ本やネットを見ないとほとんど何も書けない,VBAと比べるととてもひどい状況ですが,

JavaScriptはとても興味をそそられます。

この気持ちがあるうちに,理解度をできるだけ進めたいところです。力尽きたらまたしばらくやらなくなりますしね。。(;´∀`)

疑似掲示板 その2

TextStreamのCloseをきちんとすると,動きがとてもよくなったので,実際の使用に向けてさらに調整を加えてみました。

各授業で簡単に使えるように,データファイルに当たるbbs.txtを掲示板ファイルの名前を利用してつけるように変更。

同じフォルダにHTAファイルとtxtファイルがあるとごちゃごちゃなるので,bbsフォルダを作成してそこにtxtを保存するように変更。

見た目が悪かったので,CSSで若干調整。

(追記)更新ボタンも付け加えました。

この辺の手を加えてみました。試してみないと本当のとこわかりませんが,うまくいきそうな感じ。

ショートカットをうまく利用して生徒が簡単にアクセスできるようにもう一工夫があるといいのかな

さらにショートカットを固定できるように,仕組みを自分の中でルールづけられれば,面白いのかもしれない。

とりあえず,昨日のものよりは改善していると思うので,コードを載せます。

HTAのお約束で,メモ帳とかに貼って,文字コードを忘れずにUTF-8にして,拡張子htaで保存します。それだけでたぶん使えます。

HTAは手軽でいい。次のVersionのWindowsでも生き残らせてくれないかなぁ ( ´Д`)=3

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>メッセージ</title>
<!-- CSS -->
	<style type="text/css">
		.title{background-color: orange;font-size: 20px;display: block;width: 100%;}
		dt{display:block;width: 80px; float: left;padding-left: 2px;padding-top: 2px; background-color:lime;}
		dd{display:block;width: 410px;margin-left: 85px;padding-left: 5px;padding-top: 2px; background-color: greenyellow;}
		.user{display: none;}
		.form{background-color: beige;display: block;width: 100%-4px;padding: 4px;}
	</style>
<!--JScript-->	
<script>
	resizeTo(560,600);
	// FileSystemObject 用定数
	var ForReading = 1;
	var ForWriting = 8;
	/** BBS のデータファイルのフルパス */
	var thisName=location.pathname
	thisName=thisName.slice(thisName.lastIndexOf("\\")+1,thisName.lastIndexOf("."));
	var BbsFile = ".\\bbs\\"+thisName+"bbs.txt";
	var User=new ActiveXObject("WScript.Network").UserName;
	/** ファイルの読み込み */
	function loadText() {
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		var bbs = fso.OpenTextFile(BbsFile, ForReading);
		var tmp=bbs.ReadAll();
		bbs.Close();
		return(tmp);
	}
	/** 投稿内容のロード */
	function load() {
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		if (fso.FolderExists(".\\bbs")==false) fso.CreateFolder(".\\bbs");
		if (fso.FileExists(BbsFile)==false){
			var bbs = fso.OpenTextFile(BbsFile, ForWriting,true);
			bbs.WriteLine("<dt style='background-color:limegreen;'>名前</dt><dd style='background-color:limegreen;'>メッセージ</dd><span class='user'>ユーザー名</span>\r");
			bbs.Close();
		} 
		document.getElementById("data").innerHTML=loadText();
	}
	/** 投稿 */
	function post() {
		var name=document.getElementById("name").value;
		var msg=document.getElementById("msg").value;
		var postData = "<dt>" + name + "</dt>" + "<dd>" + msg + "</dd>" +"<span class='user'>" + User +"</span>\r";
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		var bbs = fso.OpenTextFile(BbsFile, ForWriting);
		bbs.WriteLine(postData);
		bbs.Close();
		load();
		document.getElementById("name").value="";
		document.getElementById("msg").value="";
	}
</script>
</head>

<body onLoad="load();">
	
	<div class="title">一言メッセージ</div>
	<span class="form">
		名前 <input type="text" id="name" size="14" value="" placeholder="Name"><br>
		メッセージ <input type="text" id="msg" size="50" value="" placeholder="Message"><br>
	  <input type="button" id="post" value="送信" onClick="post()">
		<input type="button" id="Reload" value="更新" onClick="load()">
	</span>
	<dl id="data"></dl>
</body>
</html>

動作画面はこんな感じです。

f:id:chemiphys:20190108134542p:plain

試用後に再調整かな。

今度はアンケートに近いものが作れるようにしてみよう。

疑似掲示板(失敗) JScript & HTA → 成功かも

興味がない分野について,自分の知識が全くないことに気づかせてくれるJSciptの学習。

今日は掲示板ぽいのを作ることをしていました。

neos21.hatenablog.com

こちらの記事を参考に,コードも使わせてもらいながら,自分の環境で作る。

JQueryを自分の環境でいまのところきちんと動かせなかったので,けっこうコードは行き当たりばったりで作ってます。

JScriptの学習と思ってこつこつやっていました。

例によってHTAです。HTMLでは動作しません。

メモ帳にはりつけて,拡張子HTAで保存します。文字コードUTF-8にしないと動かないようです。

追記 imihitoさんにコメントをいただいて,見直してみたらCloseに()が抜けていましたので修正しました。
  失敗を忘れないためにも下のほうの駄文は残しております。コードは書き直しました。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>メッセージ</title>
<!-- CSS -->
	<style type="text/css">
		dt{float: left;}
		dd{margin-left: 80px;}
		.user{display: none;}
	</style>
<!--JScript-->	
<script>
	// FileSystemObject 用定数
	var ForReading = 1;
	var ForWriting = 8;
	/** BBS のデータファイルのフルパス */
	var BbsFile = "bbs.txt";
	var User=new ActiveXObject("WScript.Network").UserName;
	/** ファイルの読み込み */
	function loadText() {
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		var bbs = fso.OpenTextFile(BbsFile, ForReading);
		var tmp=bbs.ReadAll();
		bbs.Close();
		return(tmp);
	}
	/** 投稿内容のロード */
	function load() {
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		if (fso.FileExists(BbsFile)==false){
			var bbs = fso.OpenTextFile(BbsFile, ForWriting,true);
			bbs.WriteLine("<dt>名前</dt><dd>メッセージ</dd><span class='user'>ユーザー名</span>\r");
			bbs.Close();
		} 
		document.getElementById("data").innerHTML=loadText();
	}
	/** 投稿 */
	function post() {
		var name=document.getElementById("name").value;
		var msg=document.getElementById("msg").value;
		var postData = "<dt>" + name + "</dt>" + "<dd>" + msg + "</dd>" +"<span class='user'>" + User +"</span>\r";
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		var bbs = fso.OpenTextFile(BbsFile, ForWriting);
		bbs.WriteLine(postData);
		bbs.Close();
		load();
		document.getElementById("name").value="";
		document.getElementById("msg").value="";
	}
</script>
</head>

<body onLoad="load();">
	<h1>一言メッセージ</h1>
	<p>
		名前 <input type="text" id="name" size="14" value="" placeholder="Name">
		  メッセージ <input type="text" id="msg" size="60" value="" placeholder="Message">
	</p>
	<p>
		<input type="button" id="post" value="送信" onClick="post()">
		※エラーが出たら少し待ってもう一度 送信 を押してください。
	</p>
	<dl id="data"></dl>
</body>
</html>

こんな画面になるとってもシンプルなもの。
送信ボタンを押せば投稿されるよ,ということと ユーザー名を裏で記録してるよ,というもの。
f:id:chemiphys:20190107225337p:plain


一人で試してても
f:id:chemiphys:20190107225633p:plain
こういうエラーがまぁまぁ出ます。書き込み時の競合なのかなーと思うけどテキストのファイルサイズもそんなに大きくないし,

なんでそれなりの確率でこいつが出てくるのか不思議です。できる範囲でCloseもやっているのになぁ。WriteLineの直後にClose書いたら拒否されるのでそこはやってません。

複数ウィンドウを開いて試すとさらにダメ。ということは実際の使用には現状はたえない状態のようです。元の記事の方とは書き込み回りも違いますし,そちらに

寄せていけば改善されるのだろうか。 ※追記 Close();をきちんとすることで改善されていると思われます。

とりあえず,この形で作りたかったので,その試しとして記録するとして,今度は各クライアントが一つのテキストを吐き出すようにして,あるフォルダにその小さいテキストを集める。

すでに存在する場合は上書きするという形にして,競合の可能性をなくす。

小さいテキストをかき集めて掲示板のデータにする,という形で今度は作ってみようと思います。

読み込みの際は問題にならないんじゃないかなと思うので,エラーを回避できるかなぁと思ったり。

明日はそれに挑戦してみよう。。

実際使っている授業支援ソフトが,アンケート機能が通信環境の安定性を損ねるということでなくなっています。

その代わりになるものを手にしたいと思っていますので,40名程度を相手にアンケートぽいものをサーバーレスで作ってみたいと思ってるところなんです。

そこまでたどり着くかどうかはさっぱりですが,楽しいですし,やってみたいところ。。

JScript mp3の再生について 書き残し

前回のタイマーで一番時間がかかった点の記録。

JavaScriptでmp3を鳴らすのはとても簡単だったのに,JScriptの場合はそうでなかった点。

というかそれに関する記述を探すのがとても大変でした。なので書き残し。

ちなみにわたしはDreamweaverを使ってJavascriptの学習をしています。。


Javascriptの場合はAudioオブジェクトがあるのでかなり楽でした。

        var pu = new Audio();
        pu.src = "pu.mp3";
        pu.volume = 0.5;
        pu.play();

これだけで音が鳴らせます。volumeについては0~1の間で設定。ほんとにすごく簡単。

でも,このままではHTAで,つまりJScriptではと言っていいんでしょうか,鳴らせません。

そこでやってるのが

      var pu= new ActiveXObject("MediaPlayer.MediaPlayer");
      pu.Volume=-10000; //音量を0に
      pu.FileName = "pu.mp3";
      pu.Volume=0;  //音量最大に  -10000~0 規定値 -600
      pu.play();

Createobjectに相当するやつなんでしょう。これで似たようにかける。

Audioタグを使ったり,ライブラリを使う方法は難しそうでめんどくさそうで 見送りました。

こちらの問題点はFileNameを設定したタイミングかな,そこで音がいきなりなります。

なので一度Volumeを最小に相当する-10000にして,適当なタイミングで音量をもどして使っています。

ひたすら検索しまくって探してたどりついたので,元記事がもうわかりません。。

見つけたら貼ります。

ここを除けばけっこうあっさりできてた気がしますので,ほんと苦労した内容でした。

年が明けてしばらく経ちますが。

のんびりしてたらもう5日も経ってました。

最近はVBAからは離れていますが,仕事が始まればまたデータ処理で思い出すんだと思います。

VBAからはすこし離れていますが,しばらく前に興味を持ったJavaScriptの勉強をしているところです。

全然わからない → 他人のコードを切り貼りしたり ちょこっとずつ付け足していくとなんとなく物が作れるようになってきました。

とても役に立ちそうな言葉だと思いますし,ブラウザを基本とすれば大概いろいろつくれそうなものなんだなぁというところまでは来ています。

でも,ローカルのファイルの操作となると File API とかいうやつを使わないといけないんだなぁ 面倒だなぁと思いながらそれでもいろいろといじってると,

HTA に出会いました。HTML Applications ってやつですね。

Windows10では少なくとも使えるみたいです。現在の職場ではOSはWindows10なので,少なくとも数年はいける。

JavaScript自身は HTML5CSS とセットでたぶんずーっと使えそうな予感ですので,そちら側はブラウザを元とするものについてはいけそうです。

HTAになると,微妙に JScriptとかVBScriptになり,ちょこっとずつ仕様が変わるので,思った通りにいかないことも多々ありますが,

 ローカルファイルにアクセスできる
 セキュリティに関して制限が甘い(警告類があんまりでない)
 htmlで気軽に書いてるのになんか立派なアプリケーションぽく見える
 もちろんインストールとかいらない

など,私にとってはかなりの魅力を持ったもののようです。

数年戦えますし,JavaScriptの学習にも十二分にもなりますので,OfficeのVBAJavaScriptHTAで遊び続けてものにしようと思います。

JQueryもローカルにライブラリ落としとけば私の職場の環境でもつかえそうです。JQueryまで理解すればたぶん本職ではないプログラマには十分かなぁと思ったり。。

本はひたすら買い漁りました。かなり出費してしまいましたが,長く使える知識になってくれると思っています。

さて,作ったものを載せてみます。

元はPowerPointVBAで作って授業中に使っていたタイマーと同じものなんですが,PowerPointってExcelのThisworkbookに相当するものがないので,他のスライドショーとの共存が難しいです。

基本はOneNote主体で授業を構成しているので,それでもいいんですが,PowerPointも使いたいよなぁと常々思っていました。

最初はブラウザで動くものをJavascriptで作り,満足していたんですが,表示の面でツールバーとかがいろいろ残るので不満が残るものが最初にできました。

CSSJavascriptがフルに使えるという意味でそちらを優先するものも今後いろいろ試してはみますが,タイマーはコンパクトであってほしい。そこは譲れない。

なので,いろいろな制限をのむ形でHTAで作ってみました。 メモ帳に張り付けて 文字コードUTF-8で保存します。拡張子はhtaで。。
音もなるように作ってるんですが,音を鳴らすためにはどこからかmp3を拾ってきて 同じフォルダに pu.mp3 start.mp3 end.mp3 とリネームして入れてください。

www.kurage-kosho.info
こちらのページなどの音がおすすめかも。クレジット表示なしでも使っていいですよ,と書かれていますので,コンパクトさ優先の私にはありがたいです。

アプリケーションを聞いてきたら Microsoft HTML アプリケーションホスト みたいなやつを選んでください。

<!DOCTYPE HTML>
<html lang="ja">
<HTA:APPLICATION SCROLL="no" NAVIGABLE="yes" CAPTION="yes" />

<head>
  <title></title>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <!--CSS-->
  <style type="text/css">
    a.Link{
      text-decoration: none;
      display: block;
      width: 100%;
      height: 100%;
    }
    a.Timer{
      text-decoration: none;
      font-size:160px;
      color:red;
      display: block; 
      line-height: 1.1;
      font-family:"Comic Sans MS", "cursive";
      text-align:center;
    }
    a:hover{background-color:yellow;}
    table {
      border-collapse: collapse
    }
    table td{
      text-align:center;
      width:150px;
      height:50px;
      border:1px solid black;
      font-size: 40px;
    }
  </style>
  <!--JavaScript記述-->
  <script type="text/javascript">
    var spanMyTime;//時間 を 表示 する SPAN
    var spanlog;
    var time0;
    var timer;//経過時間のTimer
    var timeval;
    var pu= new ActiveXObject("MediaPlayer.MediaPlayer");
      pu.Volume=-10000; //音量を0に
      pu.FileName = "pu.mp3";
    var endSound= new ActiveXObject("MediaPlayer.MediaPlayer");
      endSound.Volume=-10000; //音量を0に
      endSound.FileName="end.mp3";
    var startSound=new ActiveXObject("MediaPlayer.MediaPlayer");
      startSound.Volume=-10000;
      startSound.FileName="start.mp3";
    //初期処理(各種DOMを取得)
    function init() {
      timer=null;
      resizeTo(480, 290);
      document.body.style.overflow = "hidden";
      spanMyTime = document.getElementById("mytime");
      spanlog=document.getElementById("log");
      var time = ['10:00', '8:00', '7:00', '6:00', '5:00','4:00', '3:00', '2:00', '1:00', '0:30', '0:20','0:10'];
      var timesec = ['600', '480', '420', '360', '300', '240', '180', '120', '60', '30', '20','10'];
      var html = ['<table>'];
      for (var c = 0; c < 4; c++) {
        html.push('<tr>');
        for (var r = 0; r < 3; r++) {
          html.push('<td><a class="Link" href="#" onclick="startTimer(' + timesec[c+4*r] + ',true)">');
          html.push(time[c + 4 * r]);
          html.push('</a></td>');
        }
      }
      spanMyTime.innerHTML = html.join('');
      spanlog.innerHTML="";
    }

    function startTimer(tm,flg) {
      pu.Volume=0;  //音量最大に  -10000~0 規定値 -600
      pu.stop();
      endSound.Volume=0;  //音量最大に
      endSound.stop();
      startSound.Volume=0;
      startSound.play();
      timeval = tm;
      if (flg==true) time0=tm;
      spanlog.innerHTML="";
      // 既に 開始 し て いる 場合 は、 何 も し ない
      if (timer!= null) {
          stopTimer();
          return;
      }
      spanMyTime.innerHTML = '<a class="Timer"  href="#" onclick="stopTimer()">'+ timeConv(timeval) +'</a>';
      timer = setInterval(interval, 1000);
    }
    function stopTimer() {
      if (timer!= null) {
          clearInterval(timer);
      }
      // timer に null を 代入 する
      timer = null;
      spanMyTime.innerHTML = '<a class="Timer"  href="#" onclick="startTimer('+timeval+',false)">' + timeConv(timeval) + '</a>';
      spanlog.innerHTML='<a href="#" onClick="init()"> BACK </a>    <a href="#" onClick=startTimer('+time0+',false)> ReStart ' + timeConv(time0) + '</a>';
    }
    function interval() {
      // 経過 時間 を 表示
      timeval--;
      spanMyTime.innerHTML = '<a class="Timer"  href="#" onclick="stopTimer()">' + timeConv(timeval) + '</a>';
      if (timeval == 0) {
        clearInterval(timer);
        endSound.play();
        timer=null;
        spanlog.innerHTML='<a href="#" onClick="init()"> BACK </a>    <a href="#" onClick=startTimer('+time0+',false)> ReStart ' + timeConv(time0) + ' </a>';
        spanMyTime.innerHTML='<a class="Timer"  href="#" onclick="startTimer('+time0+')">' + timeConv(timeval) + '</a>';
      } else {
        if (timeval % 5 == 0) pu.play();
        if (timeval < 5) pu.play();
      }
    }
    function timeConv(tm) {
      var fun;
      var byou;
      fun = Math.floor(tm / 60);
      byou = ("0" + tm % 60).slice(-2);
      return fun + ":" + byou;
    }
  </script>
<!--JavaScript ここまで-->
</head>
<body onload="init()">
    <span id="mytime"></span>
    <span id="log"></span>
</body>
</html>

ちなみに,音を鳴らすたびに微妙に時間はずれていきますので 10分のを回すと音によるのかもしれませんが3秒くらいずれました。

気になる方は使えません。私は気にならないのでたぶん使います。

あとはBase64とかいうやつで文字列に直せば音もソースに組み込めるんでしょうか,そんな知識はないのでやってはいませんが,いろいろと奥は深いんでしょうね。。

今後もいろいろ試してみようと思っているところです。