派遣事務員の迷走

派遣事務員コロ子。会社の犬。顔出しNG。常に迷走している。

FizzBuzzで覚えるVBA(いろんなFizzBuzzを紹介するよ)

こんにちは。
派犬事務員のコロです。

FizzBuzzにハマるウサ子

2回目の講座の宿題FizzBuzzにウサ子がドハマりして、毎日のようにいろんなFizzBuzzが送り付けられてきたので、変なの優秀なのを紹介します~。

FizzBuzzとはプログラミングの練習問題のこれ↓

数字を1から順に100までデバッグ出力します。
ただし
・数字が3の倍数のときには数字の代わりに「Fizz
・数字が5の倍数のときには数字の代わりに「Buzz」
・数字が3の倍数かつ5の倍数のときには代わりに「FizzBuzz
と出力するようにしてください。

多分全部で20~30個あったと思う。
新しい構文が出てくるたびにFizzBuzzが送られてきて、ウサ子曰く「FizzBuzzVBAを覚えた」らしい。
VBAを勉強してるけど「なかなか使うところがない」という人はいろんなFizzBuzzを考えてみよう。

毎日のように送られてきたFizzBuzz


回答1(足し算バージョン)
習得できると思われるスキル
①ループ
②If文
へんてこレベル:★

Sub FizzBuzz1()

    Dim x As Long: x = 3
    Dim y As Long: y = 5
    Dim z As Long: z = x * y
    
    Dim i As Long
    For i = 1 To 100
    
        If i = z Then
            Debug.Print "FizzBuzz"
            x = x + 3
            y = y + 5
            z = z + 15
        ElseIf i = y Then
            Debug.Print "Buzz"
            y = y + 5
        ElseIf i = x Then
            Debug.Print "Fizz"
            x = x + 3
        Else
            Debug.Print i
        End If
        
    Next i

End Sub

おお!Modを使わないタイプ!
全部足し算で考える。


回答2(ブール比較バージョン)
習得できると思われるスキル
①If文(Trueのとき処理を行う)
へんてこレベル:★

Sub FizzBuzz2()

    Dim x As Boolean
    Dim y As Boolean
    Dim z As Boolean
    Dim i As Long
    For i = 1 To 100
        x = i Mod 3 = 0
        y = i Mod 5 = 0
        z = i Mod 15 = 0
        If z = True Then
            Debug.Print "FizzBuzz"
        ElseIf y = True Then
            Debug.Print "Buzz"
        ElseIf x = True Then
            Debug.Print "Fizz"
        Else
            Debug.Print i
        End If
    Next i

End Sub

「IF 式 Then」の式がTrueのとき処理を行う、とういうのを理解していて良い。
「 If z = True Then」は、zはTrueなので「 If z Then」と書くのがスマートかも。


回答3(周期バージョン)
習得できると思われるスキル
①Select Case文
Select Case文の優れているところは、Orで繋ぐ条件式が複数の場合はカンマ「,」で繋げて書けるトコ。
へんてこレベル:★

Sub FizzBuzz3()

    Dim i As Long
    Dim cnt As Long
    Dim loopcnt As Long
    
    For i = 1 To 100
    
        cnt = cnt + 1
        
        Select Case cnt
        Case 3, 6, 9, 12
            Debug.Print "Fizz"
        Case 5, 10
            Debug.Print "Buzz"
        Case 15
            Debug.Print "FizzBuzz"
            cnt = 0
            loopcnt = loopcnt + 1
        Case Else
            Debug.Print cnt + 15 * loopcnt
        End Select
    
    Next i
    
End Sub

考え方は、15で一周期。

回答4(掛け算バージョン)
習得できると思われるスキル
①四則演算?
へんてこレベル:★★

Sub FizzBuzz4()

    Dim x As Long, y As Long, z As Long
    x = 3
    y = 5
    z = x * y
    
    Dim ch1 As Long, ch2 As Long, ch3 As Long
    ch1 = 1
    ch2 = 1
    ch3 = 1
    
    Dim i As Long
    For i = 1 To 100
        If i = z * ch1 Then
            Debug.Print "FizzBuzz"
            ch1 = ch1 + 1
            ch2 = ch2 + 1
            ch3 = ch3 + 1
        ElseIf i = y * ch2 Then
            Debug.Print "Buzz"
            ch2 = ch2 + 1
        ElseIf i = x * ch3 Then
            Debug.Print "Fizz"
            ch3 = ch3 + 1
        Else
            Debug.Print i
        End If
    Next i
    
End Sub

掛ける数を増やすのか。なるほど。


回答5(文字列バージョン)
習得できると思われるスキル
①型の変換
へんてこレベル:★★★★★★★★★★
数値を文字列にして判定する。

Sub FizzBuzz5()

    Dim i As Long
    Dim stri As String
    
    For i = 1 To 100
    
        'iを15で割った数値を文字列に変換する
        stri = Cstr(Round((i / 15), 10))

        If Len(stri) = 1 Then
            Debug.Print "FizzBuzz"
        ElseIf Len(stri) = 3 Then
            Debug.Print "Fizz"
        Else
            If Mid(stri, 3, 1) = Mid(stri, 4, 1) Then
                Debug.Print "Buzz"
            Else
                Debug.Print i
            End If
        End If

    Next i
End Sub

え?っと思った人。これを見て欲しい。

A列の値を15で割ると、なんか法則があるっぽい。

A列の値が3の倍数のとき:「0.2」「0.4」など文字列にすると3文字(点も1文字になる)
A列の値が5の倍数のとき:「0.333・・」「0.666・・・」など、3文字目と4文字目が同じ値
A列の値が15の倍数のとき:「1」「2」「3」など1文字

おお!!これはなかなか思いつかない!
ちなみに
i=1のとき
stri = Cstr(i / 15)
だと「6.66666666666667E-02」となってしまうので
stri = Cstr(Round((i / 15), 10 ) )と少数以下を10桁にして指数表示にならないように工夫したらしい。
でも、なんで1/15のときだけ指数表示になるんだろう?


回答6(イベントプロシージャもどきバージョン)
習得できると思われるスキル
①Functionプロシージャ
へんてこレベル:★★★★★★★★★
「Functionプロシージャはワークシート関数としても使えますよ。」とは言ったけど、こんなのを作るとは!


「はい、入れました」


「イミディエイトウインドウを見るのね?」

えっ!!イベントプロシージャ?
と思ったらFunction関数!

Function StartFizzBuzz(ByVal x As String) As String

    If x <> "" Then
        Call FizzBuzz
        StartFizzBuzz = "イミディエイトウィンドウを見てね"
    Else
        StartFizzBuzz = "A1セルに何か入れて"
    End If

End Function

'************************************************************
Sub FizzBuzz()

    Dim i As Long
    
    For i = 1 To 100
    
        If i Mod 15 = 0 Then
            Debug.Print "FizzBuzz"
        ElseIf i Mod 5 = 0 Then
            Debug.Print "Buzz" 
        ElseIf i Mod 3 = 0 Then
            Debug.Print "Fizz"
        Else
            Debug.Print i
        End If
        
    Next i

End Sub

B1セルに自作のFuction関数を入れて、引数をA1セルにする。

A1セルに値が入ってる場合はイミディエイトウインドウにFizzBuzzを出力する、という仕組み。
なんか簡易イベントプロシージャって感じ。すごい!
めちゃめちゃびっくり!



回答8(足し算しばりバージョン)
へんてこレベル:★★★★

Sub FizzBuzz8()

    Dim i As Long
    Dim num1 As Long
    Dim num2 As Long
    Dim num3 As Long
    Dim num4 As Long
    num1 = 3
    num2 = num1 + 3
    num3 = num2 + 3
    num4 = num3 + 3
    Dim num5 As Long
    Dim num6 As Long
    Dim num7 As Long
    num5 = 5
    num6 = num5 + 5
    num7 = num6 + 5
    Dim x As Long
    x = 15
    
    For i = 1 To 100
    
        If i = num7 Then
            Debug.Print "FixxBuzz"
            num7 = num7 + x
        ElseIf i = num6 Then
            Debug.Print "Buzz"
            num6 = num6 + x
        ElseIf i = num5 Then
            Debug.Print "Buzz"
            num5 = num5 + x
        ElseIf i = num4 Then
            Debug.Print "Fizz"
            num4 = num4 + x
        ElseIf i = num3 Then
            Debug.Print "Fizz"
            num3 = num3 + 1
        ElseIf i = num2 Then
            Debug.Print "Fizz"
            num2 = num2 + x
        ElseIf i = num1 Then
            Debug.Print "Fizz"
            num1 = num1 + x
        Else
            Debug.Print i
        End If
        
    Next i

End Sub


回答9(引き算しばりバージョン)
へんてこレベル:★★★★

Sub FizzBuzz9()

    Dim i As Long
    Dim x As Long
    Dim y As Long
    Dim z As Long
    Dim th As Long
    Dim fi As Long
    Dim ft As Long
    th = 3
    fi = 5
    ft = 15
    Dim nt As Long
    Dim tt As Long
    Dim nn As Long
    For i = 1 To 100
        If i - ft - x = 0 Then
            Debug.Print "FizzBuzz"
            nt = 90
            x = NewFizzBuzz(x, i, ft, nt)
            y = x
            z = x
        ElseIf i - 5 - y = 0 Then
            Debug.Print "Buzz"
            tt = 100
            y = NewFizzBuzz(y, i, fi, tt)
        ElseIf i - 3 - z = 0 Then
            Debug.Print "Fizz"
            nn = 99
            z = NewFizzBuzz(z, i, th, nn)
        Else
            Debug.Print i
        End If
    Next i

End Sub

'***************************************************************************************************

Function NewFizzBuzz(ByVal x As Long, ByVal i As Long, ByVal mn As Long, ByVal cn As Long) As Long

    Dim cnt1 As Long
    cnt1 = 100
    Dim j As Long
    Dim l As Long
    Dim m As Long
    m = i
    If x = 0 Then
        For j = 1 To 100
            cnt1 = cnt1 - mn
            If cnt1 < mn Then
                Exit For
            End If
        Next j
        j = j - 1
    Else
        For l = 1 To 100
            m = m - mn
            If m = 0 Then
                Exit For
            End If
        Next l
        For j = 1 To 100
            cnt1 = cnt1 - mn
            If cnt1 < mn Then
                Exit For
            End If
        Next j
        j = j - l
    End If
    Dim k As Long
    For k = 1 To j
        cn = cn - mn
    Next k
    x = cn
    NewFizzBuzz = x
    
End Function


回答10(中級バージョン)
習得できると思われるスキル
①ループでのカウンタ変数の指定数の増減
②配列

Sub FizzBuzz10()

    Dim arr(0 To 100) As String
    
    '配列に代入
    Dim i As Long
    
    For i = 0 To 100 Step 3
        arr(i) = "Fizz"
    Next i
    
    For i = 0 To 100 Step 5
        If arr(i) = "" Then
            arr(i) = "Buzz"
        Else
            arr(i) = "FizzBuzz"
        End If
    Next i
    
    'イミディエイトウインドウに出力
    For i = 1 To 100
        If arr(i) = "" Then
            Debug.Print i
        Else
            Debug.Print arr(i)
        End If
    Next i

End Sub


回答11(意味不明バージョン)

Sub FizzBuzz11()

    Dim i As Long
    Dim j As Long
    Dim k As Long
    Dim l As Long
    k = 1
    
    For i = 1 To 100
        For j = 1 To 5
            If j = 1 Then
                For l = 1 To 3
                    If i Mod 3 = 0 Then
                        Debug.Print "Fizz"
                        i = i + 1
                    Else
                        Debug.Print i
                        i = i + 1
                    End If
                Next l
            ElseIf j = 2 Then
                For l = 1 To 3
                    If i Mod 3 = 0 Then
                        Debug.Print "Fizz"
                        i = i + 1
                    ElseIf i Mod 3 = 2 Then
                        Debug.Print "Buzz"
                        i = i + 1
                    Else
                        Debug.Print i
                        i = i + 1
                    End If
                Next l
            ElseIf j = 3 Then
                For l = 1 To 3
                    If i Mod 3 = 0 Then
                        Debug.Print "Fizz"
                        i = i + 1
                    Else
                        Debug.Print i
                        i = i + 1
                    End If
                Next l
            ElseIf j = 4 Then
                For l = 1 To 3
                    If i = 101 Then
                        Exit Sub
                    Else
                        If i Mod 3 = 0 Then
                            Debug.Print "Fizz"
                            i = i + 1
                        ElseIf i Mod 3 = 1 Then
                            Debug.Print "Buzz"
                            i = i + 1
                        Else
                            Debug.Print i
                            i = i + 1
                        End If
                    End If
                Next l
            ElseIf j = 5 Then
                For l = 1 To 3
                    If i Mod 3 = 0 Then
                        Debug.Print "FizzBuzz"
                    Else
                        Debug.Print i
                        i = i + 1
                    End If
                Next l
            End If
        Next j
        j = 1
    Next i

End Sub

他にも意味不明なのが多数。
確かにFizzBuzz楽しいけど、こんなにハマる人初めて見た・・・。

みんなの凄いFizzBuzzがあったら教えてね。

VBA講座の講師をやりました!

こんにちは。
派犬事務員のコロ子です。

あっという間にお祭りシーズン

お久しぶりです~。
実は、ノンプロ研VBA初心者講座の講師をさせて頂きました!
先日講座を終えて、燃え尽き症候群というか放心状態というかも抜けの殻状態だけど、これが通常運転なので日常に戻ってきました。

5月下旬に講師のお話を頂いてから、テンパり過ぎてブログところか、何も手につかず日常生活に支障をきたすレベルで怯えてました。
緊張し過ぎて夜寝れないのに、昼間は眠くて居眠りする。
小心者なのに神経図太いわけではないですよ。生命維持のための防衛機能、だと思う・・・。

The内向的な性格

しゃべるの苦手。人前で話すなんてもってのほか。超内向的な性格。
「石橋を叩いて渡る」というより「石橋を叩きすぎて壊すタイプ」なんて言われた事があるけど、どちらかというと「石橋を叩いて手を痛め、おそるおそる石橋を渡り、緊張し過ぎて固くなり、足を滑らせ石橋から落下するタイプ」だと思う。そして落下先の川で慌ててバシャバシャ泳ぎ、元来た岸にたどり着く。たまにまぐれで対岸に泳ぎ着いたときは「やればできるじゃん!」と言われたりする。

今回の講座では、高橋さんや先代の講師が作り上げた強靭な石橋は壊れるはずもないのに、ビビり過ぎて無駄に叩き、足を滑らせ橋から落ちたところに、ティーチングアシスタント(TA)から浮き輪が投げられ、「助かった~、ナイスアシストです!」という間に浮き輪ごと引っ張られ対岸に到着、という感じで無事終了しました。

どんな練習をしたか

たまたまネットの記事で「内向的な性格の人は思慮深く集中力がある」的なのを見た。内向的だけど、思慮深くないし集中力もない。これは人によると思う。
そして「内向的な人は完璧に準備をした方が良い」的な事も書いてあった。
なるほど。完璧は難しいけど、ちゃんと準備すれば少しは安心できる。
最初はスライドを見ながらしゃべる練習を繰り返し行った。
スライドを見ているときは「こうやって説明しよう」と思っていても、実際に声に出してしゃべってみると言葉が出てこない。あたまの中がぐるぐるになって無言。そのまま固まる。
語彙力が少ないのが原因なのか、日頃からしゃべり慣れていないのがいけないのか。

事前打ち合わせのときに、TAさんから「理解してもらうのが目的で、かならずしも流暢にしゃべる必要はない。」と言われちょっと楽になった。また「話すことを全部書くと良い」とアドバイス頂き、スライド50~60枚分を書き出してみたが、読んでみるとなんか変。前後繋がってないというか説明になっていない。喋るのがダメでなく、書くのもダメだった。言葉を扱う能力に問題アリ、ということか・・・。
でも、いざとなればカンニングペーパーがある、という安心感で少し落ち着いた。

書くのも話すのも苦手だけど克服した、という方、アドバイスください。

環境について

デスクトップPCと壊れそうなノートPCを所有。
ノートPCをデスクトップPCのサブモニタにしようと思ったけど、ノートPCが時々固まる・立ち上がらない、WiFiが不安定、の理由で断念。(今回断念したけど、なかなか良い方法だと思う)
www.youtube.com

モニターをもう一つ買ってデュアルモニターにしようとも思ったけど(先代講師の方はみんなデュアルモニターだった)、机が狭い→部屋が狭い→小屋が狭い、という小屋が狭いのはどうにもならないので断念。

ということで、シングルモニターで仮想デスクトップを使ってみました。
tonari-it.com
↑Windows11でもOK
デスクトップ1:講座のスライド
デスクトップ2:Excel
Slack、x(旧Twitter)は予備のノートPCまたはスマホで対応。

何とかなったけど、やっぱりモニターは2つ以上あった方がやりやすいと思う。

FizzBuzzにハマるウサ子

少ししゃべるようになったところで、ウサ子に練習相手になってもらった。ウサ子はちょっとVBAをかじったことがある程度の初心者なので絶好の練習相手だ、と思ったけど・・・。
2回目の講座の宿題のFizzBuzzにウサ子がドハマりした。

どんな問題かというと

数字を1から順に100までデバッグ出力します。
ただし
・数字が3の倍数のときには数字の代わりに「Fizz
・数字が5の倍数のときには数字の代わりに「Buzz」
・数字が3の倍数かつ5の倍数のときには代わりに「FizzBuzz
と出力するようにしてください。

そうそう、よくあるプログラミングの練習問題のアレですよ。

FizzBuzz楽しー!」
とか言いながら、ものすごい勢いで2個、3個、4個と作りつづけ、毎日のようにメールが届く。
講座の練習をしようとパソコンを開くとDos攻撃のようにウサ子からの「FizzBuzz攻撃」。
練習させない気かー!!
そして顔を合わせるたびに「新しいFizzBuzz見てくれた?」とドヤ顔で聞いてくる。
意味不明なのが多いので次回ウサ子の「FizzBuzz特集」するので一緒に見てほしい。

感想

卒業LT大会(こんなの作ったよ、を発表してもらう会。卒業制作発表会)で受講生の発表が素晴らしくて感動!!!
こんなボロボロだったのに「親は無くとも子は育つ」なのか。みんなちゃんとできてて嬉しー!ありがとうございました。
それにしてもノンプロ研が偉大過ぎる。こんなコロ子が講師ですよ!!

Excelでお絵描き(ちいかわが描けるコードあるよ!)

こんにちは。
派犬事務員のコロ子です。


うさ子:最近「ちいかわ」にハマってるの~。Excelでお絵描きしてるんだ。見て!見て!

コロ子:えっ!これExcelで書いたの?
うさ子:そうだよ。図形を組み合わせて作ったの~。

な、なんと!無駄な才能!こんな事ができても何にもならないのに!
お絵描きソフトが買えないビンボーなうさ子。
ときに、ビンボーは無駄な才能を開花させるのか・・・。

うさ子の作品集

ちいかわ
ハチワレ
うさぎ
くりまんじゅう
お出かけ

コピペで作れるよ

下のコードをコピペで、うさ子の作ったちいかわが書けるよ!

めちゃめちゃ長いのでソースコードはをクリックして表示してね。

Excelのバージョンなどでうまく位置が合わない可能性もあるかも。

これらのコードをどうやって作ったか、というと、
Sheet1(図形があるシート)の図形をすべてループしてプロパティを取得するコードをActiveSheetに出力して作成した。


これを実行すると、ActiveSheetに下の図のようにコードが出力されるので、これをVBEエディタにコピペする。

Sub ちいかわ()

    Dim ws As Worksheet
    Set ws = ActiveSheet

    'セルの色をピンク
    ws.Cells.Interior.Color = 10040319

'ここセルに出力されたコードをにコピペ

End Sub
セルに出力されたコード

ちいかわとハチワレ以外も作りたかったけど、図形のフリーハンドを使っていて上手くいかず・・・。
次の機会(あるのか?)チャレンジするかも。

おまけ

うさぎとどんぐり
二日酔い

MKG(味噌汁かけごはん)をもうビンボー飯と呼ばせない!

こんにちは。
派犬事務員のコロ子です。

河津桜さいてますね


お給料は上がらないのに、物価の上昇が骨身にしみる・・・。


うさ子:あ~、お腹すいた~。コロ子何か作って~。
コロ子:えー、何にもないよー。味噌汁かけごはんでいい?
うさ子:やだよ!そんな貧乏飯食べたくないよ!!
コロ子:うさ子だってビンボーなんだから文句言うんじゃないよ!

そもそも、なんで味噌汁かけごはんは貧乏飯とカテゴライズされ嫌われているのだろうか。
コロ子的には「たまごかけごはん」も「お茶づけ」も同系列だと思うのに、たまごかけごはんは「TKG」などと呼ばれもてはやされていたり、お茶漬けは永〇園がお茶漬けの素などを販売していて、しっかり市民権を得ている。

そうだ、味噌汁かけごはんも「MKG」と呼ばれ、貧乏飯から脱出すればいいのだ!

MKGとは

Mostんたんはん
ご飯に味噌汁をかけるだけ。前日の残りで簡単にできるし、もちろんレンチンのご飯と、お湯を注ぐだけの簡易味噌汁でもOKだ。
忙しいビジネスパーソンや、時間がないときにピッタリの簡単ごはんだ。

Modern康的はん
味噌は発酵食品なので、健康的なことは間違いない。具材に野菜をたっぷり入れればさらに健康的だ。味噌汁はだいたいどんな具でも合うから素晴らしい。
味噌・出汁・具材にこだわれば、意識の高い人にもピッタリな健康ご飯だ。

この理由でMKGを食べない理由はないだろう。
みんなが堂々とMKGを食べ、日本人のソウルフードになればいいのに。

MKGアレンジ例

①TMKG
TKGとのコラボMKG
卵は味噌汁の具としてもあるので、絶対おいしいはず(未検証)
卵を溶いても、月見タイプでもご自由に!

②カレーMKG
横須賀海軍カレーは味噌が入っているらしい。
昔の海軍さんはインドのカレースパイスに近づけようと、いろいろ思考錯誤して味噌を入れたとか。
だから絶対カレーにも合うはず!(未検証)

蒙古タンメン中本 辛旨味噌MKG
セブンイレブンに売っているあのカップラーメンでMKGを作ってみよう。(未検証)
麺を食べ終わった汁は捨ててはいけない。
もはや味噌汁じゃない!?ですって?
MKGはそんなケチなことはいわない。味噌味のスープならなんでもOKだ。
MKGの心は広い。


MKGの標語を募集するよー

んな大好き民的はん
ナー悪くないちんとはん

MKG By うさ子(雑だなぁ)

同じユーザーフォームを複数同時に表示させる

こんにちは。
派犬事務員のコロ子です。

前回「ユーザーフォームは作った瞬間にインスタンスが生成されてオブジェクトが使えるようになる」の記事を書いたら
「あえてインスタンスを生成することもできるよ」と教えていただいた。
ということは、同じユーザーフォームを複数同時に表示することもできるのか!?
さっそく試してみよう!

同じユーザーフォームを複数同時に表示させる

このユーザーフォームを2つ同時に表示する

Sub Test1()

    Dim uf1 As UserForm1
    Dim uf2 As UserForm1

    Set uf1 = New UserForm1
    Set uf2 = New UserForm1

    uf1.Show vbModeless
    uf1.TextBox1.Value = 100 ’←値の代入はフォーム表示の前でも後でも可

    uf2.Show vbModeless
    uf2.TextBox1.Value = 200
    uf2.Top = uf1.Top + 150 ’←フォームの位置設定はフォーム表示後に行う

End Sub

おお!できた!

【解説】

UserForm1型の変数を宣言してNewでインスタンスを生成する

Sub Test1()

    Dim uf1 As UserForm1
    Dim uf2 As UserForm1
    
    Set uf1 = New UserForm1
    Set uf2 = New UserForm1

ユーザーフォームはモードレス(vbModeless)で開く。
モードレスにしないとuf1を閉じてからでないとuf2が表示されない。

    uf1.Show vbModeless

uf1とuf2が同じ位置に重ならないようにuf2を下にずらす。

    uf.Show vbModeless
    uf.Top = FormTop

フォームの位置はフォームを表示してから設定しないとエラーになる。
TextBoxへの値の代入はフォーム表示の前でも後でも可。

ダブルクリックしたらどんどんフォームが開くのを作る

なんか楽しいのでダブルクリックしたらフォームが開くのを作ってみた。
クリックした数字をTextBox1に入れてどんどんフォームを開く。


シートモジュールに記載するコード

'2番目以降のフォームの位置。パブリック変数を用意する
Public FormTop As Long

'ダブルクリックのイベント
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)

    Dim uf As UserForm1
    Set uf = New UserForm1
    
    '前に作ったフォームと重ならないようにする
    FormTop = FormTop + 100
    
    uf.TextBox1.Value = Target.Value
    uf.Show vbModeless
    uf.Top = FormTop

End Sub

フォームモジュールに記載するコード

フォームを閉じるごとにフォームの開始位置を戻す

'ユーザーフォームを閉じるとき
Private Sub UserForm_Terminate()

    Sheet1.FormTop = Sheet1.FormTop - 100

End Sub

VBA ユーザーフォームは作った瞬間にオブジェクトが使えるようになる!?(コロ子勘違いしていた)

こんにちは。
派犬事務員のコロ子です。


お久しぶりです。長らくブログを書いてなかったけど、やめたわけじゃないよ~。
最近仕事で変な単調作業をしていて犬小屋に帰ってからぐったり疲れてパソコンを触る元気がなかったので。
VBAを書く仕事は全然疲れないのに単調作業は本当に疲れて困るわぁ~(>_<)


ユーザーフォームについて、またまた勘違いしてました・・・。

何を勘違いしていたかというと、ユーザーフォームって作った瞬間にインスタンスが生成されてオブジェクトが使えるようになるんですね。

どーゆーことかというと、
①「ボタン1」と押すとUserForm1が表示される。
②TextBox1に数字を入力する。
③UserForm1の「OK」ボタンを押すとTextBox2にTextBox1を10倍した数字が入る。
このようなフォームの場合、

この処理のコードは下記のようになる。

「ボタン1」に登録するコード(Sheetモジュールか標準モジュールに記載)
Public Sub ボタン1()
 'ユーザーフォームを表示する
    UserForm1.Show
End Sub
UserForm1のOKボタンを押したときのコード(UserForm1モジュールに記載)
Private Sub CommandButtonOK_Click()
 'TextBox2にTextBox1×10を入力
    TextBox2.Value = TextBox1.Value * 10
End Sub

ねーねー。
「ボタン1」を押してフォームが表示されるのも必要だけど、シートの数字をダブルクリックしたら、最初からその数字がTextBox1に入ってフォームが表示されるようにできる?
さらにTextBox2にも×10の値を入れといてねー。

楽勝!

できますよ~。すぐやりますね~。

簡単だよー、秒でできるよー、と下記のコードを書いたら

シートモジュールのダブルクリックイベント
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    
    UserForm1.Show
   
    UserForm1.TextBox1.Value = Target.Value
    Call UserForm1.CommandButtonOK_Click
    
End Sub

※【注意】他のモジュールからCallするので
Private Sub CommandButtonOK_Click()

Public Sub CommandButtonOK_Click()
に変更する。

あれー・・・。

UserForm1.TextBox1.Value = Target.Valueに数字が入っていない。
どーゆーことかと、ステップ実行をしてみたら

ダブルクリックのイベントの中でユーザーフォームを開くので、次の処理はユーザーフォームを閉じてからじゃないと実行できないのね。なるほど~!
でも、何か変だなぁ。ユーザーフォームを閉じているのに何でUserForm1.TextBox1.Value = Target.Valueがエラーにならないんだろう・・・?

もう1回ダブルクリックでユーザーフォームを開いてみると、
なんと!!さっきダブルクリックした値が入っているではないですか!

【1回目】
3をダブルクリックしてユーザーフォームを開く

TextBox1に値は入っていない

【2回目】
5をダブルクリックしてユーザーフォームを開く

1回目でダブルクリックした値が入っている。


【3回目】
さらに別の数字をダブルクリックしてユーザーフォームを開いてみると

2回目でダブルクリックした値が入っている。

ど、どういうこと?
何で前回の値を覚えているの?
ユーザーフォームってフォームを表示したときにインスタンスが生成されて、閉じたときに破棄されるんじゃないの???

???と思いながら、下記コードを試したてみた。

Sub Test1()
    UserForm1.TextBox1 = 10
End Sub

UserForm1.TextBox1 に10を入れる

Sub Test2()
    UserForm1.Show
    Debug.Print UserForm1.TextBox1.Value
End Sub

UserForm1が表示される。
TextBox1 に10が入っている。

Sub Test3()
   Debug.Print UserForm1.TextBox1.Value
End Sub

UserForm1を閉じて実行するとTextBox1は空欄。

ユーザーフォームは表示していないときもメンバーにアクセスできる。
ということは
①ユーザーフォームはVBEエディタで作った瞬間にインスタンスが生成されてオブジェクトが参照できる。
②閉じた時に値が破棄される。
ということなのね!

では、正解は

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)

    'TextBox1に値をセット
    UserForm1.TextBox1.Value = Target.Value
    
    'クリックイベントを呼び出す
    Call UserForm1.CommandButtonOK_Click
    
    'フォームを表示
    UserForm1.Show
    
End Sub

TextBox1に値をセットして
リックイベントを呼び出して
それからフォームを表示を表示する。

またまた、長いこと勘違いしてたわぁ~。全然楽勝じゃなかったわぁ~。
ユーザーフォームは表示された時にインスタンスが生成されると思ってた。
だって「UserForm_Initialize」ってイベントがあるから。。。

ということは、ユーザーフォームのメンバーの初期値は「Initialize」イベントの中で書かなくてもOKってこと?

例えば、下記のようなシートでユーザーフォームを表示するとき
「ボタン1」を押したら、コンボボックスにB列のデータを
「ボタン2」を押したら、コンボボックスにD列のデータを
表示させたいとき


いつも「Initialize」イベントで書いていたけど、これでいいんだよね。

「ボタン1」に登録するコード(Sheetモジュールか標準モジュールに記載)
Public Sub ボタン1()
    UserForm2.ComboBox1.RowSource = Range("B6:B20").Address
    UserForm2.Show
End Sub

「ボタン2」に登録するコード(Sheetモジュールか標準モジュールに記載)
Public Sub ボタン2()
    UserForm2.ComboBox1.RowSource = Range("D6:D20").Address
    UserForm2.Show
End Sub

もしかして「Initialize」イベント不要?
(いやいや、場合によるから)

VBAで①②③、ABCなどの連続番号を入力する(オートフィル風)

こんにちは。
派犬事務員のコロ子です。

休日は一瞬で終わる

①②③やABCのオートフィル風を作る

先日、「①②③とかABCとかをオートフィルできる方法ないんですか?」と質問を受けた。
どうやらないっぽい。関数とかで作れるみたいだけど、毎回関数を入れるのも面倒なのでVBAで作ってみよう。

Asc関数

「Asc関数」の戻り値は 「Shift_JIS文字コード」を利用して作成してみよう。
まずはShift_JIS文字コードを確認してみる。

右下のタスクバーの文字を右クリックしてIMEパッド」を開く

IMEパッドの左側から「シフトJIS」を選択する。

半角英数、記号などフォルダがいっぱいある。半角英数から英文字を探してみると、「ABC・・・Z」は連続した文字コードになっている。①~⑳も連続した文字コードになっている。ということは、ループで作れる!

オートフィル風は
①まず先頭に文字を入力する。
②連続文字を入力する範囲を選択する。
③選択した範囲に連続した文字が入るようにする。

上記のコードを作成する。

Sub 選択範囲を連続番号にする()

    Dim ran As Range
    Dim buf As Long

    For Each ran In Selection

        '先頭のセルの場合
        If ran = Selection(1) Then

            'Acsコードに変換
            buf = Asc(ran.Value)

        Else

            '文字コードに戻す
            buf = buf + 1
            ran = Chr(buf)

        End If

    Next ran

End Sub

コードができたら、どのExcelでも使えるように個人用マクロブックの「PERSONAL.XLSB」に登録する。

個人用マクロブックの作り方は↓の真ん中あたりを参考にして
https://koroko.hatenablog.com/entry/2019/09/10/211811

さらにクイックアクセスツールバーにマクロを登録する。
①ファイル→オプションより「クイックアクセスツールバー」を選択する
②マクロを選択する
③「選択範囲を連続番号にする」マクロを選択する
④追加をクリックする
⑤追加した「選択範囲を連続番号にする」マクロを選択する
⑥「変更」をクリックして好きなアイコンを選択する。
⑦「OK」をクリックする

オートフィル風の出来上がり!

もちろん、横方向にも、飛び飛びでもできるよ。


「あいうえお」の場合は「ぁあぃい、かが」など並び順が不規則なので注意!
また普通の数字もできないです。
その場合はこちらを参考に。

Sub 選択範囲を連続番号にする()

    Dim ran As Range
    Dim buf As Long

    '数字の場合
    If IsNumeric(Selection(1).Value) Then

        For Each ran In Selection

            If ran = Selection(1) Then

                buf = ran.Value

            Else

                buf = buf + 1
                ran = buf

            End If

        Next ran

    '日付の場合
    ElseIf IsDate(Selection(1).Value) Then

        Dim mydate As Date

        For Each ran In Selection

            If ran = Selection(1) Then

                mydate = ran.Value

            Else


                mydate = mydate + 1
                ran = mydate


            End If

        Next ran


    '「あいうえお」の場合(ぁあぃい、かが、など並び順が不規則なので)
    ElseIf InStr("あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん", Selection(1).Value) Then

        Dim i As Long
        For Each ran In Selection

            If ran = Selection(1) Then

                'Acsコードに変換
                buf = Asc(ran.Value) + 1

            Else

                Do

                    If InStr("あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん", Chr(buf)) Then

                        ran = Chr(buf)
                        buf = buf + 1
                        Exit Do

                    Else

                        buf = buf + 1

                    End If

                Loop

            End If

        Next ran

    '他(①とかAとか)
    Else

        For Each ran In Selection

            If ran = Selection(1) Then

                'Acsコードに変換
                buf = Asc(ran.Value)

            Else

                '文字コードに戻す
                buf = buf + 1
                ran = Chr(buf)

            End If

        Next ran

    End If

End Sub

シフトJIS」表を見ながらオリジナルの連続番号を作ってみよう!