ワークシートだけでやってみる

http://q.hatena.ne.jp/1296542184


120通りパターンを作り出す関数が以下。

="5" & MID("*/+-=",INT((ROW()-1)/24)+1,1) & "4" & MID(REPLACE("*/+-=",INT((ROW()-1)/24)+1,1,""),INT(MOD((ROW()-1),24)/6)+1,1) & "3" & MID(REPLACE(REPLACE("*/+-=",INT((ROW()-1)/24)+1,1,""),INT(MOD((ROW()-1),24)/6)+1,1,""),INT(MOD((ROW()-1),6)/2)+1,1) & "2" & MID(REPLACE(REPLACE(REPLACE("*/+-=",INT((ROW()-1)/24)+1,1,""),INT(MOD((ROW()-1),24)/6)+1,1,""),INT(MOD((ROW()-1),6)/2)+1,1,""),INT(MOD((ROW()-1),2))+1,1) & "1" & REPLACE(REPLACE(REPLACE(REPLACE("*/+-=",INT((ROW()-1)/24)+1,1,""),INT(MOD((ROW()-1),24)/6)+1,1,""),INT(MOD((ROW()-1),6)/2)+1,1,""),INT(MOD((ROW()-1),2))+1,1,"") & "0"

A1セルに入力して120行目までオートフィルすれば全てのパターンを列挙します。
一つの数式にしたので分かりづらいですが、面倒なので説明はしません。


次にこの数式を評価しないといけないのですが、VBAのevaluateは使えないので、
過去の遺物4.0マクロ関数を使います。


まずB1セルを選択して、数式→名前の管理→新規作成(2007の方法)からダイアログを開きます。
名前を「計算」にでもして、範囲を使っているシート、参照範囲を「=EVALUATE(A1)」にしてOK。
B1セルの数式を

=計算

にしてセルの右下をダブルクリックすれば、全ての計算結果がでます。
この中でTRUEとなっている式が成立してるというわけです。

とりあえず言っとけ祭

数年振りにはてなの社長こと近藤氏が人力検索に現れたということで、マンネリ化していた人力検索も一刻の盛り上がりを見せた。人力検索の機能要望の質問では短時間で多数の回答が付き、人力検索利用者のシステムに対する問題意識や不満の大きさを認識されたと思う。また、数年前には無かった短文での回答の多さに驚いたのではないかと思う。たくさんの回答が集まったように見えて実質的に内容のある回答は半分で、それ以外はうごメモ等の年少者によるものであったわけです。

 
実を言うとこの直前に私は近藤氏に最初で最後であろうメッセージを送っています。それは例のポイント集めの質問が年少者を巻き込んで活発化するのを看過できないとして、「人力検索で今起こっていることをご存知でしょうか?」という書き出しで直接訴えかけた内容でした。ただ直接訴えかけるような方法はルール違反だと思うので金輪際行わないようにしようと思います。その為かは定かではありませんが時期を置かず該当3質問は非表示となりました。


そのすぐ後の氏の数年ぶりの人力検索での質問を考えると、ひょっとしたら私のメッセージが人力検索に目を向けるきっかけになったのかもと邪推します。メッセージを送る際、気まぐれでポイントを100ポイントにしたのでそれを人力検索の質問に使ったのかもしれないと。


私やたぶん多くの人が求めていたことって、目に見える運営なんじゃないかと思います。システムが悪かろうと管理者が近くに感じられるシステムはこの先の希望があるからとても魅力的です。でもいつしか違反の通報や要望を正規の方法で送っても何のレスポンスも無くなってしまっていました。声を上げても無駄であると思って見限ったユーザーは去っていくだけでしょう。私のようにいつまでもしがみついてるユーザーもいるけどね。


まさかこれは見られてはいないと思うけど、以前こんな生意気なタイトルでブログを書いたことがあります。
人力検索はどうして失敗したか
その最後にこう書きました。


はてなの運営はどうすればいいかわからなければ聞けばいいのです。その為の人力検索でしょう」

夢の記憶

ごくたまに楽しかった学生の頃の夢を見ます。
すごくリアルで起きるまで夢だと気づかないときがあります。「あっ、夢だったのか」と。
それと同じようにあるとき目を開けたら、今まで生きてきた世界が夢だったなんてことが起こりはしないかとときどき想像するのです。


「25年前の自分に戻ったらどういう人生を送るか」という質問に柄にもなく小説形式で回答してみました。
http://q.hatena.ne.jp/1295696153


この回答では2つのことを念頭に置きました。一つは前の人生の記憶は夢のように曖昧な物と捉えたこと。夢のようにところどころ抜け落ちていたり、きっかけが無ければ思い出さなかったり。その方が毎回同じ過ちを繰り返すという話にもっていきやすいからです。ただし曖昧で漠然とした記憶でも人生に有利に働くことになります。例えばこの新商品は爆発的ヒットしそうな予感がするから発売先の株を買うとかできるわけです。


そしてもう一つ念頭に置いたのは時間移動では運命を変えられない世界観にすること。これはどういうことかと言うと、バック・トゥ・ザ・フューチャースター・トレックでは過去を変えることで未来がめちゃくちゃになるタイムスリップではなくて、ドラえもんのタイムスリップ感と言えば分かりやすいかもしれません。


ドラえもんの道具でのび太でも簡単に勝てるチャンバラ刀というのが出てくる話があります。のび太宮本武蔵と戦ってみたいと言ってタイムマシンで過去に行きますが、宮本武蔵を見つけることができず挙句の果てにチャンバラ刀を無くしてしまいます。その刀を拾ったのが宮本武蔵で以後無敵の剣豪になったというわけです。


この話で面白いのがタイムスリップも歴史の一部となっているということ。時間の因果律を変えるタイムスリップでも歴史の運命は変えられない。運命が時間の一次元上に存在しているような世界観です。それは人生をリプレイして変えようとするが本質的な部分では変えられず同じ頃に自殺する話にすることで表現しようとしました。タイムリープという神の力に対して、人間の知恵でどうにかできることの方が非現実的なような気がします。


続きの回答では、運命という神の力に対して挑戦しなくてはなりませんでしたが、目的のすり替えをして逃げました。男が望んていることはループからの脱出ではなくて、ループするが故の不幸からの脱出です。タイムリープも記憶を伴わなければ意味を持たないことに着目すれば、前世で記憶を消すというささやかな神への抵抗ができるというわけです。


でも不幸にならなければ自殺をしなくなり結果的にタイムループから脱出できるかと言えば答えはノーです。この男は前世の記憶を持たない一番最初にも自殺をしているはずだからです。ではこの男の運命はこれからどうなるかと言うと、何回か自殺を繰り返して記憶を消すという行為を繰り返すということになります。釈迦の手のひらからは逃れることはできないのでしょうかね。


回答した後でこんなことを考えました。もしもこの世界は死と夢が繋がっていても誰も否定できないんじゃないかって。人が死んだらその人の人生のある時点の夢で目を覚ます。そのときは記憶がほとんど消えて残るのは微かな夢の記憶だけ。それこそはたまに見るリアルな夢の正体なんて。
誰も死んだ後のことなんかわからないじゃない。

意外と知らないExcelの罠

仕事で使っているワークシートがありまして、入っている数式を上書きしたらわかるように
チェックするためのプログラムを作ってありました。


チェックでは二方向から合計したセルを比較することで一方が間違っているかがわかるというものです。


ところがこの比較するプログラムが明らかに同じセルの数値にFalseを返したのです。
更に調べるとワークシート関数で比較するとTrueを返します。


それで、セルに何が入っているかを調べる為にTypeName関数で型を調べると
どちらもDoubleであることがわかりました。


これはまるめによる誤差ではないかと調べるとわかりました。
http://msdn.microsoft.com/ja-jp/library/ae382yt8%28v=VS.80%29.aspx


関数の途中で剰余を使っていたために浮動小数点に誤差が生じていたのです。
この場合の解決方法として、誤差はたいてい小さな値なので差をとって一定値以下なら同じとしちゃえ
という乱暴な方法のようなので、その為の関数を作ってみます。

'浮動小数点数を比較する
Function DecHikaku(d1 As Double, d2 As Double) As Boolean
    If d1 = d2 Then
        DecHikaku = True
    Else
        If d1 > d2 Then
            If d1 - d2 < 0.0001 Then
                DecHikaku = True
            Else
                DecHikaku = False
            End If
        Else
            If d2 - d1 < 0.0001 Then
                DecHikaku = True
            Else
                DecHikaku = False
            End If
        End If
    End If
End Function


今まで意識せずに=で比較してたケースでも例外が発生するケースは重々にあるようです。

http://q.hatena.ne.jp/1290914062


もう終わった質問のようだけど自分だったらこういう回答になるかな。


まず、セルに入力状態の時にマクロを実行するのは不可能。
それでセルを選択するときに右のセルの文字列をクリップボードにコピーし、
マクロではなくCtrl+Vで貼りつければ同様のことができるのではないかと。


具体的にはセルの選択時にコピーするコードはこちら。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim CB As New DataObject
    
    CB.SetText Target.Offset(0, 1).Value
    CB.PutInClipboard
End Sub

※ Microsoft2.0 Object Livraryの参照設定が必要。

                                                                                                                                                            • -


B1セルに限らず19文字のロシア語全部をExcelでロシア語キーボードにしてしまいます。


次のようにシートを作ります。


標準モジュールの先頭に

Public myRange As Range


シートモジュールに

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Intersect(Target, Range("B1:T1")) Is Nothing Then
        Set myRange = Target
    Else
        myRange.Value = myRange.Value & Target.Value
        myRange.Select
        SendKeys "{F2}"
    End If
End Sub


これでA1セルに限らず任意のセルで入力中にロシア語を入力するときに該当の
セルをクリックすることで入力され、入力状態に戻るマクロとなります。

VBAから一括してマクロを削除するコード


調べるとそのまま使えるコードがありました。
http://chaichan.web.infoseek.co.jp/vbtips/VBMemo2006081403.htm
※ セキュリティ設定と参照設定は必要。

Sub Macro()
    Dim objVBCOMPO As Object
    For Each objVBCOMPO In ActiveWorkbook.VBProject.VBComponents
        With objVBCOMPO.CodeModule
            If .CountOfLines <> 0 Then .DeleteLines 1, .CountOfLines
        End With
        If (objVBCOMPO.Type = vbext_ct_StdModule Or objVBCOMPO.Type = vbext_ct_MSForm) Then
            ActiveWorkbook.VBProject.VBComponents.Remove objVBCOMPO
        End If
    Next objVBCOMPO
    Set objVBCOMPO = Nothing
End Sub


このコードを実行すると、標準モジュールだけじゃなくてシートモジュールとかのコードも削除して
自分自身も消えてしまうという。

住所分割

http://q.hatena.ne.jp/1283352623


面白そうなので、VBAでZIPJISを使った住所分割をしてみる。
ZIPJISを解凍すると、ZIPJIS9B.K3というファイルがCSVのデータのようなので、
このファイルを実行させるエクセルファイルと同じ場所に置く。


次に以下のコードをコピペして実行。
アクティブなシートのA列に住所データが入っていれば分割される。
該当する住所が見つからない場合は、分割されないでB列とC列が空白なります。

Sub ZipSep()
    Dim FSO As Object
    Dim TS As Object
    Dim GYO As Long
    Dim strREC As String
    Dim h As Variant
    Dim i As Long
    Dim j As Long
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Dim lastRow1 As Long
    Dim lastRow2 As Long
    Dim s1 As String
    Dim s2 As String
    Dim p1 As Integer
    
    Application.ScreenUpdating = False
    
    Set ws1 = ActiveSheet
    Set ws2 = Worksheets.Add
    
    Set FSO = CreateObject("Scripting.FileSystemObject")

    Set TS = FSO.OpenTextFile(ThisWorkbook.Path & "\ZIPJIS9B.k3", 1, False)
    Range("A:A").ClearContents
    h = Split(TS.ReadLine, ",")
    Cells(1, 1).Value = Replace(h(2), """", "")
    GYO = 2
    Do Until TS.AtEndOfStream
        h = Split(TS.ReadLine, ",")
        If UBound(h) > 1 Then
            If Cells(GYO - 1, 1).Value <> Replace(h(2), """", "") Then
                Cells(GYO, 1).Value = Replace(h(2), """", "")
                GYO = GYO + 1
            End If
        End If
    Loop
    
    TS.Close
    Set TS = Nothing
    Set FSO = Nothing

    ws1.Activate
    
    lastRow1 = ws1.Cells(Rows.Count, 1).End(xlUp).Row
    lastRow2 = ws2.Cells(Rows.Count, 1).End(xlUp).Row
    
    For i = 1 To lastRow1
        s1 = ws1.Cells(i, 1).Value
        For j = 1 To lastRow2
            s2 = ws2.Cells(j, 1).Value
            If Left(s1, Len(s2)) = s2 Then
                Select Case Left(s2, 3)
                    Case "東京都"
                        ws1.Cells(i, 1).Value = "東京都"
                    Case "大阪府"
                        ws1.Cells(i, 1).Value = "大阪府"
                    Case "京都府"
                        ws1.Cells(i, 1).Value = "京都府"
                    Case "北海道"
                        ws1.Cells(i, 1).Value = "北海道"
                    Case Else
                        p1 = InStr(1, s2, "県")
                        If p1 > 1 Then
                            ws1.Cells(i, 1).Value = Left(s2, p1)
                        Else
                            ws1.Cells(i, 1).Value = ""
                        End If
                End Select
                ws1.Cells(i, 2).Value = Replace(s2, ws1.Cells(i, 1).Value, "")
                ws1.Cells(i, 3).Value = Replace(s1, s2, "")
                Exit For
            End If
        Next j
    Next i
    
    Application.DisplayAlerts = False
    ws2.Delete
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
End Sub


このZIPJISも都道府県は分割されていないので、コード中で分割する処理が必要となる。
また、正確に都道府県からの住所ならよいが、東京の人は区から書いたり、
大都市の人は普通に市から住所を書くことが多いと思う。
更にZIPJISは最新のデータであるが故に、昔の住所を使う人がいた場合はヒットしないことになる。
そこら辺までは不可能と言えば不可能か。