読者です 読者をやめる 読者になる 読者になる
スポンサーリンク

はてなカウンターのアクセス解析を整理して,「人気記事のランキング」を自動生成するバッチ

excel WSH/JScript はてなカウンター

はてなダイアリー」のアクセス解析ツール「はてなカウンター」を開くと,

「ある期間に,どのページのPVが多かったか?」という集計の画面がある。

↓こんな感じ。



アクセスされたURLと,期間内でのアクセス数が並んでいる。

(これだと,URLだけなので,記事のタイトルが分からない。


もし,この画面で集計された内容をもとに

  • ある期間内で,もっとも閲覧されていた記事のランキング・リスト

を自動生成できたら,とても便利だろう。


例えば,対象期間が「2013年の1年間」だとすれば,

「1年間で最も人気があった記事のアクセス数ランキング」を自動生成できる。


そういうバッチを作ってみた。

以下はソースコードと使い方。

そして,このブログ内の記事に対して,2013年のアクセス・ランキングも生成してみる。


必要なファイルは,1個だけ。下記のバッチファイルである。


アクセスランキングを生成.bat

@if(0)==(0) ECHO OFF
cscript.exe //nologo //E:JScript "%~f0" %* > %0\..\log.txt
echo 終了しました。
@pause
GOTO :EOF
@end



function log(s){ WScript.Echo(s); }


// ---- 引数取得


// 引数があるか
if( WScript.Arguments.length == 0 )
{
	// http://language-and-engineering.hatenablog.jp/entry/20110921/p1
	
	log("同一フォルダ上のExcelファイルをドロップしてください。");
	WScript.Quit();
}

// ファイルパスを構築
var filename = WScript.Arguments.Unnamed(0);
	//var ws = WScript.CreateObject("WScript.Shell");
	//var cwd = ws.CurrentDirectory;
	//var filepath = cwd + "\\" + filename;
var filepath = filename;
var fso = WScript.CreateObject("Scripting.FileSystemObject");
var filedir  = fso.GetParentFolderName( filepath );
	// http://jeanne.wankuma.com/tips/vb6/path/getdirectoryname.html

// ファイルが存在するか
if( ! fso.FileExists( filepath ) )
{
	// http://wsh.style-mods.net/ref_filesystemobject/fileexists.htm

	log( filepath + " は無効なファイルパスです。");
	log("同一フォルダ上のExcelファイルをドロップしてください。");
	WScript.Quit();
}
else
{
	log( filepath + " は有効なファイルです。");
}



// ---- Excel起動


var excel = null;
try
{
	// Excel(Kingsoft Spreadsheet)を立ち上げる
	excel = WScript.CreateObject("ET.Application");
		//http://language-and-engineering.hatenablog.jp/entry/20121218/p1
}
catch(e)
{
	// Excel(MS Office)を立ち上げる
	excel = WScript.CreateObject("Excel.Application");
		//http://language-and-engineering.hatenablog.jp/entry/20090717/p1
}
	// 例外設計
	// http://language-and-engineering.hatenablog.jp/entry/20101029/p1

excel.Visible = true;


// 対象ブックを開く
excel.Workbooks.Open( filepath );
var book = excel.Workbooks( excel.Workbooks.Count );

// 最初のシートにハイパーリンクがコピペで列挙されているとする
var sheet_links = book.Worksheets(1);
	// http://3rd.geocities.jp/kaito_extra/Source/ExcelCtrl.html

// 2番目のシートにURLを整理する
var sheet_urls = book.Worksheets(2);



// ---- URLを正規化して格納するためのオブジェクト

var url_dic = {
	
	// 辞書配列の本体
	_arr : []
	,
	
	blog_id : ""
	,
	
	// 総記事数
	get_entry_num : function(){
		return this._arr.length;
	}
	,
	
	// 位置に基づいて記事情報を返す
	get_entry_by_index : function( ind )
	{
		return this._arr[ind];
	}
	,

	// 位置に基づいて,正規化された記事URL情報を返す
	get_normal_url_info_by_index : function( ind )
	{
		var info = this.get_entry_by_index( ind );
		var _normal_url = "http://d.hatena.ne.jp/"
			+ this.blog_id 
			+ "/" 
			+ info.entry_date 
			+ "/" 
			+ ( info.entry_id ? info.entry_id : "" )
		;
		
		return {
			normal_url : _normal_url,
			cnt        : info.cnt
		};
	}
	,

	// URLを受け付けて記録
	record : function( url_raw, cnt )
	{
		var url_info = this._normalize_url( url_raw );
		var entry_date = url_info[1];
		var entry_id   = url_info[2];
		
		// 無効なURLははじく
		if(
			( ! url_info[0] )
			||
			( ! url_info[1] )
		){
			log( "スキップ:" + url_raw );
			return;
		}
		
		this.blog_id   = url_info[0];
		
		// 既に登録済みのURLの別形態URLであれば
		if( this._has_entry( entry_date, entry_id ) )
		{
			this._update_entry_info( entry_date, entry_id, cnt );
		}
		else
		{
			this._add_entry_info( entry_date, entry_id, cnt );
		}
	}
	,
	
	// URLを正規化
	_normalize_url : function( url_raw )
	{
		// 注:「不明」などの文字列や,googleなど他ドメインのサイトのURLが渡ってくる場合もある
	
		if(
			url_raw.match( new RegExp("/mobile\\?", "i" ) )
		)
		{
			// ガラケーからアクセスされた場合
			log("ガラケーからのアクセスを検出");

			// URLからコアな情報だけを抽出
			url_raw.match( 
				new RegExp( 
					"^http://d\\.hatena\\.ne\\.jp/([^/]+)/mobile\\?([^&]*&)?date=([0-9]+)(&section=([^/]*))?(/)?$",
					"i"
				)
			);
				// http://d.hatena.ne.jp/---/mobile?guid=on&date=20130101&section=p1
				// guid=on& は無い場合もある
				
				// http://ratememo.blog17.fc2.com/blog-entry-907.html
				
			log(
				"1:" + RegExp.$1 + "," +
				"2:" + RegExp.$2 + "," +
				"3:" + RegExp.$3 + "," +
				"4:" + RegExp.$4 + "," +
				"5:" + RegExp.$5
			);
			
			var blog_id    = RegExp.$1;
			var entry_date = RegExp.$3;
			var entry_id   = RegExp.$5; // 空の場合もある。日付だけでアクセスされた場合
			
		}
		else
		{
			// PCまたはタッチデバイスからアクセスされた場合
		
			// URLからコアな情報だけを抽出
			url_raw.match( 
				new RegExp( 
					"^http://d\\.hatena\\.ne\\.jp/([^/]+)/(touch/)?([0-9]+)(/)?([^/]*)(/)?$",
					"i"
				)
			);
			
			var blog_id    = RegExp.$1;
			var entry_date = RegExp.$3;
			var entry_id   = RegExp.$5; // 空の場合もある。日付だけでアクセスされた場合
				// 201301 のように,月だけで指定された場合は,アクセス集計に数えないものとする。
			
			if( entry_id )
			{
				// URL末尾の?以降のパラメータを除去
				// http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13118651288
				
				entry_id.match( /^([^\?]+)(\?.*)?$/ );
				entry_id = RegExp.$1;
			}
		}
		
		// 重要な情報だけを返す
		return [ blog_id, entry_date, entry_id ];
	}
	,

	// エントリが辞書に登録済みか
	_has_entry : function( _entry_date, _entry_id )
	{
		for( var i = 0; i < this._arr.length; i ++ )
		{
			var info = this.get_entry_by_index(i);
			if(
				( info.entry_date == _entry_date )
				&&
				( info.entry_id   == _entry_id )
			)
			{
				// もうある
				return true;
			}
		}
		
		// まだない
		return false;
	}
	,

	// エントリ情報を追加
	_add_entry_info : function( _entry_date, _entry_id, _cnt )
	{
		if( 
			( ! _entry_date )
			||
			( ! _cnt )
		)
		{
			log( 
				"無効なデータを追加できません。" 
				+ "entry_date=" + _entry_date
				+ ", cnt=" + _cnt
			);
			WScript.Quit();
		}
	
		this._arr.push(
			{
				entry_date : _entry_date,
				entry_id   : _entry_id,
				cnt        : _cnt
			}
		);
	}
	,

	// エントリ情報を更新
	_update_entry_info : function( _entry_date, _entry_id, _cnt )
	{
		// 同一エントリ情報を探して数字だけ更新
		for( var i = 0; i < this._arr.length; i ++ )
		{
			var info = this.get_entry_by_index(i);
			if(
				( info.entry_date == _entry_date )
				&&
				( info.entry_id   == _entry_id )
			)
			{
				// 加算
				info.cnt += _cnt;
				
				log( 
					"重複:" 
					+ _entry_date + "/" + _entry_id + "のカウントを" 
					+ _cnt + "から" + info.cnt + "に調整"
				)
			}
		}
	}
	,
	
	// 全記事情報がそろった時点で,登録情報を最終チェックする
	finalize_data : function()
	{
		// 記事IDを持っていない記事情報について,
		// 可能なら記事IDを付与する。
		for( var i = 0; i < this._arr.length; i ++ )
		{
			var info = this.get_entry_by_index(i);
			if( ! info.entry_id )
			{
				var entry_date = info.entry_date;
				var entries = this._find_entries_by_entry_date( entry_date );
				
				// 適切な記事IDを探す
				var ids = [];
				for( var j = 0; j < entries.length; j ++ )
				{
					// 有効な記事IDを持っていれば候補として考慮
					if( entries[ j ].entry_id )
					{
						ids.push( entries[ j ].entry_id );
					}
				}
				// 記事IDの候補があれば
				if( ids.length > 0 )
				{
					// デフォルトでは,日付内で下から順にp1, p2, p3... と記事IDが付与される。
					// 日付URLを開くと最初に見えるのは一番上の記事だから,最後の記事IDを採用する。
					ids.sort();
					var new_entry_id = ids[ ids.length - 1 ];
					
					// 新しい記事IDを基に数値を加算
					this._update_entry_info( entry_date, new_entry_id, info.cnt );
					info.delete_flag = true; // 削除予約
					
					log(entry_date + "の日付の記事に,記事IDとして" + new_entry_id + "を付与");
				}
				else
				{
					// 記事IDの候補がなければしょうがないので,日付URLのまま放置する。
					log(entry_date + "の日付の記事には記事IDを付与せず");
				}
			}
		}
		// 上記で削除予約した情報を削除
		for( var i = this._arr.length - 1; i >= 0; i -- )
		{
			if( this.get_entry_by_index(i).delete_flag )
			{
				// 配列から要素を削除
				this._arr.splice( i, 1 );
					// http://javascript-memo.seesaa.net/article/24832361.html
			}
		}
		
	}
	,
	
	// 日付をキーにして記事情報を検索する
	_find_entries_by_entry_date : function( entry_date )
	{
		var ret = [];
		for( var i = 0; i < this._arr.length; i ++ )
		{
			var info = this.get_entry_by_index(i);
			if( info.entry_date == entry_date )
			{
				ret.push( info )
			}
		}
		
		return ret;
	}

};



// ---- URLを読み取って整理


var continue_flag = true;
var y = 2;
while( continue_flag )
{
	// 該当セルが空でなければ読み取りを継続
	if( sheet_links.Cells( y, 1 ).Value )
	{
		log( y + "行目のハイパーリンクを検査" );
	
		// このセルの範囲にハイパーリンクが存在するか
		// http://hinden.at.webry.info/201104/article_12.html
		var links = sheet_links.Cells( y, 1 ).Hyperlinks;
		if( links.Count > 0 )
		{
			// 正規化前のURLを取得
			var url_raw = links(1).Address;
				// http://okwave.jp/qa/q2294383.html
			
			// 記録
			url_dic.record( url_raw, sheet_links.Cells( y, 2 ) );
			log( "URLを記録 [" + url_dic.get_entry_num() + "] " + url_raw );
		}
		
		// 次の行へ
		y ++;
	}
	else
	{
		// 空セルに到達したので読み取りを中断
		continue_flag = false;
	}
}
log("全URLの記録が完了");


// 全記事情報を整理
url_dic.finalize_data();
log("記事情報の整理が完了");


// ---- 整理済みのURLをシートに書きだし


// 登録順に書きだし
for( var i = 0; i < url_dic.get_entry_num(); i ++ )
{
	var info = url_dic.get_normal_url_info_by_index( i );

	var y = i + 1;
	sheet_urls.Cells( y, 1 ).Value = info.normal_url;
	sheet_urls.Cells( y, 2 ).Value = info.cnt;
}
log("全URLの書き出しが完了");


// シート上で,アクセス数の多い順にソート(URL統合のため順序が変動しているから)
var xlDescending = 2;
	// http://msdn.microsoft.com/en-us/library/office/ff834316.aspx
sheet_urls.Range( 
	"A1:B" + url_dic.get_entry_num() 
).Sort(
	sheet_urls.Cells(1, 2), // アクセス数をキーに降順で並び替え
	xlDescending 
);
	// http://www.excel.studio-kazu.jp/kw/20091227224357.html
log("ソートが完了");


// ---- 全URLにタイトルを付与する


// IEで全URLを調査する


// IEがビジー状態の間待ちます
function waitIE( ie )
{    
    while( ( ie.Busy ) || ( ie.readystate != 4 ) )
    {
        WScript.Sleep( 100 );
    }
    
    WScript.Sleep( 1000 )
}


// IE起動
var ie = WScript.CreateObject("InternetExplorer.Application")
ie.Navigate( "http://www.google.co.jp/" );
ie.Visible = true;
waitIE( ie );
log("ブラウザでのアクセスを開始します。");



// シート掲載順にアクセス
for( var i = 0; i < url_dic.get_entry_num(); i ++ )
{
	var y = i + 1;
	var target_url = sheet_urls.Cells( y, 1 ).Value;

	// 開く
	log("[" + y + "] " + target_url + "を開きます");
	ie.Navigate( target_url );
	waitIE( ie );
	
	// タイトルを抽出して記録
	var tit = ie.Document.title;
	log( "タイトルは " + tit );
	sheet_urls.Cells( y, 3 ).Value = tit;
}
log("全URLのタイトル抽出が完了");


// IEの制御を破棄
ie.Quit();
ie = null;



// ---- 終了


// ブックを保存
excel.DisplayAlerts = false;
book.SaveAs( filepath );


// Excelを閉じて終了
//excel.Quit();
//excel = null;

log("全処理が終了");

ここまでがソースコード。


使い方としては,まず上記の内容をBATファイルとして保存。


そして,BATと同じフォルダ上に,適当なExcelファイルを新規作成。

そのエクセルの1シート目に,「はてなカウンター」の内容を貼り付ける。

下記の画面キャプチャみたいに。



アクセス解析の画面のテーブル内容を,左上にそのままコピペすればよい。

行数は,いくらでも下のほうまで続けてよい。


で,そのExcelファイルを,先ほどのBATファイルにドロップする。

これで処理が開始〜完了する。


このバッチがやってくれる事は:

  • まず,アクセス解析画面のコピペの中から,ハイパーリンクをURLに変換し,
  • PC用・スマホ用・ガラケー用などの異なるURLを統合して,1つのURLとしてアクセス数を合計し直し
  • 統合されたURLのそれぞれに対して,ブラウザ(IE)からアクセスして,記事のタイトルを取得し,Excelのシート上に記録する。

すると,Excelファイルの2シート目には,

  • 統合されたURL
  • PV数
  • 記事のタイトル

が並ぶ。

4列目には,下記のようなExcel関数を書いて,下までオートフィルすればよい。

="&#9654;第"&ROW()&"位:"&CHAR(10)&SUBSTITUTE(C1," - 主に言語とシステム開発に関して","")&" <img src=http://b.hatena.ne.jp/entry/image/"&A1&">"&CHAR(10)&A1&CHAR(10)&"-"&B1&" pv"&CHAR(10)&CHAR(10)


これで,ランキングのHTMLが生成できた。

期間や解析対象などを変えつつ,いくらでも使いまわせる。


とりあえず,本ブログの場合の実行結果を丸ごとペーストしてみる。


2013年にアクセス数が多かった記事のランキングとしての出力結果:

▶第1位:
開発に役立つ,BATファイルの書き方・パターン集 (コマンドプロンプトの定石を体系的に学び,バッチ中級者になろう)
http://language-and-engineering.hatenablog.jp/entry/20130502/PatternsOfMSDOSo...

  • 86921 pv


▶第2位:
Tortoise SVNの使い方を覚えてもらうためのページ (初級,中級)
http://language-and-engineering.hatenablog.jp/entry/20110114/p1

  • 23715 pv


▶第3位:
ネットワーク図の書き方 (物理/論理構成図の作成手順と,Excelで使えるアイコン素材のリンク集)
http://language-and-engineering.hatenablog.jp/entry/20110916/p1

  • 16947 pv


▶第4位:
今から3分で jmeter の使い方を身に付ける  (負荷テスト入門)
http://language-and-engineering.hatenablog.jp/entry/20081014/1223905380

  • 16247 pv


▶第5位:
J:COMでネット利用時に,無線LANルータを導入し,PCとiPadからWi-Fi接続する方法 (ケーブルモデムにつながらない時のための,設定手順のメモ)
http://language-and-engineering.hatenablog.jp/entry/20111015/p1

  • 11496 pv


▶第6位:
Excel VBAで,グラフを自動で描画しよう(データ範囲を動的に変える) + ソフトウェアの品質保証について
http://language-and-engineering.hatenablog.jp/entry/20090516/p1

  • 10367 pv


▶第7位:
GoFの23のデザインパターンを,Javaで活用するための一覧表 (パターンごとの要約コメント付き)
http://language-and-engineering.hatenablog.jp/entry/20120330/p1

  • 9186 pv


▶第8位:
JavaScriptの動かないコード (中級編) clickイベントを強制的に発生させたい (fireEvent/createEventの使い方)
http://language-and-engineering.hatenablog.jp/entry/20090907/p1

  • 8929 pv


▶第9位:
Excel VBAのマクロを,複数のブックから利用する方法 (標準モジュールをブックの外部で管理して,共通ライブラリとして読み込み)
http://language-and-engineering.hatenablog.jp/entry/20090731/p1

  • 8905 pv


▶第10位:
Androidアプリで,HTTP通信のPOSTリクエストをする汎用クラス (文字化け無し+非同期タスク)
http://language-and-engineering.hatenablog.jp/entry/20111121/p1

  • 8783 pv


▶第11位:
コマンドラインからプロセスを起動・終了する方法 (環境変数とレジストリについて)
http://language-and-engineering.hatenablog.jp/entry/20081028/1225160338

  • 8131 pv


▶第12位:
Androidアプリをマーケットに公開する方法の作業手順メモ (リリース時とアップグレード時のチェックリスト)
http://language-and-engineering.hatenablog.jp/entry/20120310/AndroidMarketRel...

  • 7803 pv


▶第13位:
Android SDKプログラミング APIリファレンスのリンク集
http://language-and-engineering.hatenablog.jp/entry/20130302/AndroidSDKProgra...

  • 7679 pv


▶第14位:
Linux上でシェルが実行される仕組みを,体系的に理解しよう (bash 中級者への道)
http://language-and-engineering.hatenablog.jp/entry/20110617/p1

  • 7675 pv


▶第15位:
コマンドプロンプトで,暗記するべき10の必須コマンド  (前半) ファイル処理系
http://language-and-engineering.hatenablog.jp/entry/20081001/1222857265

  • 7035 pv


▶第16位:
今から3分で,Smartyの使い方を覚えよう (PHPテンプレートエンジンの入門)
http://language-and-engineering.hatenablog.jp/entry/20130107/SmartyPHPTemplat...

  • 6728 pv


▶第17位:
韓国語の文字(ハングル)の覚え方。母音・子音ごとに図解で暗記
http://language-and-engineering.hatenablog.jp/entry/20130708/KoreanAlphabetsV...

  • 6697 pv


▶第18位:
なんとなくCSSを使っている人が,CSS中級者になるために (「崩れないレイアウト」のセオリー)
http://language-and-engineering.hatenablog.jp/entry/20110216/p1

  • 6665 pv


▶第19位:
Excel VBAのマクロで,IEを自動操作しよう (DOMセレクタ関数をVBAで自作)
http://language-and-engineering.hatenablog.jp/entry/20090710/p1

  • 6504 pv


▶第20位:
逆コンパイル + 逆アセンブル のための5つの無料ツール
http://language-and-engineering.hatenablog.jp/entry/20081008/1223384382

  • 6367 pv


▶第21位:
Word VBA の入門用リンク集 (ワードマクロの,サンプルコードやリファレンス)
http://language-and-engineering.hatenablog.jp/entry/20100314/p1

  • 6365 pv


▶第22位:
台湾語のあいさつなど日常会話フレーズ集 (ピンインと声調,カタカナ付き)
http://language-and-engineering.hatenablog.jp/entry/20130308/BasicGreetingsIn...

  • 6347 pv


▶第23位:
ハングル検定5級に独学で合格するための対策リンク集 (過去問や単語など)
http://language-and-engineering.hatenablog.jp/entry/20130610/KoreanLicenseLev...

  • 6191 pv


▶第24位:
Linux上にSambaで共有フォルダを作り,Windowsから開発環境として利用しよう (環境構成のわかりやすい図解付き)
http://language-and-engineering.hatenablog.jp/entry/20110820/p1

  • 6047 pv


▶第25位:
JScript / VBScript (WSH)で,IEを自動操作しよう
http://language-and-engineering.hatenablog.jp/entry/20090713/p1

  • 5904 pv


▶第26位:
韓国語(ハングル)で会話するための,最初歩の必須フレーズ
http://language-and-engineering.hatenablog.jp/entry/20130707/KoreanFirstStepP...

  • 5698 pv


▶第27位:
今から1時間で,Androidアプリの開発環境を構築し,Windows上でサンプルを動作させる手順
http://language-and-engineering.hatenablog.jp/entry/20110724/p1

  • 5590 pv


▶第28位:
メモリの中身を読んでみよう (プロセスをダンプ+解析する方法)
http://language-and-engineering.hatenablog.jp/entry/20081019/1224341559

  • 5293 pv


▶第29位:
今から1時間で,64ビットWindows 7上にAndroid開発環境を構築し,サンプルを動作させる手順 (※4.x系のSDKを使用)
http://language-and-engineering.hatenablog.jp/entry/20121017/AdnroidDevelopme...

  • 5175 pv


▶第30位:
コマンドプロンプトで,暗記するべき10の必須コマンド (後半)ネットワーク系
http://language-and-engineering.hatenablog.jp/entry/20081002/1222908187

  • 5062 pv

↑こういう記事ランキング表が手軽に作れるわけだ。


※なお,本記事は「ランキング生成のためのバッチ」についての記事だから,

本ブログの2013年の人気記事については,別のエントリで改めて言及する。



このバッチの面倒な所は,たまにブラウザが止まってしまうところ。何せIEだから・・・。

その場合,F5を押してリロードすれば処理が再開する。


バッチのソースコードの参考情報:


BATとWSHのコードを1ファイルに混在させるためのshebang記法
http://computer-technology.hateblo.jp/entry/20131025/p1


JScript / VBScript (WSH)で,IEを自動操作しよう
http://language-and-engineering.hatenablog.jp/entry/20090713/p1


URLの末尾のfb_locale=ja_jpはなに?
http://detail.chiebukuro.yahoo.co.jp/...

  • 最近、どのブログサービスでもURLの末尾にfb_locale=ja_jpが付いている


Internationalization : Facebook開発者向けドキュメントの日本語訳とTips
http://facebook-docs.oklahome.net/arc...

  • Open GraphオブジェクトのクローラーはURLにfb_localeパラメータを付加(例:?locale=en_US)し、X-Facebook- Localeヘッダも渡します。


PROBLEM retrieve fb_locale parameter in the URL OR the X-Facebook-Locale header | GEEK'S BLOG
http://www.raleche.com/content/proble...

  • retrieve fb_locale parameter


Kennt jemand das Url anhängsel ?fb_locale=de_DE - ABAKUS
http://www.abakus-internet-marketing....


JavaScriptの関数オブジェクト(1/2) | JavaScriptのQ&A【OKWave】
http://okwave.jp/qa/q7261969.html

  • RegExpは組み込み関数の中で唯一シングルトンで,正規表現のマッチがヒットしない場合は上書きされないため、前回の結果が残っている,という点に注意


正規表現を使いこなす
http://www.web3d-club.net/jikken/Java...

  • グループでマッチングした文字列は検索実行後も記憶されており,参照するにはJavaScriptの場合「RegExp.$1」で取り出す


$1...$9 プロパティ (RegExp) (JavaScript)
http://msdn.microsoft.com/ja-jp/libra...

  • $1...$9 のプロパティの値は、かっこで囲まれたパターンの検索が成功するたびに変更されます
  • 正規表現パターン内に指定できるかっこで囲んだ部分の数に制限はありませんが、保存されるのは最後に見つかった 9 つだけ


文字列結合時に改行を入れたい−CHAR関数:Excel(エクセル)の関数・数式の使い方-文字列
http://www.relief.jp/itnote/archives/...

  • Excelのセル内の改行コードは CHAR(10)


言葉を簡単に入れ替えるには?SUBSTITUTE関数で文字を置き換えてみよう - FMVサポート : 富士通
http://azby.fmworld.net/usage/excel-f...

  • =SUBSTITUTE(文字列,検索文字列,置換文字列,対象)

関連する記事:

2012年のトップ記事のまとめ
http://language-and-engineering.hatenablog.jp/entry/20130103/p1


はてなダイアリーに執筆した記事一覧を,表形式に整理するブックマークレット (アーカイブページを,Excelに貼り付けやすく整形加工)
http://language-and-engineering.hatenablog.jp/entry/20140102/p1


はてブのマイページから,情報を一括して整形・抽出するブックマークレット
http://language-and-engineering.hatenablog.jp/entry/20131229/p1


2008年の記事 TOP 5
http://language-and-engineering.hatenablog.jp/entry/20081231/1230726519