Hatena::ブログ(Diary)

bonlife このページをアンテナに追加 RSSフィード

言及ISBN/ASIN
  • Ringo EXPO 08 [DVD]
  • 三文ゴシップ
  • my way
  • ビジネスパーソンのための話し方入門 (日経文庫)
  • ザ・グーグルウェイ グーグルを成功へ導いた型破りな戦略
  • 考え・書き・話す3つの魔法
  • 自分の答えのつくりかた―INDEPENDENT MIND

2006-02-12 朝から第3のビールを飲んでます。

秀丸マクロでEXCELのPROPER関数を実装

SNYDER'Sにハマっているbonlifeです。昨夜、人力検索はてなの質問(http://www.hatena.ne.jp/1139656587)に不正確な回答をしてしまいました。まぁ、いつものことです。再回答しましたが、開かれない可能性もあるのでこちらにも書いておきます。(再回答の内容にもゴミコードが含まれてます…。ガビョーン。)EXCELでのPROPER関数OracleでのINITCAPのような英単語の先頭を大文字、それ以外を小文字にするマクロを作成いたしました。

disabledraw;
// 全て選択し、小文字に変換
selectall;
filter "" , "ToLower";
// 単語の先頭の文字を大文字に変換
gofiletop;
while (code != eof ){
	beginsel;
	right;
	endsel;
	filter "" , "ToUpper";
	escape;
	left;
	wordright;
}
gofiletop;
enabledraw;

秀丸がVer 5.0以上の場合、変換モジュールが標準で組み込まれており、大文字への変換(ToUpper)、小文字への変換(ToLower)は簡単に実行できます。wordrightの動きと改行の関係がよくつかめておらず、最初はleftを入れておりませんでした。その結果、改行直後の単語(つまり行頭の単語)の先頭の文字が大文字になりませんでした。色々試していると改行も1つのwordとして扱われているようでしたので、leftで元の位置に戻した後、wordrightで次の単語を指定してみました。すると求める動きをするようになりました。めでたし、めでたしです。最初whileの次の行にgowordtopを入れていたのですが、wordrightした時に次の単語の先頭にカーソルが移動しており、gowordtopは全く無意味だということが分かりましたので、その部分も削除いたしました。

後はお好みに応じて選択範囲に対して処理をするように改訂をしたり、マクロ実行後のカーソルの位置を元に位置やファイルの最後に変更するなどしてみてはいかがでしょうか。それにしても秀丸マクロ、便利ですね。

EXCELのデータをテキストに貼り付ける際に余計なダブルクォートを削除

休みの日に限って勤勉なbonlifeです。人力検索はてなの質問(http://www.hatena.ne.jp/1137168136)に適当な回答をしていたのですが、ちょっと見直してみました。セル内にAlt+Enterで入力できる改行がある場合、そのセルコピーすると先頭行の最初と最終行の最後にダブルクォートが挿入されます。この改行を削除するための秀丸マクロを書いてみました。どういったケースで活用できるのかは、イマイチ不明ですが、EXCELで表示されている内容をそのまま秀丸に貼り付けることが出来ます。処理速度は…遅いです。表示の制御を行っていないせいもあるとは思いますが、なんとも遅いです。

http://d.hatena.ne.jp/junsub777/20060118

こちらでいくつかアイディアを出されている方がいらっしゃいますが、私のやり方は

  • 貼り付けた内容から、"を抜く
  • コピーした内容から、"を抜く

の間ぐらいでしょうか。全て貼り付けた後、処理を行う方が速いのかな、とも思ったのですが、その場合、どうやって貼り付けた範囲を覚えておいて、先頭行と最終行で処理を分けるのかが分からなかったんですよね…。仕方なく、クリップボードの内容を配列に1つずつ入れて、配列の値を取り出す際に適宜ダブルクォートを削除する実装にしてみました。もっとスマートなやり方があるかしら。

// クリップボード操作開始
beginclipboardread;

// 配列$a[]にクリップボードの内容を一行ずつ取り込み
#i=0;
$a[#i]=getclipboard;

while($a[#i]!=""){
	#i=#i+1;
	$a[#i]=getclipboard;
}

// 配列$a[]が空の場合、マクロを終了
if ($a[0]==""){
	endmacro;
}

// 配列$a[]の大きさが1の場合、そのまま貼り付け
if ($a[1]==""){
	insert $a[0];
} else {
// 配列$a[]の大きさが2以上の場合、以下の処理を実行
//   一行目の処理
//   (1) ダブルクォート2つを1つに戻す
//   (2) 行頭のダブルクォートを削除
	insert $a[0];
	up 1;
	selectline;
	replaceall "\"\"", "\"" , regular , inselect;
	selectline;
	replaceall "^\"", "" , regular , inselect;
	down 1;
//   二行目から最終行の前の行までの処理
//   (1) ダブルクォート2つを1つに戻す
	#j=1;
	while($a[#j+1]!=""){
		insert $a[#j];
		up 1;
		selectline;
		replaceall "\"\"", "\"" , regular , inselect;
		down 1;
		#j=#j+1;
	}
//   最終行の処理
//   (1) ダブルクォート2つを1つに戻す
//   (2) 行末のダブルクォートを削除
	insert $a[#j];
	up 1;
	selectline;
	replaceall "\"\"", "\"" , regular , inselect;
	selectline;
	replaceall "\"$", "" , regular , inselect;
	down 1;
}

秀丸マクロ変数記憶するためのメモリは640KBなので、あまり大きなデータは扱えないので注意が必要です。また、クリップボード内に一行の長さが4KB以上のデータは4KBでデータが切られてしまうらしいです。秀丸マクロヘルプには「ぶっちぎられてしまいます。」と書いてあります。すごい表現ですね…。

ちなみに、EXCELセル内での改行を検索する場合、検索文字列を入力する部分でCtrl+Jと入力する、ということを知っているとどこかで役に立つかも。(ソースはこちらです。 : http://arena.nikkeibp.co.jp/tec/excel/20040308/107599/)

追記ですが、上記のマクロセル1つのコピーにしか対応していません。使えないですね…。複数のセルに対応しながら、それぞれのセルが1行か複数行かを判定し、状況に応じてダブルクォートを削除するのは相当難しそうです。私の現在のスキルでは無理です。セル内にはダブルクォートが含まれない、という前提があれば相当簡単になります。

// クリップボード操作開始
beginclipboardread;

// 配列$a[]にクリップボードの内容を一行ずつ取り込み
#i=0;
$a[#i]=getclipboard;

while($a[#i]!=""){
	#i=#i+1;
	$a[#i]=getclipboard;
}

// 配列$a[]が空の場合、マクロを終了
if ($a[0]==""){
	endmacro;
} else {
// 配列$a[]が空でない場合、ダブルクォートを削除
	#j=0;
	while($a[#j]!=""){
		insert $a[#j];
		up 1;
		selectline;
		replaceall "\"+", "" , regular , inselect;
		down 1;
		#j=#j+1;
	}
}

こちらの方がはるかに現実的かもしれないですね。