WSH/JScriptで,Excelのデータを自動でグラフ描画 (題材:はてなカウンターのアクセス数を週ごとにグラフ化)
WSH/JScriptを使って,エクセルのデータをグラフ化しよう。
表計算データから,バッチで自動的にグラフを描画できる。
題材として,上記のような「ブログのアクセス数の推移」を
折れ線グラフにしてみる。
ここで掲載するバッチの処理は
- はてなカウンターから,自動的にアクセス数を収集する。
- 収集したデータを,Excelに記録する。
- Excelに記録したデータをグラフ化して,ファイル内に保存する。
という処理を行なう。
グラフ生成部分のコードは,とても簡単。下記に抜粋:
// グラフを作成 var chs = sheet.ChartObjects(); var g = chs.Add( 30, 50, 500 + 20 * (x - 2), 300 ); g.Name = "アクセス数の遷移"; // データ範囲をセット(左上と右下) var xlRows = 1; // データが横方向に並んでいる場合 var xlColumns = 2; g.Chart.SetSourceData( sheet.Range( sheet.Cells(2, 2), sheet.Cells(3, x) ), xlRows ); // x軸の項目軸範囲をセット g.Chart.SeriesCollection(1).XValues = sheet.Range( sheet.Cells(1, 2), sheet.Cells(1, x) ); // オプションをセット var xlLine = 4; g.Chart.ChartType = xlLine // 折れ線 // 系列名をセット g.Chart.SeriesCollection(1).Name = "PV"; g.Chart.SeriesCollection(2).Name = "ユニーク";
これだけで,WSHでグラフ描画できる。VBScriptの場合も同じ。
はてなカウンターから,週ごとのアクセス数をグラフ化するバッチ
週ごとのアクセス数をグラフ化.bat
@echo off rem はてなカウンターから,週ごとのアクセス数を抽出してグラフ化するバッチ rem ---- 設定事項 ---- rem カウンターを特定する情報 SET HATENA_ID=(はてなID) SET COUNTER_ID=(はてなカウンター内の番号) rem 集計の開始日 SET START_YYYY=2014 SET START_MM=01 SET START_DD=01 rem ---- 処理 ---- echo 処理開始時刻: %date% %time% > log.txt SET CURRENT_DIR="%~dp0" cscript.exe //nologo //E:JScript counter-weekly-access.js ^ "%CURRENT_DIR%" "%HATENA_ID%" "%COUNTER_ID%" ^ %START_YYYY% %START_MM% %START_DD% echo 終了しました。 echo 処理終了時刻: %date% %time% >> log.txt pause
counter-weekly-access.js
/* はてなカウンターから,対象月のレポートを作成してExcelに記録するバッチ ・該当はてなIDにログイン済みであること ・呼び出し側のバッチ内の設定事項を調整すること */ // 引数を取得 var curr_dir = WScript.Arguments.Unnamed(0); var hatena_id = WScript.Arguments.Unnamed(1); var counter_id = WScript.Arguments.Unnamed(2); var start_year = WScript.Arguments.Unnamed(3); var start_month = WScript.Arguments.Unnamed(4); var start_date = WScript.Arguments.Unnamed(5); // ---- 設定事項 // 情報を記録するExcelファイル名 var today = new Date(); var xls_filename = "weekly_graph_" + hatena_id + "_" + counter_id + "_" + ( today.getFullYear() ) + "-" + ( today.getMonth() + 1 ) // 人間の見る世界なのでMonthに+1する事に注意 + "-" + ( today.getDate() ) + "_since_" + start_year + "_" + start_month + "_" + start_date + ".xls" ; // ---- 前処理 // グローバル変数を定義 var excel = null; // 新規ブック生成 var file_path = curr_dir + xls_filename; var book = createNewBookHere( file_path ); var sheet = getNewSheet( book, "calc" ); // IE起動 var ie = getIE(); // ---- 記録 // グラフ終了週の開始日曜 var previousSunday = getWeekStartSunday( today ); var calcEndDate = addDate( previousSunday, -7 ); // グラフ開始週の開始日曜 var userStartDate = new Date( start_year, start_month, start_date ); var calcStartDate = getWeekStartSunday( userStartDate ); // 指定期間でグラフを作成 recordWeeklyAccessGraph( sheet, calcStartDate, calcEndDate ); // ---- 終了 quitIE( ie ); saveBook( book ); log("全処理が終了"); // --------------- 以下はユーティリティ関数 --------------- // ログ出力 function log(s){ WScript.Echo(s); } // 2ケタで0埋めした文字列を返す function dig2( num ) { if( num < 10 ) { return "0" + num; } else { return "" + num; } } // ----- 日付演算 ----- // ある日付が属する週の,週が開始する日曜日を求める function getWeekStartSunday( target_date ) { var diff_day_count = target_date.getDay(); // 日曜日まで曜日をさかのぼる return addDate( target_date, - diff_day_count ); // http://javascript123.seesaa.net/article/297521353.html } // 日付に対し,日にちを加算する function addDate( orig_date, day_count ) { var result_date = new Date( orig_date.getFullYear(), // http://kawara-tan.blogspot.jp/2009/10/javascript-getyeargetfullyear.html orig_date.getMonth(), // 人間の見ない世界なのでMonthに+1しない事に注意 orig_date.getDate() ); // 指定日数分のミリ秒を加える var diff_ms = day_count * ( 1000 * 60 * 60 * 24 ); result_date.setTime( result_date.getTime() + diff_ms ); // http://www.hoge256.net/2007/08/64.html return result_date; } // ----- Excel操作 ----- // カレントフォルダにExcelを新規生成し,ブックを返す。 function createNewBookHere( file_path ) { var fso = WScript.CreateObject("Scripting.FileSystemObject"); // ファイルが存在するか if( fso.FileExists( file_path ) ) { log( "既にファイルが存在します。実行停止"); WScript.Quit(); } else { log( "記録対象:" + file_path ); } // Excel起動 try { excel = WScript.CreateObject("ET.Application"); } catch(e) { excel = WScript.CreateObject("Excel.Application"); } excel.Visible = true; // 新規ブック excel.Workbooks.Add(); var book = excel.Workbooks( excel.Workbooks.Count ); // 新規ブックを保存 excel.DisplayAlerts = false; book.SaveAs( file_path ); log("とりあえずブックを保存しました"); return book; } // 新しいシートを追加して返す function getNewSheet( book, new_name ) { var sheet = book.Worksheets.Add(); // http://officetanaka.net/excel/vba/sheet/sheet03.htm sheet.Name = new_name; return sheet; } // ブックを保存 function saveBook( book ) { excel.DisplayAlerts = false; book.SaveAs( file_path ); log( "ブックを保存しました。" ); } // ----- IE操作 ----- // IE起動 function getIE() { var ie = WScript.CreateObject("InternetExplorer.Application") ie.Visible = true; ie_goto_url( ie, "http://www.google.co.jp/" ); log("ブラウザでのアクセスを開始します。"); return ie; } // IEがビジー状態の間待ちます function ie_wait_while_busy( ie, _url ) { var timeout_ms = 45 * 1000; var step_ms = 100; var total_waited_ms = 0; while( ( ie.Busy ) || ( ie.readystate != 4 ) ) { WScript.Sleep( step_ms ); // タイムアウトか? total_waited_ms += step_ms; if( total_waited_ms >= timeout_ms ) { log( "警告:タイムアウトのため,リロードします。(" + ie.LocationURL + ")" ); // どこかに移動中なら,そこへの移動を再試行 if( _url ) { log( _url + "への遷移を再試行"); ie_goto_url( ie, _url ); } else { log( "リロード中"); // 移動先が明示されていなければリロード ie.document.location.reload( true ); ie_wait_while_busy( ie ); } break; } } WScript.Sleep( 1000 ) } // ページを移動 function ie_goto_url( ie, url ){ ie.Navigate( url ); ie_wait_while_busy( ie, url ); } // IEの制御を破棄 function quitIE( ie ) { ie.Quit(); ie = null; } function $( ie, elem_id ) { return ie.document.getElementById( elem_id ); } // ----- はてなカウンター操作 ----- // はてなカウンターの週アクセスのURLを返す。 function getCounterWeeklyAccessURL( target_year, target_month, target_date ) { var counter_url = "http://counter.hatena.ne.jp/" + hatena_id + "/report?cid=" + counter_id + "&date=" + target_year + "-" + dig2( target_month ) + "-" + dig2( target_date ) + "&mode=access&type=weekly" ; return counter_url; // http://counter.hatena.ne.jp/XXXXX/report?cid=1&date=2014-02-09&mode=access&type=weekly } // 指定期間のアクセス数のグラフを作成 function recordWeeklyAccessGraph( sheet, calcStartDate, calcEndDate ) { log( "開始日:" + calcStartDate ); log( "終了日:" + calcEndDate ); var calcDate = new Date( calcStartDate ); sheet.Cells( 1, 1 ).Value = "期間"; sheet.Cells( 2, 1 ).Value = "PV"; sheet.Cells( 3, 1 ).Value = "ユニーク"; // シート上に期間内のアクセス数を記録 var continue_flag = true; var x = 2; while( continue_flag ) { // 該当週の情報へジャンプ var target_url = getCounterWeeklyAccessURL( calcDate.getFullYear(), calcDate.getMonth() + 1, calcDate.getDate() ); ie_goto_url( ie, target_url ); // 該当週のアクセス数を抽出 var tds = $( ie, "hourlyreport" ).getElementsByTagName("td"); var count_pv = tds[0].innerText; var count_unique = tds[1].innerText; // 書き込み sheet.Cells( 1, x ).Value = calcDate.getFullYear() + "/" + ( calcDate.getMonth() + 1 ) + "/" + calcDate.getDate() ; sheet.Cells( 2, x ).Value = count_pv; sheet.Cells( 3, x ).Value = count_unique; sheet.Columns( x ).AutoFit(); // http://home.att.ne.jp/zeta/gen/excel/c04p54.htm // 次の週へ calcDate = addDate( calcDate, 7 ); x ++; // 継続するか if( calcDate >= calcEndDate ) { continue_flag = false; } } // グラフを作成 // http://language-and-engineering.hatenablog.jp/entry/20090516/p1 var chs = sheet.ChartObjects(); // http://vbsguide.seesaa.net/article/144812178.html var g = chs.Add( 30, 50, 500 + 20 * (x - 2), 300 ); g.Name = "アクセス数の遷移"; // データ範囲をセット(左上と右下) var xlRows = 1; var xlColumns = 2; // http://9013.teacup.com/tokyoinfbox/bbs/20 g.Chart.SetSourceData( sheet.Range( sheet.Cells(2, 2), sheet.Cells(3, x) ), xlRows ); // x軸の項目軸範囲をセット g.Chart.SeriesCollection(1).XValues = sheet.Range( sheet.Cells(1, 2), sheet.Cells(1, x) ); // オプションをセット var xlLine = 4; // http://officetanaka.net/excel/vba/graph/06.htm g.Chart.ChartType = xlLine // 折れ線 /* g.Chart.HasTitle = true g.Chart.ChartTitle.Characters.Text = chart_title g.Chart.Axes(xlCategory, xlPrimary).HasTitle = true g.Chart.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = x_title g.Chart.Axes(xlValue, xlPrimary).HasTitle = True g.Chart.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = y_title */ // 系列名をセット g.Chart.SeriesCollection(1).Name = "PV"; g.Chart.SeriesCollection(2).Name = "ユニーク"; }
関連する記事:
Excel VBAで,グラフを自動で描画しよう(データ範囲を動的に変える) + ソフトウェアの品質保証について
http://language-and-engineering.hatenablog.jp/entry/20090516/p1
JavaScript で,クリックした座標に点を追加できるグラフチャートを描画する方法 (jQuery のプラグイン jquery.sparklines / jquery.flotの使い方)
http://language-and-engineering.hatenablog.jp/entry/20081120/1227114053
日経平均株価の下落ぶりをMIDIサウンドで味わう (コマンドラインでMIDI生成)
http://language-and-engineering.hatenablog.jp/entry/20081027/1225038111