2010年12月25日土曜日
2010年11月27日土曜日
2010年11月18日木曜日
2010年11月16日火曜日
第2のホームポジション
ホームポジションと言えば、通常は左右の人差し指をそれぞれFとJに置いたポジションの事を言います。
通常も何もそれで正解なのですが、仕事中に僕が最も長く手を置いているのは実は先述のF・Jのポジションではありません。
写真は会社のPCです。
ちょっとピンぼけしてますが、「→」キーの上が派手に擦り切れているのが分かると思います。
ここが僕の仕事中のホームポジションであり、擦り切れている位置に常に右手の薬指を引っ掛けておき、周辺キーのそこからの相対位置を体が憶えていると言う具合です。
新しいキーボードが支給されると、キートップよりも何よりも真っ先にこの部分がテカテカになってしまいます。
通常も何もそれで正解なのですが、仕事中に僕が最も長く手を置いているのは実は先述のF・Jのポジションではありません。
写真は会社のPCです。
ちょっとピンぼけしてますが、「→」キーの上が派手に擦り切れているのが分かると思います。
ここが僕の仕事中のホームポジションであり、擦り切れている位置に常に右手の薬指を引っ掛けておき、周辺キーのそこからの相対位置を体が憶えていると言う具合です。
新しいキーボードが支給されると、キートップよりも何よりも真っ先にこの部分がテカテカになってしまいます。
2010年11月3日水曜日
Vim on Colemak
配列いじりに手を染めて以来、ViとEmacsは、すっかりご無沙汰になっていました。
しかし、設定ファイルをパッと開いて「1」を「0」に書き換えてサッと閉じる、みたいな時は、やっぱりViが早いです。
ColemakはQwertyとはアルファベットの並びが違うので、Colemak上でVi(Vim)を使うとなると、当然キーバインドを変更する必要があります。
もちろん、キーバインドを変更せずに強引にねじ伏せる事も可能なのですが、Vi(Vim)を使う意味がなくなってしまうでしょう。
そんな訳で、Vi(Vim)のキーバインドも「俺様」で行きます。
以下_vimrcをさらさらしてみるテスト。
"####キーバインド(undo)####
noremap <c-u> u
"####キーバインド(削除)####
noremap k d
"####キーバインド(移動系)####
noremap h <Left>
noremap n <Down>
noremap e <Up>
noremap i <Right>
noremap a <Home>
noremap d <End>
noremap s b
noremap t w
noremap O <PageUp>
noremap o <PageDown>
"####キーバインド(挿入系)####
noremap u i
noremap U a
noremap l I
noremap L A
noremap y o
noremap Y O
noremap f c
noremap F C
"####コピー&ペースト####
noremap c y
noremap v p
noremap V P
2010年10月27日水曜日
ハイフンは右小指下段
日本語入力に俺様カスタマイズのカナ入力を使っているのですが、その中では特に長音記号を定義していません。ローマ字入力と同じようにハイフンを使って入力しています。
とは言え、長音記号が右小指最上段ではあまりに苦しいので、右小指下段へ移動しました。
「・」「?」と入れ替えた格好ですが、丁度「!」と「?」が左右対称位置となり、これは結構気に入っています。
また、長音記号の近くなので感覚的に覚えやすいと考えて、「~」を右小指中段の外側に置きました。「^」の位置としては良すぎるのかも知れませんが…。
とは言え、長音記号が右小指最上段ではあまりに苦しいので、右小指下段へ移動しました。
「・」「?」と入れ替えた格好ですが、丁度「!」と「?」が左右対称位置となり、これは結構気に入っています。
また、長音記号の近くなので感覚的に覚えやすいと考えて、「~」を右小指中段の外側に置きました。「^」の位置としては良すぎるのかも知れませんが…。
カギ括弧はどう打つ?
僕は「」を先に打って確定してしまい、カーソルキーで一つ戻ってから「」の中身を書くのが好きです。
「おはよう!」みたいな短いものは、一気に閉じカッコまで打ち切ってしまいますが、カギ括弧の中身が頭の中で未推敲である場合は、「」をまず確定し、それからゆっくりと中身を考える事が多いです。
と言う事で、「[」「]」(ややこしいな…)を右手と左手の間に縦に配置してみました。
打つ時は、左手の中指と人差し指でタタンと真ん中の2キーを打って、右手のエンターキーで確定すると言う寸法です。
「おはよう!」みたいな短いものは、一気に閉じカッコまで打ち切ってしまいますが、カギ括弧の中身が頭の中で未推敲である場合は、「」をまず確定し、それからゆっくりと中身を考える事が多いです。
と言う事で、「[」「]」(ややこしいな…)を右手と左手の間に縦に配置してみました。
打つ時は、左手の中指と人差し指でタタンと真ん中の2キーを打って、右手のエンターキーで確定すると言う寸法です。
2010年10月24日日曜日
現在の俺様配列をさらさらしてみる
実際には、右手の受け持ち範囲は全て右に一個ずらしているので、その部分も特殊定義と言えなくもないのですが、右手の位置を右に一個ずらしてしまえば感覚的には同じように打てると言う事で特に色分けはしていません。
2010年10月23日土曜日
Colemak!!!Colemak!!!
http://colemak.com/
配列図を眺めていたら、やたらとテンションが上がってきて抑えられなくなりました。
これはやるしかない!
しかし、ググッてみた限りでは、日本でColemakを使っている人はどうやら少ないみたいです。
2chハードウェア板のキーボードスレにちらりと書き込んでいる方はいました。この方はColemak+月配列の使い手のようでした。
配列スレに書き込んで聞いてみたのですが、「俺使ってるよ!」と言う書き込みは今のところありません。しかし即座に反応が返って来るあたりは流石ですw。
Dvorakを使っている人は多いです。
DvorakJP、ACT、JLOD等、Dvorakで日本語入力をする方法が確立しているからでしょう。
しかし、残念ながらColemakには、それがありません。
故に、先程の方のように、Colemak+月配列のような使い方になるのでしょう。
僕は英語はさっぱり分からないので、日常で「英文」を打つ機会はありません。
しかし、「英単語」は結構な頻度で打っていると思います。
音楽とか映画とか、機材、フリーウェア、そういったものをWebで検索する時は、しばしば英単語を直接タイプしますし、仕事でも、日本語の文章に混じって英単語は結構な頻度でタイプします。
つまり、僕のように英語が分からなくて、英語と全く縁のない人でも、日常生活の中では結構な頻度で英単語をタイプするのです。
……いや、あれこれ言いますまい。何を言ってもただ使う理由を探しているだけにしか見えませんw。
要するに使いたいんです!慣れるまでの間、目に見えて生産性が落ちたっていいんです!配列図みてたらテンション上がっちまったんです!
俺はColemakに凸するぜ!!!(つーかもうしたぜ!w)
配列図を眺めていたら、やたらとテンションが上がってきて抑えられなくなりました。
これはやるしかない!
しかし、ググッてみた限りでは、日本でColemakを使っている人はどうやら少ないみたいです。
2chハードウェア板のキーボードスレにちらりと書き込んでいる方はいました。この方はColemak+月配列の使い手のようでした。
配列スレに書き込んで聞いてみたのですが、「俺使ってるよ!」と言う書き込みは今のところありません。しかし即座に反応が返って来るあたりは流石ですw。
Dvorakを使っている人は多いです。
DvorakJP、ACT、JLOD等、Dvorakで日本語入力をする方法が確立しているからでしょう。
しかし、残念ながらColemakには、それがありません。
故に、先程の方のように、Colemak+月配列のような使い方になるのでしょう。
僕は英語はさっぱり分からないので、日常で「英文」を打つ機会はありません。
しかし、「英単語」は結構な頻度で打っていると思います。
音楽とか映画とか、機材、フリーウェア、そういったものをWebで検索する時は、しばしば英単語を直接タイプしますし、仕事でも、日本語の文章に混じって英単語は結構な頻度でタイプします。
つまり、僕のように英語が分からなくて、英語と全く縁のない人でも、日常生活の中では結構な頻度で英単語をタイプするのです。
……いや、あれこれ言いますまい。何を言ってもただ使う理由を探しているだけにしか見えませんw。
要するに使いたいんです!慣れるまでの間、目に見えて生産性が落ちたっていいんです!配列図みてたらテンション上がっちまったんです!
俺はColemakに凸するぜ!!!(つーかもうしたぜ!w)
忘れるのが難しい
カナの配置換えをする際、実を言うと、新しい配置を覚えるよりも、旧い配置を忘れる方が難しかったりします。
覚えるのは気合と根性でなんとかなるのですが、一旦覚えてしまったものは、「さぁ忘れるぞ」と思ったところで忘れられるものではありません。
特に出現頻度の高いカナの配置を変更した場合が厄介です。
例えば「い」の位置を変更した場合、「い」のみを打つときは間違えなくても、「ない」を打つときに、旧い「い」の位置をどうしても打ってしまいます。
「い」の位置だけでなく、「ない」を打つ際の指の形を体がまとめて記憶してしまっているからです。
実はつい最近「う」と「ん」を入れ替えたばかりで苦しんでいるんですけどね。(;^ω^)
覚えるのは気合と根性でなんとかなるのですが、一旦覚えてしまったものは、「さぁ忘れるぞ」と思ったところで忘れられるものではありません。
特に出現頻度の高いカナの配置を変更した場合が厄介です。
例えば「い」の位置を変更した場合、「い」のみを打つときは間違えなくても、「ない」を打つときに、旧い「い」の位置をどうしても打ってしまいます。
「い」の位置だけでなく、「ない」を打つ際の指の形を体がまとめて記憶してしまっているからです。
実はつい最近「う」と「ん」を入れ替えたばかりで苦しんでいるんですけどね。(;^ω^)
2010年10月17日日曜日
意外と高い「る」の頻度
出現頻度の高いカナはなるべくアンシフト面に配置した方が総打鍵数が減るので、単純に考えれば入力は楽になるはずです。
現バージョンのアスナロ配列では、高頻度の「た」をシフト面に配置しており、常々これを改善したいと考えていたのですが、なかなか良いアイデアが浮かびませんでした。
今回、「た」と「る」では「た」の方が頻度が高かろうと考えて、「た」をアンシフト面へ昇格し、代わりに「る」をシフト面へ降格する手を試みました。
いざテスト。
…ヤバイ、「る」って意外と頻度高いよ…_| ̄|○
おかしいなぁ…と思いつつ、Webで公開して下さっている方々のカナ出現頻度表を検索で引っかかる端から拝見。
すると、「た」を追い抜き、「か」に次いで堂々の六位に「る」が出現している方がいらっしゃいました。Σ(゚д゚lll)ガーン
うーん、誤解してたなぁ…。「る」の頻度は中の上のちょい上、「き」あたりと同等と考えていたのですが、認識を修正しました。「る」は、どうやらサンプル次第では高順位を占めるカナのようです。
認識が変わったところで様々なカナ配列を見なおしてみると…、シフトキー押しっぱなしを前提に設計された飛鳥カナ配列を除けば、ほぼ全てのカナ配列が「る」をアンシフト面に配置しています。全然気づかなかった…_| ̄|○
しかもなんと小梅配列では「る」は人差し指ホームポジションである「F」の位置です。
今後は「た>る」ではなく、「る>た」の認識で行くことにします。(`・ω・´)
現バージョンのアスナロ配列では、高頻度の「た」をシフト面に配置しており、常々これを改善したいと考えていたのですが、なかなか良いアイデアが浮かびませんでした。
今回、「た」と「る」では「た」の方が頻度が高かろうと考えて、「た」をアンシフト面へ昇格し、代わりに「る」をシフト面へ降格する手を試みました。
いざテスト。
…ヤバイ、「る」って意外と頻度高いよ…_| ̄|○
おかしいなぁ…と思いつつ、Webで公開して下さっている方々のカナ出現頻度表を検索で引っかかる端から拝見。
すると、「た」を追い抜き、「か」に次いで堂々の六位に「る」が出現している方がいらっしゃいました。Σ(゚д゚lll)ガーン
うーん、誤解してたなぁ…。「る」の頻度は中の上のちょい上、「き」あたりと同等と考えていたのですが、認識を修正しました。「る」は、どうやらサンプル次第では高順位を占めるカナのようです。
認識が変わったところで様々なカナ配列を見なおしてみると…、シフトキー押しっぱなしを前提に設計された飛鳥カナ配列を除けば、ほぼ全てのカナ配列が「る」をアンシフト面に配置しています。全然気づかなかった…_| ̄|○
しかもなんと小梅配列では「る」は人差し指ホームポジションである「F」の位置です。
今後は「た>る」ではなく、「る>た」の認識で行くことにします。(`・ω・´)
2010年10月11日月曜日
ワンセグ用の半波長ダイポールアンテナを自作
まぁ、自作というほどのものではないのだけれど…。
モノラルイヤホンをぶった切って、割り箸やストローに固定して作る半波長ダイポールアンテナの記事をあちこちで見かけたので、自分でもやってみたくなりました。
僕の場合は更に横着して、30cm定規に直接セロテープで貼りつけてしまいました。
アンテナの長さは12.5~15cmくらいで、人によってまちまちのようだったので、電波の出力の弱い東京MXにあわせて15cm弱にしました。
写真では一見15cmジャストに見えますが、コードをサキイカにしてる時に被覆のビニールが伸びてしまったので、中の線は多分15cm弱です。
アスナロ配列
別に新配列と言う訳ではなく、今まで月配列Rと呼んでいたものを「アスナロ配列」と呼ぶ事にしただけです。
今まで、月配列4-698(幸花配列)を弄って使用している私家版配列の事を仮に「月配列R」と呼んでいたのですが、ちっとも名が体を表していません。
2ch月スレを読む限り、新JISの流れを汲まず、且つ、中指シフトを採用している配列は植物の名称が付されるようです。
幸花配列をベースにしているこの配列は当然、そのカナの配置に於いて新JISの影響は受けていません。
自分ひとりしか使っていないこの配列に名が必要であるかどうかはともかくとして、今後この配列を「アスナロ配列」と呼ぶ事にします。
2010年9月29日水曜日
月配列R_20100929
今回は、我ながらうまく整理出来たと思う。
基本的には清音の裏に濁音と半濁音を配置。
上記規則性からはずれているカナは、青の太罫線で囲っている。
規則性からはずれているカナのうち、「び」と「ぴ」、「ぶ」と「ぷ」、「ぼ」と「ぽ」は、感覚的に記憶しやすいように、それぞれ指の動きが左右対称になるよう配置し、且つ、濁音か半濁音のどちらかが清音の裏に来るようにしている。
基本的には清音の裏に濁音と半濁音を配置。
上記規則性からはずれているカナは、青の太罫線で囲っている。
2010年9月23日木曜日
2010年9月20日月曜日
2010年9月18日土曜日
月配列R_20100915~17
どうやら連休に入ると配列をがんがん入れ替えてしまうみたいです。
上が9/17、下が9/15。
okでおkが打てなくなったのはやや無念。
でも、どうしても濁点をアンシフト面に配置してみたかったので、「お」には一旦シフト面へ退いてもらうことにします。
上が9/17、下が9/15。
okでおkが打てなくなったのはやや無念。
でも、どうしても濁点をアンシフト面に配置してみたかったので、「お」には一旦シフト面へ退いてもらうことにします。
2010年9月3日金曜日
2010年7月10日土曜日
ファンが止まっていたらしい。しかも数年Σ(´∀`;)
もう随分長いこと我が家のリビングで頑張ってくれているThinkPad A31P。
最近、キーボードの左のあたりが熱くなって落ちるようになったので、キーボードを外してみたら埃がぎっしりΣ(´∀`;)。
ファンの外し方がいまいち良く分からなかったので、外さずに掃除機と綿棒とピンセットを駆使して埃を取り除きました。
祈りつつ電源ON。
見事起動(∩´∀`)∩。
しかも、今まで全然鳴る事のなかったファンの風切音がします。
…そう言えば数年前、ファンの音が急にうるさくなって、「ヤバイ、壊れたかな?」と思っていたら、いつの間にか静かになって、「あ、治ったんだ、良かった良かった。」と思ったことがありました。
今考えると、治ったのではなくて埃が詰まってファンが回らなくなっただけのようです。
しかもその後、数年止まったまま!!!(笑)
いやはや、良く壊れずにもってくれたものです。
さすがに、埃を取り除いた直後は、排気口からなにやら黒いスス状の汚れが吹き出してきました。
教訓:冷却ファンの掃除は定期的に行なったほうが良さそうです。
最近、キーボードの左のあたりが熱くなって落ちるようになったので、キーボードを外してみたら埃がぎっしりΣ(´∀`;)。
ファンの外し方がいまいち良く分からなかったので、外さずに掃除機と綿棒とピンセットを駆使して埃を取り除きました。
祈りつつ電源ON。
見事起動(∩´∀`)∩。
しかも、今まで全然鳴る事のなかったファンの風切音がします。
…そう言えば数年前、ファンの音が急にうるさくなって、「ヤバイ、壊れたかな?」と思っていたら、いつの間にか静かになって、「あ、治ったんだ、良かった良かった。」と思ったことがありました。
今考えると、治ったのではなくて埃が詰まってファンが回らなくなっただけのようです。
しかもその後、数年止まったまま!!!(笑)
いやはや、良く壊れずにもってくれたものです。
さすがに、埃を取り除いた直後は、排気口からなにやら黒いスス状の汚れが吹き出してきました。
教訓:冷却ファンの掃除は定期的に行なったほうが良さそうです。
2010年6月27日日曜日
【Excel】5,461 要素より大きな配列を返すと…【VBA】
VBA中でワークシート関数を使用する際に、どういう条件で発生しているのかいまいち分からないエラーがあったのですが、やっと分かりました。
XL2000: カスタム関数で 5,461 要素より大きな配列を返すとエラー「#VALUE!」! マクロの実行後のエラー
…と言う事のようです。
狭い範囲を与えた場合には正常動作するのに、範囲を広げるとエラーが出るのに気付いて、いろいろな範囲を与えながら試していたら、5,461行目を超えた所でエラーが出たので、「5461 excel」でググったら上記サイトに辿り着きました。
XL2000: カスタム関数で 5,461 要素より大きな配列を返すとエラー「#VALUE!」! マクロの実行後のエラー
…と言う事のようです。
狭い範囲を与えた場合には正常動作するのに、範囲を広げるとエラーが出るのに気付いて、いろいろな範囲を与えながら試していたら、5,461行目を超えた所でエラーが出たので、「5461 excel」でググったら上記サイトに辿り着きました。
Sub HowToUse()
[a1:b5461].Select
'[a1:b5462].Selectだと型不一致エラーが出る
t = Timer
DecreaseRight(Selection).Select
Application.StatusBar = _
"処理時間 " & Timer - t & " 秒"
End Sub
Function DecreaseRight(a1 As Range) As Range
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
End With
Set f = Application.WorksheetFunction
NewColumn = c1
For c = c2 To c1 Step -1
'Set x = Range(Cells(r1, c), Cells(r2, c))
Let x = Range(Cells(r1, c), Cells(r2, c))
If f.CountA(x) > 0 Then
NewColumn = c
Exit For
End If
Next c
Debug.Print TypeName(x)
'Set x だとRange、Let x だとVariant()
'Variant()の場合要素数5,462以上でエラーが出る(XL2K)
Set f = Nothing
Set DecreaseRight = _
Range(Cells(r1, c1), Cells(r2, NewColumn))
End Function
まぁ、いつまでExcel2000使ってるつもりだよ!と言う話なんですけどねw。
2010年6月20日日曜日
【Excel】無駄な選択範囲を縮める⑥【VBA】
大量の閉じカッコで終端されて、なんだかLispっぽくなってる箇所とかありますが、とりあえず動くのでいいでしょう。
DecreaseToUsedRange関数で、一行目のみ或いは一列目のみを選択した際にA1セルのみを返してしまうと言うバグを発見。「ur2 = 1」と「uc2 = 1」と言う判定ロジックがまずかった。判定ロジックを「a1.Address = "A1"」に変えればOK。修正版のコードは後日…(^_^;)
Function DecreaseRange(a1 As Range) As Range
Set DecreaseRange = _
DecreaseLeft( _
DecreaseRight( _
DecreaseUpper( _
DecreaseBottom( _
DecreaseToUsedRange(a1)))))
End Function
Function DecreaseToUsedRange(a1 As Range) As Range
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
End With
With ActiveSheet.UsedRange
ur1 = .Row
uc1 = .Column
ur2 = .Rows.Count + ur1 - 1
uc2 = .Columns.Count + uc1 - 1
End With
b = (r1 > ur2) Or (c1 > uc2) Or _
(r2 < ur1) Or (c2 < uc1) Or _
(ur2 = 1) Or (uc2 = 1)
If b Then
'UsedRangeの外側が与えられた場合の処理
'左上隅のセルを返す
NewRow1 = r1
NewColumn1 = c1
NewRow2 = r1
NewColumn2 = c1
Else
'UsedRangeの内側が与えられた場合の処理
If r1 < ur1 Then
NewRow1 = ur1
Else
NewRow1 = r1
End If
If c1 < uc1 Then
NewColumn1 = uc1
Else
NewColumn1 = c1
End If
If r2 > ur2 Then
NewRow2 = ur2
Else
NewRow2 = r2
End If
If c2 > uc2 Then
NewColumn2 = uc2
Else
NewColumn2 = c2
End If
End If
Set DecreaseToUsedRange = _
Range(Cells(NewRow1, NewColumn1), _
Cells(NewRow2, NewColumn2))
End Function
Function DecreaseBottom(a1 As Range) As Range
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
End With
NewRow = r1
For c = c1 To c2
If Len(Cells(r2, c)) > 0 Then
NewRow = r2
Exit For
End If
r = Cells(r2, c).End(xlUp).Row
If r > NewRow Then
NewRow = r
End If
Next c
Set DecreaseBottom = _
Range(Cells(r1, c1), Cells(NewRow, c2))
End Function
Function DecreaseUpper(a1 As Range) As Range
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
End With
Set f = Application.WorksheetFunction
NewRow = r2
For r = r1 To r2
Set x = Range(Cells(r, c1), Cells(r, c2))
If f.CountA(x) > 0 Then
NewRow = r
Exit For
End If
Next r
Set f = Nothing
Set DecreaseUpper = _
Range(Cells(NewRow, c1), Cells(r2, c2))
End Function
Function DecreaseRight(a1 As Range) As Range
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
End With
Set f = Application.WorksheetFunction
NewColumn = c1
For c = c2 To c1 Step -1
Set x = Range(Cells(r1, c), Cells(r2, c))
If f.CountA(x) > 0 Then
NewColumn = c
Exit For
End If
Next c
Set f = Nothing
Set DecreaseRight = _
Range(Cells(r1, c1), Cells(r2, NewColumn))
End Function
Function DecreaseLeft(a1 As Range) As Range
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
End With
Set f = Application.WorksheetFunction
NewColumn = c2
For c = c1 To c2
Set x = Range(Cells(r1, c), Cells(r2, c))
If f.CountA(x) > 0 Then
NewColumn = c
Exit For
End If
Next c
Set f = Nothing
Set DecreaseLeft = _
Range(Cells(r1, NewColumn), Cells(r2, c2))
End Function
【2011/06/01追記】DecreaseToUsedRange関数で、一行目のみ或いは一列目のみを選択した際にA1セルのみを返してしまうと言うバグを発見。「ur2 = 1」と「uc2 = 1」と言う判定ロジックがまずかった。判定ロジックを「a1.Address = "A1"」に変えればOK。修正版のコードは後日…(^_^;)
2010年6月19日土曜日
【Excel】無駄な選択範囲を縮める⑤【VBA】
無駄な選択範囲を縮める関数として、
・ReduceRangeR -> 下方の無駄な選択範囲を縮める
・ReduceRangeC -> 右方の無駄な選択範囲を縮める
・xUsedRange -> "UsedRange"の外側の範囲を縮める
を定義しました。
上記三つを更にまとめて、関数"ReduceRange"を定義します。
ついでに、"Exit For"を使うべきところで"GoTo"を使っていた箇所を修正。
実行前
実行後
xUsedRange
黄、紫、青の部分までサイズを縮小
ReduceRangeC
黄、紫の部分までサイズを縮小
ReduceRangeR
黄の部分までサイズを縮小
ここまで来ると、上方と左方の空白部分も最適化したくなってきます。
要らないような気もするけど…。
・ReduceRangeR -> 下方の無駄な選択範囲を縮める
・ReduceRangeC -> 右方の無駄な選択範囲を縮める
・xUsedRange -> "UsedRange"の外側の範囲を縮める
を定義しました。
上記三つを更にまとめて、関数"ReduceRange"を定義します。
Sub HowToUse()
ReduceRange(Selection).Select
End Sub
Function ReduceRange(a1 As Range) As Range
'ただ単に三つの関数を束ねるだけの関数
'xUsedRangeを最初に適用すると最も効率が良い(多分)
Set ReduceRange = ReduceRangeR(ReduceRangeC(xUsedRange(a1)))
End Function
Private Function xUsedRange(a1 As Range) As Range
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
End With
With ActiveSheet.UsedRange
ur1 = .Row
uc1 = .Column
ur2 = .Rows.Count + ur1 - 1
uc2 = .Columns.Count + uc1 - 1
End With
If (r1 > ur2) Or (c1 > uc2) Or (r2 < ur1) Or (c2 < uc1) Or (ur2 = 1) Or (uc2 = 1) Then
'UsedRangeの外側が与えられた場合の処理
'(左上隅のセルを返す)
NewRow1 = r1
NewColumn1 = c1
NewRow2 = r1
NewColumn2 = c1
GoTo xxx
End If
If r1 < ur1 Then
NewRow1 = ur1
Else
NewRow1 = r1
End If
If c1 < uc1 Then
NewColumn1 = uc1
Else
NewColumn1 = c1
End If
If r2 > ur2 Then
NewRow2 = ur2
Else
NewRow2 = r2
End If
If c2 > uc2 Then
NewColumn2 = uc2
Else
NewColumn2 = c2
End If
xxx:
Set xUsedRange = Range(Cells(NewRow1, NewColumn1), Cells(NewRow2, NewColumn2))
End Function
Private Function ReduceRangeC(a1 As Range) As Range
r1 = a1.Row
c1 = a1.Column
r2 = a1.Rows.Count + r1 - 1
c2 = a1.Columns.Count + c1 - 1
Set f = Application.WorksheetFunction
NewColumn = c1
For c = c2 To c1 Step -1
If f.CountA(Range(Cells(r1, c), Cells(r2, c))) > 0 Then
NewColumn = c
Exit For
End If
Next c
Set ReduceRangeC = Range(Cells(r1, c1), Cells(r2, NewColumn))
End Function
Private Function ReduceRangeR(a1 As Range) As Range
r1 = a1.Row
c1 = a1.Column
r2 = a1.Rows.Count + r1 - 1
c2 = a1.Columns.Count + c1 - 1
NewRow = r1
For c = c1 To c2
If Len(Cells(r2, c)) > 0 Then
NewRow = r2
Exit For
End If
r = Cells(r2, c).End(xlUp).Row
If r > NewRow Then
NewRow = r
End If
Next c
Set ReduceRangeR = Range(Cells(r1, c1), Cells(NewRow, c2))
End Function
コードの分かりにくそうな所にコメントを少々追加。ついでに、"Exit For"を使うべきところで"GoTo"を使っていた箇所を修正。
実行前
実行後
xUsedRange
黄、紫、青の部分までサイズを縮小
ReduceRangeC
黄、紫の部分までサイズを縮小
ReduceRangeR
黄の部分までサイズを縮小
ここまで来ると、上方と左方の空白部分も最適化したくなってきます。
要らないような気もするけど…。
【Excel】無駄な選択範囲を縮める④【VBA】
再チャレンジ。
"UsedRange"よりも大きな範囲が与えられた場合に"UsedRange"よりも外側の範囲を除いた"Range"を返す関数です。
【2011/06/01追記】
xUsedRange関数で、一行目のみ或いは一列目のみを選択した際にA1セルのみを返してしまうと言うバグを発見。「ur2 = 1」と「uc2 = 1」と言う判定ロジックがまずかった。判定ロジックを「a1.Address = "A1"」に変えればOK。修正版のコードは後日…(^_^;)
"UsedRange"よりも大きな範囲が与えられた場合に"UsedRange"よりも外側の範囲を除いた"Range"を返す関数です。
Sub HowToUse()
xUsedRange(Selection).Select
End Sub
Private Function xUsedRange(a1 As Range) As Range
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
End With
With ActiveSheet.UsedRange
ur1 = .Row
uc1 = .Column
ur2 = .Rows.Count + ur1 - 1
uc2 = .Columns.Count + uc1 - 1
End With
If (r1 > ur2) Or (c1 > uc2) Or (r2 < ur1) Or (c2 < uc1) Or (ur2 = 1) Or (uc2 = 1) Then
NewRow1 = r1
NewColumn1 = c1
NewRow2 = r1
NewColumn2 = c1
GoTo xxx
End If
If r1 < ur1 Then
NewRow1 = ur1
Else
NewRow1 = r1
End If
If c1 < uc1 Then
NewColumn1 = uc1
Else
NewColumn1 = c1
End If
If r2 > ur2 Then
NewRow2 = ur2
Else
NewRow2 = r2
End If
If c2 > uc2 Then
NewColumn2 = uc2
Else
NewColumn2 = c2
End If
xxx:
Set xUsedRange = Range(Cells(NewRow1, NewColumn1), Cells(NewRow2, NewColumn2))
End Function
"UsedRange"の外側が与えられた場合は、その範囲の左上隅のセル一個を範囲として返す仕様にしました。【2011/06/01追記】
xUsedRange関数で、一行目のみ或いは一列目のみを選択した際にA1セルのみを返してしまうと言うバグを発見。「ur2 = 1」と「uc2 = 1」と言う判定ロジックがまずかった。判定ロジックを「a1.Address = "A1"」に変えればOK。修正版のコードは後日…(^_^;)
2010年6月16日水曜日
【Excel】無駄な選択範囲を縮める③【VBA】
"UsedRange"よりも大きな範囲が与えられた場合に"UsedRange"よりも外側の範囲を除いた"Range"を返す関数です。
2010年6月13日日曜日と2010年6月14日月曜日のコードを実行する前にこのコードを実行すれば、データの有無を調べる範囲が縮まって、更なる高速化が望めるはずです。
実はこのコード、"UsedRange"の外側の範囲を与えられたときにうまく動作しないと言う不具合があります。解決法は目下思案中…。
2010年6月13日日曜日と2010年6月14日月曜日のコードを実行する前にこのコードを実行すれば、データの有無を調べる範囲が縮まって、更なる高速化が望めるはずです。
Sub HowToUse()
xUsedRange(Selection).Select
End Sub
Private Function xUsedRange(a1 As Range) As Range
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
End With
With ActiveSheet.UsedRange
ur1 = .Row
uc1 = .Column
ur2 = .Rows.Count + ur1 - 1
uc2 = .Columns.Count + uc1 - 1
End With
If ur1 = 1 Then
NewRow1 = 1
ElseIf r1 < ur1 Then
NewRow1 = ur1
Else
NewRow1 = r1
End If
If uc1 = 1 Then
NewColumn1 = 1
ElseIf c1 < uc1 Then
NewColumn1 = uc1
Else
NewColumn1 = c1
End If
If ur2 = 1 Then
NewRow2 = 1
ElseIf r2 > ur2 Then
NewRow2 = ur2
Else
NewRow2 = r2
End If
If uc2 = 1 Then
NewColumn2 = 1
ElseIf c2 > uc2 Then
NewColumn2 = uc2
Else
NewColumn2 = c2
End If
Set xUsedRange = Range(Cells(NewRow1, NewColumn1), Cells(NewRow2, NewColumn2))
End Function
【2010年6月19日土曜日追記】実はこのコード、"UsedRange"の外側の範囲を与えられたときにうまく動作しないと言う不具合があります。解決法は目下思案中…。
2010年6月15日火曜日
【Excel】半角と全角の変換マクロ⑧【VBA】
要するにやりたかったのはこれです。
セルを全選択しても、数十万個のデータに対して処理をかけても、数秒で完了します。
セルを全選択しても、数十万個のデータに対して処理をかけても、数秒で完了します。
Sub 全角に変換する()
t = Timer
Call xStrConv(ReduceRangeR(ReduceRangeC(Selection)), vbWide)
Application.StatusBar = " 全角に変換しました。 " _
& Timer - t & " 秒"
End Sub
Sub 半角に変換する()
t = Timer
Call xStrConv(ReduceRangeR(ReduceRangeC(Selection)), vbNarrow)
Application.StatusBar = " 半角に変換しました。 " _
& Timer - t & " 秒"
End Sub
Private Function ReduceRangeC(a1 As Range) As Range
r1 = a1.Row
c1 = a1.Column
r2 = a1.Rows.Count + r1 - 1
c2 = a1.Columns.Count + c1 - 1
Set f = Application.WorksheetFunction
NewColumn = c1
For c = c2 To c1 Step -1
If f.CountA(Range(Cells(r1, c), Cells(r2, c))) > 0 Then
NewColumn = c
GoTo xxx
End If
Next c
xxx:
Set ReduceRangeC = Range(Cells(r1, c1), Cells(r2, NewColumn))
End Function
Private Function ReduceRangeR(a1 As Range) As Range
r1 = a1.Row
c1 = a1.Column
r2 = a1.Rows.Count + r1 - 1
c2 = a1.Columns.Count + c1 - 1
NewRow = r1
For c = c1 To c2
If Len(Cells(r2, c)) > 0 Then
NewRow = r2
GoTo xxx
End If
r = Cells(r2, c).End(xlUp).Row
If r > NewRow Then
NewRow = r
End If
Next c
xxx:
Set ReduceRangeR = Range(Cells(r1, c1), Cells(NewRow, c2))
End Function
Private Sub xStrConv(a1, a2)
If Not TypeName(a1) = "Range" Then
MsgBox ("セルを選択して下さい")
Exit Sub
End If
If a1.Count = 1 Then
x = StrConv(a1.FormulaLocal, a2)
GoTo xxx
End If
RowsCount = a1.Rows.Count
ColumnsCount = a1.Columns.Count
r1 = a1.Row
c1 = a1.Column
r2 = RowsCount + r1 - 1
c2 = ColumnsCount + c1 - 1
x = Range(Cells(r1, c1), Cells(r2, c2)).FormulaLocal
For r = 1 To RowsCount
For c = 1 To ColumnsCount
x(r, c) = StrConv(x(r, c), a2)
Next c
Next r
xxx:
a1.Value = x
End Sub
2010年6月14日月曜日
【Excel】無駄な選択範囲を縮める②【VBA】
昨日は、引数Rangeをとり、下方の空白行を除いたRangeを返す関数を作ったので、今回は、右方の空白行を除いたRangeを返す関数を作ってみました。
Sub HowToUse()
ReduceRangeC(Selection).Select
End Sub
Private Function ReduceRangeC(a1 As Range) As Range
r1 = a1.Row
c1 = a1.Column
r2 = a1.Rows.Count + r1 - 1
c2 = a1.Columns.Count + c1 - 1
Set f = Application.WorksheetFunction
NewColumn = c1
For c = c2 To c1 Step -1
If f.CountA(Range(Cells(r1, c), Cells(r2, c))) > 0 Then
NewColumn = c
GoTo xxx
End If
Next c
xxx:
Set ReduceRangeC = Range(Cells(r1, c1), Cells(r2, NewColumn))
End Function
2010年6月13日日曜日
【Excel】無駄な選択範囲を縮める【VBA】
"Range("A65536").End(xlUp).Row"で、データが入力されている最終行を取得するのはExcelVBAの定石なので、これを汎用性のある関数にしてみました。
実行前
実行後
Sub HowToUse()
ReduceRangeR(Selection).Select
End Sub
Private Function ReduceRangeR(a1 As Range) As Range
r1 = a1.Row
c1 = a1.Column
r2 = a1.Rows.Count + r1 - 1
c2 = a1.Columns.Count + c1 - 1
NewRow = r1
For c = c1 To c2
If Len(Cells(r2, c)) > 0 Then
NewRow = r2
GoTo xxx
End If
r = Cells(r2, c).End(xlUp).Row
If r > NewRow Then
NewRow = r
End If
Next c
xxx:
Set ReduceRangeR = Range(Cells(r1, c1), Cells(NewRow, c2))
End Function
引数にRangeをとって、下方の空白行を除いたRangeを返します。実行前
実行後
【Excel】半角と全角の変換マクロ⑦【VBA】
疲れたので、きちんとした速度測定は次回(笑)。でも多分更に高速化されているはず。
Sub 全角に変換する()
If Not TypeName(Selection) = "Range" Then
MsgBox ("セルを選択して下さい")
Exit Sub
End If
t = Timer
Call ExStrConv(Selection, vbWide)
Application.StatusBar = _
("全角に変換しました。 " & Timer - t & " 秒")
End Sub
Sub 半角に変換する()
If Not TypeName(Selection) = "Range" Then
MsgBox ("セルを選択して下さい")
Exit Sub
End If
t = Timer
Call ExStrConv(Selection, vbNarrow)
Application.StatusBar = _
("半角に変換しました。 " & Timer - t & " 秒")
End Sub
Private Sub ExStrConv(a1 As Range, a2)
If a1.Count = 1 Then
'選択セルが一つだけの場合の処理
'x As String
x = StrConv(a1.FormulaLocal, a2)
Else
'選択セルが二つ以上の場合の処理
'x As Variant()
With a1
r1 = .Row
c1 = .Column
r2 = .Rows.Count + r1 - 1
c2 = .Columns.Count + c1 - 1
RowsCount = .Rows.Count
ColumnsCount = .Columns.Count
End With
x = Range(Cells(r1, c1), _
Cells(r2, c2)).FormulaLocal
For r = 1 To RowsCount
For c = 1 To ColumnsCount
x(r, c) = StrConv(x(r, c), a2)
Next c
Next r
End If
a1.Value = x
End Sub
【Excel】半角と全角の変換マクロ⑥【VBA】
".Rows.Count"と".Columns.Count"を何度も呼ばずに、あらかじめ一度だけ変数に入れておけば少しは速くなる?と思って試してみました。
書き換え前
全角:124.6094秒
半角:124.0938秒
書き換え後
全角:121.5秒
半角:121.3594秒
うわ、微妙www。
Option Base 1
Sub 全角に変換する()
Call xStrConv(Selection, vbWide)
End Sub
Sub 半角に変換する()
Call xStrConv(Selection, vbNarrow)
End Sub
Private Sub xStrConv(a1, a2)
Max = 655360 '10列分のセル数
If Not TypeName(a1) = "Range" Then
MsgBox ("セルを選択して下さい")
Exit Sub
ElseIf a1.Count > Max Then
MsgBox ("処理出来るデータの数は" & Max & "までです")
Exit Sub
End If
rEnd = a1.Rows.Count
cEnd = a1.Columns.Count
Dim x: ReDim x(rEnd, cEnd)
For r = 1 To rEnd
For c = 1 To cEnd
x(r, c) = StrConv(a1(r, c).FormulaLocal, a2)
Next c
Next r
a1.Value = x
End Sub
何もデータの入っていないシートのセルを全選択して計測。書き換え前
全角:124.6094秒
半角:124.0938秒
書き換え後
全角:121.5秒
半角:121.3594秒
うわ、微妙www。
【Excel】半角と全角の変換マクロ⑤【VBA】
一晩寝て見直してみたら、昨日のコードよりも一昨日のコードのほうがシンプルでいいかな、と言う気がしてきたので、コードの基本的な骨格は一昨日のものを流用しつつ、配列を使って高速化してみました。
Option Base 1
Sub 全角に変換する()
Call xStrConv(Selection, vbWide)
End Sub
Sub 半角に変換する()
Call xStrConv(Selection, vbNarrow)
End Sub
Private Sub xStrConv(a1, a2)
Max = 655360 '10列分のセル数
If Not TypeName(a1) = "Range" Then
MsgBox ("セルを選択して下さい")
Exit Sub
ElseIf a1.Count > Max Then
MsgBox ("処理出来るデータの数は" & Max & "までです")
Exit Sub
End If
Dim x: ReDim x(a1.Rows.Count, a1.Columns.Count)
For r = 1 To a1.Rows.Count
For c = 1 To a1.Columns.Count
x(r, c) = StrConv(a1(r, c).FormulaLocal, a2)
Next c
Next r
a1.Value = x
End Sub
普段使いには一昨日のコード、大量のデータを変換したければ今回のコードを使えば良さそうです。
2010年6月12日土曜日
【Excel】半角と全角の変換マクロ④【VBA】
文字列変換のマクロを更に改良。
2010年6月10日木曜日のコードでも、とりあえずは完成だと思うのだけれど、せっかく名称を"xStrConv"としたのならば、"StrConv"関数と同じような呼び方が出来た方が分かりやすいです。つまり…、
もちろん、"StrConv"関数を
以下がコード。
処理が高速なので、たくさんのセルを選択したときにエラーを出すコードを思い切って削除しました。
ちなみに僕の環境では、セルを全選択して実行しようとすると、「メモリが不足しています」と言うエラーが出ます。
データを読み込む際に、値で読み込むのではなく、"FormulaLocal"を使う事により、結果として数式の入力されたセルをスキップしているかのように動作します。
ここで、"Formula"ではなく"FormulaLocal"を使っているのがミソで、最初は"JIS"関数が"=DBCS(A1)"のようなワケの分からない文字列に化けて、ハマッてしまいました。
救ってくれたのがこのサイト。多謝!
2010年6月10日木曜日のコードでも、とりあえずは完成だと思うのだけれど、せっかく名称を"xStrConv"としたのならば、"StrConv"関数と同じような呼び方が出来た方が分かりやすいです。つまり…、
Selection.Value = xStrConv(Selection, vbWide)
みたいな呼び方が出来ればスマートかと。もちろん、"StrConv"関数を
Selection.Value = StrConv(Selection, vbWide)
みたいに書くと「型が一致しません」と言うエラーが出ます。以下がコード。
Option Base 1
Sub 全角に変換する()
Selection.Value = xStrConv(Selection, vbWide)
End Sub
Sub 半角に変換する()
Selection.Value = xStrConv(Selection, vbNarrow)
End Sub
Private Function xStrConv(a1, a2)
Dim x: ReDim x(a1.Rows.Count, a1.Columns.Count)
For r = 1 To a1.Rows.Count
For c = 1 To a1.Columns.Count
x(r, c) = StrConv(a1(r, c).FormulaLocal, a2)
Next c
Next r
xStrConv = x
End Function
データを配列に格納して処理する仕様へ変更したので処理が高速です。処理が高速なので、たくさんのセルを選択したときにエラーを出すコードを思い切って削除しました。
ちなみに僕の環境では、セルを全選択して実行しようとすると、「メモリが不足しています」と言うエラーが出ます。
データを読み込む際に、値で読み込むのではなく、"FormulaLocal"を使う事により、結果として数式の入力されたセルをスキップしているかのように動作します。
ここで、"Formula"ではなく"FormulaLocal"を使っているのがミソで、最初は"JIS"関数が"=DBCS(A1)"のようなワケの分からない文字列に化けて、ハマッてしまいました。
救ってくれたのがこのサイト。多謝!
2010年6月10日木曜日
【Excel】半角と全角の変換マクロ③【VBA】
文字列変換のマクロに、セル以外のオブジェクトが選択された場合と、選択セルが多すぎる場合にメッセージを表示するコードを付け加えました。
また、引数をStrConv関数に合わせてみました。
また、引数をStrConv関数に合わせてみました。
Sub 全角に変換する()
Call xStrConv(Selection, vbWide)
End Sub
Sub 半角に変換する()
Call xStrConv(Selection, vbNarrow)
End Sub
Private Sub xStrConv(a1, a2)
Max = 5000
Set f = Application.WorksheetFunction
If Not TypeName(a1) = "Range" Then
MsgBox ("セルを選択して下さい")
Exit Sub
ElseIf f.CountA(a1) > Max Then
MsgBox ("処理出来るデータの数は" & Max & "までです")
Exit Sub
End If
For Each c In a1
If Len(c) > 0 Then
If Not c.HasFormula Then
c.Value = StrConv(c, a2)
End If
End If
Next
End Sub
2010年6月9日水曜日
【Excel】半角と全角の変換マクロ②【VBA】
昨日に引き続きセルに入力された文字列を変換するマクロ。
タイムの測定は記事がごちゃごちゃして見難くなる(笑)ので割愛。
列が全選択される事を想定して空白セルをスキップするコードを追加。
ついでに、セルに数式が入力されている場合もスキップする仕様に変更。
配列に格納するやり方は速度が魅力だけど、コードのメンテナンスのやりやすさ等、トータルに考えて、この辺りが落としどころかなぁ。
タイムの測定は記事がごちゃごちゃして見難くなる(笑)ので割愛。
Sub 全角に変換する()
Call Sample(vbWide)
End Sub
Sub 半角に変換する()
Call Sample(vbNarrow)
End Sub
Sub Sample(a)
For Each s In Selection
If Not Len(s) = 0 Then
If Not s.HasFormula Then
s.Value = StrConv(s, a)
End If
End If
Next
End Sub
列が全選択される事を想定して空白セルをスキップするコードを追加。
ついでに、セルに数式が入力されている場合もスキップする仕様に変更。
配列に格納するやり方は速度が魅力だけど、コードのメンテナンスのやりやすさ等、トータルに考えて、この辺りが落としどころかなぁ。
2010年6月8日火曜日
【Excel】半角と全角の変換マクロ【VBA】
ワードには文字列を半角から全角、全角から半角に変換する機能が標準で付いていますが、エクセルには付いていません。
ワークシート関数を使えば良いといえば良いのですが、そのためだけに使用するセルが増えて表がごちゃごちゃするのも嫌だと言う事でしょう。半角と全角を変換するマクロは割とあちこちで目にします。
引数として、vbNarrowやvbWideを取れるようにして、汎用性を持たせました。
Sample01は率直ですがやや処理に時間がかかります。
Sample02は高速に動作しますが、セル範囲が一つだけのケースでエラーが発生します。
ワークシート関数を使えば良いといえば良いのですが、そのためだけに使用するセルが増えて表がごちゃごちゃするのも嫌だと言う事でしょう。半角と全角を変換するマクロは割とあちこちで目にします。
Sub xxx()
Dim t: t = Timer
For Each c In [a1:j1000]
c.Value = c.Address
Next
[a1:j1000].Select
Debug.Print (Timer - t & "秒")
'1.351563秒
End Sub
Sub callSample01Wide()
Dim t: t = Timer
Call Sample01(vbWide)
Debug.Print (Timer - t & "秒")
'約16秒
End Sub
Sub callSample01Narrow()
Dim t: t = Timer
Call Sample01(vbNarrow)
Debug.Print (Timer - t & "秒")
'約3秒
End Sub
Sub callSample02Wide()
Dim t: t = Timer
Call Sample02(vbWide)
Debug.Print (Timer - t & "秒")
'約2秒
End Sub
Sub callSample02Narrow()
Dim t: t = Timer
Call Sample02(vbNarrow)
Debug.Print (Timer - t & "秒")
'約0.9秒
End Sub
Sub Sample01(a)
For Each c In Selection
c.Value = StrConv(c, a)
Next
End Sub
Sub Sample02(a)
x = Selection
For r = 1 To Selection.Rows.Count
For c = 1 To Selection.Columns.Count
x(r, c) = StrConv(x(r, c), a)
Next c
Next r
Selection = x
End Sub
いろいろ書いていますが、下の方のSample01とSample02がコードの本体です。引数として、vbNarrowやvbWideを取れるようにして、汎用性を持たせました。
Sample01は率直ですがやや処理に時間がかかります。
Sample02は高速に動作しますが、セル範囲が一つだけのケースでエラーが発生します。
【Excel】数式の入力されたセルに色を付ける
名前
isFormula
参照範囲
=GET.CELL(48,!A1)
条件付き書式
=isFormula
48は数式、A1の前についている!は、アクティブシートを意味するとの事。つまりこの式はセルが数式の場合にTrueを返します。
"=GET.CELL(48,!A1)"でググれば情報はたくさん出てきます。
2010年6月7日月曜日
VBAでコードの実行速度を測定②
2010年5月25日火曜日の記事で書いたコードを簡略化。
Option Explicit
Sub Sumple()
Dim t: t = Timer
'計測対象のコード
Debug.Print (Timer - t & " 秒")
End Sub
2010年6月6日日曜日
【Excel】Len関数(意味のない比較だったかもw)【VBA】
100未満の数の抽出するにあたり、値そのものを見るのと、Len関数で桁数を見るのと、どっちが速いかと思って試してみたのですが…、
…これはお題が悪かったかなぁ。(´・ω・`)
一応、値そのものをみるSampleAの方が僅差で速いようです。
どちらも整数値を見て条件分岐してる訳だから、差が出ないのは当然か。
むしろ、50,000回呼び出されているにもかかわらず、処理速度を落とさないLen関数がすごいと言えるかも。
次回は文字列の処理に対して、
「If s = "" Then」と
「If Len(s) = 0 Then」
の違いを比較してみようかな。
Public StartTime As Double
Public EndTime As Double
Sub TimerStart()
StartTime = Timer
End Sub
Sub TimerStop()
EndTime = Timer
Debug.Print (EndTime - StartTime & " 秒")
End Sub
Sub xxx()
Call TimerStart '---- 測定開始
For Each c In [a1:a50000]
c.Value = Round(Rnd() * 1000)
Next
[a1:a50000].Copy [b1:b50000]
Call TimerStop '---- 約3.42秒
End Sub
Sub SampleA()
Call TimerStart '---- 測定開始
For Each c In [a1:a50000]
If c.Value < 100 Then
c.Value = "100以下です"
End If
Next
Call TimerStop '---- 約1.33秒(注)
End Sub
Sub SampleB()
Call TimerStart '---- 測定開始
For Each c In [b1:b50000]
If Len(c.Value) < 3 Then
c.Value = "100以下です"
End If
Next
Call TimerStop '---- 約1.4秒(注)
End Sub
'-- (注)処理速度は生成された乱数に応じて変わりうる
…これはお題が悪かったかなぁ。(´・ω・`)
一応、値そのものをみるSampleAの方が僅差で速いようです。
どちらも整数値を見て条件分岐してる訳だから、差が出ないのは当然か。
むしろ、50,000回呼び出されているにもかかわらず、処理速度を落とさないLen関数がすごいと言えるかも。
次回は文字列の処理に対して、
「If s = "" Then」と
「If Len(s) = 0 Then」
の違いを比較してみようかな。
EXILIM and Cyber-Shot
最近SonyのCyber-Shotを買ったので、CASIOの昔のEXILIMと並べてみました。
さすがに性能には大きな開きがありますが、EXILIMは動作が機敏なので、道具としての使い勝手はいまだに上々です。
どう言う訳か僕は、新しい道具を手に入れると、古い道具を引っ張り出してきて使いたくなるようです。
さすがに性能には大きな開きがありますが、EXILIMは動作が機敏なので、道具としての使い勝手はいまだに上々です。
どう言う訳か僕は、新しい道具を手に入れると、古い道具を引っ張り出してきて使いたくなるようです。
2010年6月5日土曜日
【Excel】描画オブジェクトの全削除(速度測定)【VBA】
昨日、ネットで拝借したコードの速度測定をしてみます。
Public StartTime As Double
Public EndTime As Double
Sub TimerStart()
StartTime = Timer
End Sub
Sub TimerStop()
EndTime = Timer
MsgBox (EndTime - StartTime & " 秒")
End Sub
Sub Add5000Lines()
Call TimerStart '---- 測定開始
For i = 1 To 5000
ActiveSheet.Shapes.AddLine(10, i, 100, i).Select
Next
Call TimerStop '---- 約0.38秒
End Sub
Sub DrawingObjectsDelete01()
Call TimerStart '---- 測定開始
ActiveSheet.DrawingObjects.Delete
Call TimerStop '---- 約0.12秒!!!
End Sub
Sub DrawingObjectsDelete02()
Call TimerStart '---- 測定開始
Set dr = ActiveSheet.DrawingObjects
For Each d In dr
d.Delete
Next
Set dr = Nothing
Call TimerStop '---- 約33秒
End Sub
まずは、Add5000Lines()でラインオブジェクトを5000本引きます。
その後に描画オブジェクトを削除するコード2種類について処理速度を比較しています。
DrawingObjectsDelete01()は高速ですが、非表示のオブジェクトを削除出来ません。
DrawingObjectsDelete02()は低速ですが、非表示のオブジェクトも削除してくれます。
つまり、昨日のコードはこの二つのコードの二段構えになっています。
素晴らしいです。
その後に描画オブジェクトを削除するコード2種類について処理速度を比較しています。
DrawingObjectsDelete01()は高速ですが、非表示のオブジェクトを削除出来ません。
DrawingObjectsDelete02()は低速ですが、非表示のオブジェクトも削除してくれます。
つまり、昨日のコードはこの二つのコードの二段構えになっています。
素晴らしいです。
2010年6月4日金曜日
2010年6月1日火曜日
【Excel】変数の型を表示させる【VBA】
前回と同じコードをサンプルに使うのも何なので、まずは2010年5月30日日曜日のフォルダ一覧を表示させるコードをファイル一覧を表示させるコードへ変更。
Sub MakeFileList()
Set fs = CreateObject("Scripting.FileSystemObject").GetFolder("C:\").Files
Dim x: ReDim x(fs.Count, 1)
For Each f In fs
x(i, 0) = f.Name
i = i + 1
Next
Range("A1:A" & fs.Count) = x
End Sub
一行目末尾を"SubFolders"から"Files"に変更するだけでOK。
変数の型を知りたい場合は以下のようにデバッグ用のコードを追加する。
Sub MakeFileList()
Set fs = CreateObject("Scripting.FileSystemObject").GetFolder("C:\").Files
Dim x: ReDim x(fs.Count, 1)
For Each f In fs
x(i, 0) = f.Name
i = i + 1
tn = TypeName(f) '<-- debug
Next
Range("A1:A" & fs.Count) = x
MsgBox ("i as " & TypeName(i) & vbCrLf & _
"x as " & TypeName(x) & vbCrLf & _
"f as " & TypeName(f) & vbCrLf & _
"fs as " & TypeName(fs) & vbCrLf & _
"---------------------" & vbCrLf & _
"f as " & tn & vbCrLf & _
"tn as " & TypeName(tn) _
) '<-- debug
End Sub
実行すると以下のようなメッセージが出ます。
ループ文の外で型を調べているので、普通に書くと変数"f"の型が"Empty"と表示されてしまいます。
なので、デバッグ用にあらたに変数"tn"を用意し、ループ文の中で"f"の型を調べて、"tn"に代入した上で表示させています。
ついでに"tn"の型も調べてみたら、"String"でした。
この事からTypeName()関数は、変数の型を"文字列"で返す事がわかります。
2010年5月30日日曜日
【Excel】サブフォルダ一覧【VBA】
対象フォルダのサブフォルダ一覧をワークシートに出力するコード。
Sub MakeFolderList()
Set sf = CreateObject("Scripting.FileSystemObject").GetFolder("C:\").SubFolders
Dim x: ReDim x(sf.Count, 1)
For Each f In sf
x(i, 0) = f.Name
i = i + 1
Next
Range("A1:A" & sf.Count) = x
End Sub
対象フォルダを変えたければ"C:\"の所を書き換えればOK。
もしA1セル以下ではなく、C3セル以下にリストを出力したい場合は、最後の行を"Range("C3:C" & sf.Count + 2) = x"のように書き換えればOK。
このコードを考えるにあたって、サンプルとして一万個のダミーフォルダを作成・削除したり、処理時間を測定したのが以下。
Public StartTime As Double
Public EndTime As Double
Const TargetFolder = "C:\test"
Sub TimerStart()
StartTime = Timer
End Sub
Sub TimerStop()
EndTime = Timer
MsgBox (EndTime - StartTime & " 秒")
End Sub
Sub MakeDummyFolder()
Call TimerStart '---- 測定開始
Set fs = CreateObject("Scripting.FileSystemObject")
For i = 0 To 9999
fs.CreateFolder (TargetFolder & _
"\_dummy_" & _
Format(i, "0000"))
Next i
Set fs = Nothing
Call TimerStop '---- 約3.5~10秒
End Sub
Sub MakeFolderListA()
[A:A].Clear
Call TimerStart '---- 測定開始
Set fs = CreateObject("Scripting.FileSystemObject")
Set sf = fs.GetFolder(TargetFolder).SubFolders
i = 1
For Each f In sf
Cells(i, 1) = f.Name
i = i + 1
Next
Set sf = Nothing
Set fs = Nothing
Call TimerStop '---- 約0~8秒???
'フォルダがなければ当然0秒
End Sub
Sub MakeFolderListB()
[B:B].Clear
Call TimerStart '---- 測定開始
Set fs = CreateObject("Scripting.FileSystemObject")
Set sf = fs.GetFolder(TargetFolder).SubFolders
Dim x As Variant
ReDim x(sf.Count, 1) '<-- 配列のリサイズ
For Each f In sf
x(i, 0) = f.Name
i = i + 1
Next
Range("B1:B" & sf.Count) = x
Set sf = Nothing
Set fs = Nothing
Call TimerStop '---- 約0~6秒???
'Aより少しだけ速い
End Sub
Sub DeleteFolders()
Call TimerStart '---- 測定開始
Set fs = CreateObject("Scripting.FileSystemObject")
Set sf = fs.GetFolder(TargetFolder).SubFolders
For Each f In sf
If f.Name Like "*_dummy_*" Then
f.Delete '<-- ※注意!フォルダ全削除
End If
Next
Set sf = Nothing
Set fs = Nothing
Call TimerStop '---- 約4~10秒
End Sub
2010年5月29日土曜日
2010年5月26日水曜日
【速度対決】10万セルに値を書き出す【VBA】
A1:CV1000(1000行×100列=10万セル)に値を書き出してみます。
Public StartTime As Double
Public EndTime As Double
Sub TimerStart()
StartTime = Timer
End Sub
Sub TimerStop()
EndTime = Timer
MsgBox (EndTime - StartTime & " 秒")
End Sub
Sub Sample01()
[a1:cv1000].Clear
Call TimerStart '---- 測定開始
For r = 1 To 1000
For c = 1 To 100
'-- セルを一つずつ呼び出し
Cells(r, c) = r
Next c
Next r
Call TimerStop '---- 約33.8秒
End Sub
Sub Sample02()
[a1:cv1000].Clear
Call TimerStart '---- 測定開始
'-- 画面の更新を停止
Application.ScreenUpdating = False
For r = 1 To 1000
For c = 1 To 100
'-- セルを一つずつ呼び出し
Cells(r, c) = r
Next c
Next r
Application.ScreenUpdating = True
Call TimerStop '---- 約21.4秒
End Sub
Sub Sample03()
[a1:cv1000].Clear
Call TimerStart '---- 測定開始
Dim x(1 To 1000, 1 To 100)
For r = 1 To 1000
For c = 1 To 100
'-- あらかじめ配列に代入
x(r, c) = r
Next c
Next r
'-- 配列の内容をセルへ一気に書き出し
[a1:cv1000] = x
Call TimerStop '---- 約0.13秒
End Sub
Sample01ではCells()で各セルに直接アクセス。
Sample02はSample01と同じコードで画面の更新を停止。
Sample03ではあらかじめ配列へ代入した後にセルへ一気に書き出しています。
一番遅いSample01でも、1万セルまでであれば3秒程度で終了しますので、1万セルを境にコードの最適化を考えれば十分かも知れません。
【速度対決】1を100万回足してみる【VBA】
1を100万回足すコードを少しずつ書き換えて速度比較をしてみました。
セルのA1:A10000に入力された数字を全て合計する処理を100回繰り返しています。
Public StartTime As Double
Public EndTime As Double
Sub TimerStart()
StartTime = Timer
End Sub
Sub TimerStop()
EndTime = Timer
MsgBox (EndTime - StartTime & " 秒")
End Sub
Sub Syokika()
[a1:a10000].Clear
[a1:a10000] = 1
End Sub
Sub Sample01()
Call Syokika
Call TimerStart '---- 測定開始
For i = 1 To 100
For Each a In [a1:a10000] '<-- この書き方がNG
ans = ans + a
Next
Next i
Call TimerStop '---- 約7秒
MsgBox Format(ans, "#,###")
End Sub
Sub Sample02()
Call Syokika
Call TimerStart '---- 測定開始
For i = 1 To 100
'-- 代入を使うだけで速度が15倍
x = [a1:a10000]
For Each a In x
ans = ans + a
Next
Next i
Call TimerStop '---- 約0.45秒
MsgBox Format(ans, "#,###")
End Sub
Sub Sample03()
Call Syokika
Call TimerStart '---- 測定開始
'-- 代入を繰り返し文の外に出すとさらに速くなる
x = [a1:a10000]
For i = 1 To 100
For Each a In x
ans = ans + a
Next
Next i
Call TimerStop '---- 約0.24秒
MsgBox Format(ans, "#,###")
End Sub
Sub Sample04()
Call Syokika
Call TimerStart '---- 測定開始
Set wf = Application.WorksheetFunction
For i = 1 To 100
'-- さらにワークシート関数を使ってみる
ans = ans + wf.Sum([a1:a10000])
Next i
Call TimerStop '---- 約0.045秒!!!
MsgBox Format(ans, "#,###")
End Sub
Sub Sample05()
Call Syokika
Call TimerStart '---- 測定開始
Set wf = Application.WorksheetFunction
'-- さらに配列に代入してみる
x = [a1:a10000]
For i = 1 To 100
ans = ans + wf.Sum(x)
Next i
Call TimerStop '---- 約0.3秒
'遅なっとるやんけ_| ̄|○
MsgBox Format(ans, "#,###")
End Sub
Sub Sample06()
Call Syokika
Call TimerStart '---- 測定開始
Set wf = Application.WorksheetFunction
'-- オブジェクトを代入
Set x = [a1:a10000]
For i = 1 To 100
ans = ans + wf.Sum(x)
Next i
Call TimerStop '---- 約0.045秒!!!
MsgBox Format(ans, "#,###")
End Sub
Sub Sample07()
Call Syokika
Call TimerStart '---- 測定開始
Set wf = Application.WorksheetFunction
'-- あるいはアドレスを文字列で代入
s = "a1:a10000"
For i = 1 To 100
ans = ans + wf.Sum(Range(s))
Next i
Call TimerStop '---- 約0.045秒!!!
MsgBox Format(ans, "#,###")
End Sub
Sample02とSample03の違いはコードを書いている段階ですぐに気付きそうですが、Sample01のようなコードは僕なんかはついつい気付かずに書いてしまいそうです。
Sample04はご存知Excel VBA最強のHuck。ワークシート関数の速さは圧倒的です。
じゃあ配列に代入したSample05ならどうよ?と考えたのですが、逆に遅くなりました。「セルの内容を配列に格納して処理」と、「ワークシート関数」を組み合わせれば最強コンビになるかと思えば然に非ず。(あと、Sample05はExcel2002だと動きましたが、Excel2000だとエラーが出ました。)
以上のことから、ワークシート関数を活用しつつ範囲を動的に変えたい場合はSample06 or 07のように書けば良い事になります。
2010年5月25日火曜日
【速度対決】Date vs 固定値【VBA】
Date関数と固定値("2010/05/25")の比較。
Public StartTime As Double
Public EndTime As Double
Sub TimerStart()
StartTime = Timer
End Sub
Sub TimerStop()
EndTime = Timer
MsgBox (EndTime - StartTime & " 秒")
End Sub
Sub Sample01()
Call TimerStart '---- 測定開始
For i = 1 To 1000000
buf = Date
Next i
Call TimerStop '---- 約0.9秒
End Sub
Sub Sample02()
Call TimerStart '---- 測定開始
For i = 1 To 1000000
buf = "2010/05/25"
Next i
Call TimerStop '---- 約0.17秒
End Sub
Sub Sample03()
Call TimerStart '---- 測定開始
d = Format(Date, "yyyy/mm/dd")
For i = 1 To 1000000
buf = d
Next i
Call TimerStop '---- 約0.17秒
End Sub
100万回実行させて、
・Date -> 約0.9秒
・固定値 -> 約0.17秒
で固定値の勝ち。これは当たり前かw。
つまり実際に使用する際は、Sample03のようにループ文の外で一回だけ代入すれば良いと言う事になります。
【速度対決】Date vs Now【VBA】
速度比較のコードを書いたら、試すのが面白くなってきました。
VBAのDate関数とNow関数の比較。
Public StartTime As Double
Public EndTime As Double
Sub TimerStart()
StartTime = Timer
End Sub
Sub TimerStop()
EndTime = Timer
MsgBox (EndTime - StartTime & " 秒")
End Sub
Sub Sample01()
Call TimerStart '---- 測定開始
For i = 1 To 1000000
buf = Date 'yyyy/mm/dd
Next i
Call TimerStop '---- 約0.9秒
End Sub
Sub Sample02()
Call TimerStart '---- 測定開始
For i = 1 To 1000000
buf = Now 'yyyy/mm/dd hh:mm:ss
Next i
Call TimerStop '---- 約0.7秒
End Sub
Sub Sample03()
Call TimerStart '---- 測定開始
For i = 1 To 1000000
buf = Left$(Now, 10) 'yyyy/mm/dd
Next i
Call TimerStop '---- 約2.8秒_| ̄|○
End Sub
100万回実行させて、
・Date -> 約0.9秒
・Now -> 約0.7秒
でNowの勝ち。て言うかどちらも一瞬ですねw。
もしかしたらLeft$(Now, 10)でDate()より速くなる?と思って試してみましたが、そうは問屋が卸しませんでした。
VBAでコードの実行速度を測定
コピペして使いまわしやすいようにモジュール化してみた。
計測したい処理の前で"TimerStart"をコールし、処理が終了したら"TimerStop"をコールする。
Public StartTime As Double
Public EndTime As Double
Sub TimerStart()
StartTime = Timer
End Sub
Sub TimerStop()
EndTime = Timer
MsgBox (EndTime - StartTime & " 秒")
End Sub
Sub Sample01()
Call TimerStart '---- 測定開始
'計測対象のコード
Call TimerStop '---- 測定終了, 結果表示
End Sub
Sample01を実行したら、当然0秒で終了します。
2010年5月24日月曜日
VBA配列の覚書
配列の方向をなかなか覚えられないので覚書。
まずは良い例。
Sub GoodExample()
Dim x(2, 0)
x(0, 0) = "a"
x(1, 0) = "b"
x(2, 0) = "c"
Range("A1:A3") = x
End Sub
実行するとA1:A3に'a','b','c'が出力される。
次に悪い例。
Sub BadExample()
Dim x(2, 0)
x(0, 0) = "a"
x(1, 0) = "b"
x(2, 0) = "c"
Range("A1:C1") = x '←間違い!
End Sub
実行するとA1:C1全てに'a'が出力されてしまう。
2010年5月23日日曜日
コードの表示
ブログ上でコードを思ったように表示させるのは意外と難しく、なかなか言う事を聞いてくれない。
この方法がベストなのかどうかは分からないけど、とりあえず、<pre><code>~ソース~</code></pre>のやり方で行くことにした。
スタイルシートに以下を追加。
pre {
background-color: #222222;
color: #33ff99;
margin-left: 2%;
margin-right: 5%;
}
code {
font-family: monospace, serif;
font-size: 1em;
line-height: 1.2;
}
昔のマイコン風に黒地に緑文字。
2010年5月19日水曜日
全シートでセルの選択範囲を同期②(Excel VBA)
標準モジュールへ以下のコードを書く。
Public GlobalCellRange As String
Public GlobalTopRow As Long
Public GlobalTopColumn As Long
Public Sub GetScrollPos()
With ActiveWindow
GlobalTopRow = .ScrollRow
GlobalTopColumn = .ScrollColumn
End With
End Sub
Public Sub SetScrollPos()
With ActiveWindow
.ScrollRow = GlobalTopRow
.ScrollColumn = GlobalTopColumn
End With
End Sub
WorkBookへ以下のコードを書く。
Private Sub Workbook_Open()
Call GetScrollPos
GlobalCellRange = Selection.Address
End Sub
WorkSheetへ以下のコードを書く。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Call GetScrollPos
GlobalCellRange = Target.Address
End Sub
Private Sub Worksheet_Activate()
Call SetScrollPos
Range(GlobalCellRange).Select
End Sub
前回の課題であった「表示されている範囲の同期」は達成。
今後の課題:ズームも同期出来るようにする。
2010年5月16日日曜日
全シートでセルの選択範囲を同期(Excel VBA)
標準モジュールへ以下のコードを書く。
Public GlobalCellRange As String
WorkSheetへ以下のコードを書く。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
GlobalCellRange = Target.Address
End Sub
Private Sub Worksheet_Activate()
Range(GlobalCellRange).Select
End Sub
ほぼ同じデータが入力されたシート同士を比較するときに、各シートの同じセルを手動で選択しながら比較する事が(僕の場合は)良くあるので自動化してみた。
ファイル名を"SelectSync.xls"とでもして、読み取り専用で持っておき、データを比較するときに使い捨てれば良い。
比較シートを増やしたい場合、シートをコピーすればシート内のコードもコピーされるため、各シートにちまちまと同じコードをコピペする必要はない。
今後の課題:シート切替時に、同一セルを選択するだけでなく、アクティブセル、表示されている範囲まで同期できれば、なお使い易いと思われる。
2010年5月1日土曜日
月配列R_20100501(やりすぎ?w)
変更しすぎてまともに打てません。_| ̄|○
数値上の成績は確実に悪くなっています。でも、自分の手には馴染むはず。多分w。
向こう3年打ちやすければいいや、と言う軽いノリで設計中。
wをシフトキーにしたのは、www <- これをスムーズに打つためw。
おk <- これをスムーズに打つために、"o = お"は外せない。日常で、最も高速入力が要求されるのは実はチャットだったりするのでw、上記「草」と併せてチャット対策是重要。
出来る限り多くの環境で使えるようにと、アルファベットキー以外は使わない方針でしたが、今回、"; = を"と"d, = ゃ"で記号キーを使いました。
"ly = び"は、ちょっと無茶してるかも知れない。でも"ly"は英文で割とよく出てくる運指なので、普段鍛錬しておく価値アリと言う事でヨシとする。
"ce = せい"もキツイ運指。でも、英文で"ce"は頻出だし、人差し指と中指を使って運指を最適化すれば速く打てるのでヨシとする。
"yu = ひと"もキツイ運指。でも、ローマ字入力で鍛えられている運指なのでヨシとする。
2010年4月25日日曜日
2010年4月17日土曜日
2010年3月31日水曜日
月配列R_20100330
シフトなし
こWとけひ|れるいおの
してDかは|っんKL
すそせきさ|くう
Dシフト
_____|ぬわあにえ
__Dろ_|やつまち
_____|みり
Kシフト
_ねゃほゆ|ぁぃぅぇぉ
なたょもら|_むK_
ふめゅよへ|__
Lシフト
ごだどげび|_ぢべ__
じでをがば|づぼぶL
ずぞぜぎざ|ぐヴ
Wシフト
_W___|__ぷぱ_
_____|_ぽぴぺ
_____|__
久々に大きく変更。
でも、意外とすんなり慣れてしまった。
配列変えに耐性がついたのかなw。
2010年3月28日日曜日
2010年3月7日日曜日
複数の入力法は共存できるのか
・私家版カナ配列(中指シフト)
・私家版行段系配列
・Qwertyローマ字入力
以上3つの日本語入力法を、混乱することなく使い分けられるかテスト中。
僕のこの努力は果たして世のため人のために役に立つのだろうかw
2010年2月20日土曜日
2010年2月14日日曜日
Libertouchのキー加重カスタマイズ その5
Libertouchのキー加重カスタマイズ その4
2010年1月24日日曜日
Libertouch
2010年1月23日土曜日
2010年1月17日日曜日
タイプウェル「B」@Qwertyローマ字入力
2009年11月8日日曜日の記事で、「ローマ字入力を復活させる事で、往年の指の回転を取り戻そう。」などと書いておきながら、がんばって打ってもBとはwww。
でもまぁだんだんスムーズに打てるようになってきたので、そろそろミス制限設定を0にしようと思います。
月配列R_20100112
まぁまぁ安定しているのでメモ的にアップ。
前回(20091231)との違いは、「ゃゅょ」の配置。これをシフト面に縦一列に並べてみました。
似た系列のカナはなるべく似た運指にまとめると言う試みなのですが、果たして吉と出るかどうか。
あとは、左手小指の使用率を下げるべく、「ら」と「ふ」の入れ替え。
「た」と「ょ」がシフト面なのは以前と変わらず。
2010年1月16日土曜日
登録:
投稿 (Atom)