MW211 EXIT

devlog
ExceVBA/プレースホルダの型指定
2020年09月18日
ExceVBAにおけるプレースホルダ(ADODB.Command.CreateParameter)のデータ型は
以下の通り。
┌───────┬──┬─┬────┐
│プレースホルダ│ 値 │幅│MSSQL型 │
├───────┼──┼─┼────┤
│adBoolean     │  11│-│bit     │
│adInteger     │   3│-│int     │
├───────┼──┼─┼────┤
│adChar        │ 129│○│char    │
│adWChar       │ 130│○│nchar   │
│adVarChar     │ 200│○│varchar │
│adVarWChar    │ 202│○│nvarchar│
├───────┼──┼─┼────┤
│adDate        │   7│-│date    │
│adDBTimeStamp │ 135│-│datetime│
└───────┴──┴─┴────┘
分類:ExcelVBA
ExcelVBA/フォーム入力欄チェックの落とし穴(3)
2020年09月12日
さて、(1)~(2)で対応完了だが、なんとなく関係なページでも発動するのが嫌だ。
ってことで特定のページのみに限定する方法。

まず、Exitイベントだがこれは簡単で、Exit前のページ番号が取得できるので
それを参照すればよい。
(なお、ページ番号は値としては0オリジンで管理されているので注意)
┌──────────────────────────────────────┐
│Private Sub MultiPage_Exit(ByVal Cancel As MSForms.ReturnBoolean)           │
│    If Me.MultiPage.Value = 2 Then ' 3ページのみ限定                        │
│        ' 入力チェックや補正                                                │
│    End If                                                                  │
│End Sub                                                                     │
└──────────────────────────────────────┘

次に、ChangeイベントだがこれはChange後のページ番号になってしまうので厄介だ。
Static変数に一つ前の値を記録しておくのがよいようだ。
いっそのこと、メンバ変数(Static変数も兼ねる)にしてしまった方が
わかりやすいということで以下のような感じになる。
┌──────────────────────────────────────┐
│Private m前ページ As Long                                                   │
├──────────────────────────────────────┤
│Private Sub UserForm_Initialize()                                           │
│    m前ページ = Me.MultiPage.Value                                          │
│End Sub                                                                     │
├──────────────────────────────────────┤
│Private Sub MultiPage_Change()                                              │
│    If m前ページ = 2 Then       ' 3ページのみ限定                           │
│        ' 入力チェックや補正                                                │
│        ' 入力チェックや補正                                                │
│        ' 入力チェックや補正                                                │
│    End If                                                                  │
│    m前ページ = Me.MultiPage.Value                                          │
│End Sub                                                                     │
└──────────────────────────────────────┘
分類:ExcelVBA
ExcelVBA/フォーム入力欄チェックの落とし穴(2)
2020年09月11日
マルチページの場合、他のページに直接飛んだ場合にも
Exitイベントが効かないようようだ。
┌──────────────────────────────────────┐
│Private Sub TextBox_Exit(ByVal Cancel As MSForms.ReturnBoolean)             │
│    ' 入力チェックや補正                                                    │
│End Sub                                                                     │
└──────────────────────────────────────┘

となると、いよいよページの変更イベントに仕込む必要も出てくる。
┌──────────────────────────────────────┐
│Private Sub MultiPage_Change()                                              │
│    ' 入力チェックや補正                                                    │
│    ' 入力チェックや補正                                                    │
│    ' 入力チェックや補正                                                    │
│End Sub                                                                     │
└──────────────────────────────────────┘
しかも、どの入力欄からなのかが定まらないのですべてに対応って感じになるのか?

そうなるとチェック処理を関数化したくなってくる。
引数に入力欄を渡す方法は以下のような感じになる。
┌──────────────────────────────────────┐
│Call 入力チェック(Me.TextBox)                                               │
├──────────────────────────────────────┤
│Private Sub 入力チェック(ByVal テキストボックス As MSForms.TextBox)         │
│    ' 入力チェックや補正                                                    │
│End Sub                                                                     │
└──────────────────────────────────────┘
分類:ExcelVBA
ExcelVBA/フォーム入力欄チェックの落とし穴(1)
2020年09月10日
フォームの入力欄にて入力直後に入力チェックや補正を行う処理を実装するには
Exitイベント(フォーカスアウト)に仕込めばよい、通常は。
┌──────────────────────────────────────┐
│Private Sub TextBox_Exit(ByVal Cancel As MSForms.ReturnBoolean)             │
│    ' 入力チェックや補正                                                    │
│End Sub                                                                     │
└──────────────────────────────────────┘

とこらが、マルチページ環境のページ(タブ)の中の最後の入力欄だった場合には
ページを離脱することになり、上記イベントが効かなくなる。
(同一ページ内の他のコントロールにフォーカスがあたらないからという解釈だろうか)

ま、画面設計を巧妙にいじって、その入力欄が最後にならないように配置するというのが
回避策として無難なところだが、他者からの依頼の場合など
そうもいっていられないことがある。

ということで、水面下で回避する方法。
┌──────────────────────────────────────┐
│Private Sub MultiPage_Exit(ByVal Cancel As MSForms.ReturnBoolean)           │
│    ' 入力チェックや補正                                                    │
│End Sub                                                                     │
└──────────────────────────────────────┘
なんのことはないページ離脱時に処理を移動すればいいのだ。(ちと微妙だが)
分類:ExcelVBA
ExcelVBA/WorksheetFunctionに配列引数(2)
2020年08月25日
引数が可変の場合、構成要素が数値や文字列なら、配列で指定ができるが
オブジェクト系(範囲など)だとこれができないっぽい。

例えばこんなイメージは無理。
┌──────────────────────────────────────┐
│MsgBox WorksheetFunction.CountIfs(配列)                                     │
└──────────────────────────────────────┘

ということで、代案。
CountIfs()の引数は最大30個なので
配列を30個あらかじめ用意して、NULLで埋めておけばそんな感じになる。
┌──────────────────────────────────────┐
│Dim 配列(1 To 30) As Variant                                                │
│For i = LBound(配列) To UBound(配列)                                        │
│    配列(i) = Null                                                          │
│Next i                                                                      │
├──────────────────────────────────────┤
│MsgBox WorksheetFunction.CountIfs( _                                        │
│    配列(1), 配列(2), 配列(3), 配列(4), 配列(5), _                          │
│    配列(6), 配列(7), 配列(8), 配列(9), 配列(10), _                         │
│    配列(11), 配列(12), 配列(13), 配列(14), 配列(15), _                     │
│    配列(16), 配列(17), 配列(18), 配列(19), 配列(20), _                     │
│    配列(21), 配列(22), 配列(23), 配列(24), 配列(25), _                     │
│    配列(26), 配列(27), 配列(28), 配列(29), 配列(30) _                      │
│)                                                                           │
└──────────────────────────────────────┘

もっといい方法がありそうだが。
分類:ExcelVBA
ExcelVBA/WorksheetFunctionに配列引数(1)
2020年08月24日
引数が可変の場合、構成要素が数値や文字列なら、配列で指定ができる。
┌──────────────────────────────────────┐
│Dim 配列 As Variant                                                         │
│配列 = Array(1, 2, 3)                                                       │
│MsgBox WorksheetFunction.Min(配列)     '.Min(1, 2, 3)と同じ    →1          │
│MsgBox WorksheetFunction.Average(配列) '.Average(1, 2, 3)と同じ→2          │
│MsgBox WorksheetFunction.Max(配列)     '.Max(1, 2, 3)と同じ    →3          │
└──────────────────────────────────────┘
分類:ExcelVBA
ExcelVBA/スカラ配列ArrayList
2020年08月22日
ExcelVBAでも同じだった。
┌──────────────────────────────────────┐
│Dim 配列 As Object                                                          │
│Set 配列 = CreateObject("System.Collections.ArrayList")                     │
│Call 配列.Add("東京")                                                       │
│Call 配列.Add("大阪")                                                       │
│Call 配列.Add("名古屋")                                                     │
│MsgBox Join(配列.ToArray(), "、")                                           │
└──────────────────────────────────────┘
ReDimより全然便利。
でも、.Net Framework 3.5がないと使えない。採用は難しいかな。
分類:ExcelVBA
ExcelVBA/X座標を列名に変換するいろいろ
2020年08月19日
┌──────────────────────────────────────┐
│Dim 出力 As String, 入力 As Long                                            │
│出力 = ""                                                                   │
│Do While 入力 > 0                                                           │
│    出力 = Chr(((入力 - 1) Mod 26) + 65) & 出力                             │
│    入力 = Int((入力 - 1) / 26)                                             │
│Loop                                                                        │
└──────────────────────────────────────┘
分類:ExcelVBA
ExcelVBA/列幅自動調整とオートフィルタ
2020年08月05日
列幅の自動調整は以下のような感じで行う。
┌──────────────────────────────────────┐
│With シート                                                                 │
│    .Columns.AutoFit                                                        │
│End With                                                                    │
└──────────────────────────────────────┘
ところが、あるシートで実行する度に幅が広がったり狭まったりする現象に出くわした。

┌──────────────────────────────────────┐
│With シート                                                                 │
│    .Columns.AutoFit                                                        │
│    .Rows("1:1").AutoFilter                                                 │
│End With                                                                    │
└──────────────────────────────────────┘
原因はオートフィルタだった。
オートフィルタがONの状態で列幅自動調整をすると広がり、
オートフィルタがOFFの状態で列幅自動調整をすると狭まっていたのだ。
しかも、「.AutoFilter」はトグル的なメソッドなので、これと組み合わさって
処理を実行する度に幅が広がったり狭まったりする現象を引き起こしていたのだ。

┌──────────────────────────────────────┐
│With シート                                                                 │
│    If .AutoFilterMode Then  '■処理追加                                    │
│        .Cells.AutoFilter    '■処理追加                                    │
│    End If                   '■処理追加                                    │
│    .Columns.AutoFit                                                        │
│    .Rows("1:1").AutoFilter                                                 │
│End With                                                                    │
└──────────────────────────────────────┘
ということで、いかなる場合もオートフィルタがOFFの状態で
列幅自動調整をするように処置。(これで狭い方オンリーになる)
分類:ExcelVBA
ExcelVBA/QRコード全削除
2020年05月15日
ひとまず図形として削除できる。
┌──────────────────────────────────────┐
│Dim 図形 As OLEObject                                                       │
│For Each 図形 In ActiveSheet.OLEObjects                                     │
│    図形.Delete                                                             │
│Next 図形                                                                   │
└──────────────────────────────────────┘
分類:ExcelVBA
前へ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 … 27 次へ