ExcelVBA　知識(雑多)

::: note warn
自分用のメモなので、形は整ってないです。
:::
### = や <> での文字列の一致・不一致の判定は、大文字/小文字、半角/全角、カタカナ/ひらがな、の区別をしている。StrComp関数が理想だが、簡易判定ならこれでいいかな
```
' = <>  は、大文字/小文字、半角/全角、カタカナ/ひらがな、を区別するらしい
Debug.Print "aaa" = "AAA"         'False
Debug.Print "aaa" <> "AAA"        'True
Debug.Print "あああ" = "アアア"   'False
Debug.Print "あああ" <> "アアア"  'True
Debug.Print "アアア" = "ｱｱｱ"      'False
Debug.Print "アアア" <> "ｱｱｱ"     'True
Debug.Print "aaa" = "aaa"         'True
Debug.Print "aaa" <> "aaa"        'False

'バイナリ/テキストモードを切り替えるなら、StrComp関数がいい
Debug.Print StrComp("aaa", "AAA", 0)  '1 等しくない  バイナリモード(デフォルトなので第3引数は省略可能)
Debug.Print StrComp("aaa", "AAA", 1)  '0 等しい  第3引数に1でテキストモード
Debug.Print StrComp("aaa", "AAA", vbBinaryCompare)  '1 等しくない  VBAの定数を指定すると分かりやすいかも
Debug.Print StrComp("aaa", "AAA", vbTextCompare)    '0 等しい
```
### $付き関数(Mid$ 等)のほうが、$なし関数よりも高速らしい。$なし関数の場合、戻り値をVariant型の変数に入れるとさらに遅いらしい
```
Sub aaa()

  Dim i As Long
  Dim var1 As Variant
  Dim str1 As String
  Dim startTime As Double
  Dim endTime As Double
  
  
  '$無し関数でVariant変数に格納
  startTime = Timer
  For i = 1 To 1000000
    var1 = Mid("abcde", 1, 3)
  Next i
  endTime = Timer
  Debug.Print "$無し関数でVariant変数に格納 :  " & (endTime - startTime)
  
  
  '$無し関数で文字列変数に格納
  startTime = Timer
  For i = 1 To 1000000
    str1 = Mid("abcde", 1, 3)
  Next i
  endTime = Timer
  Debug.Print "$無し関数で文字列変数に格納 :  " & (endTime - startTime)
  
  
 '$あり関数でVariant変数に格納
  startTime = Timer
  For i = 1 To 1000000
    var1 = Mid$("abcde", 1, 3)
  Next i
  endTime = Timer
  Debug.Print "$あり関数でVariant変数に格納 :  " & (endTime - startTime)
  
  
  '$あり関数で文字列変数に格納
  startTime = Timer
  For i = 1 To 1000000
    str1 = Mid$("abcde", 1, 3)
  Next i
  endTime = Timer
  Debug.Print "$あり関数で文字列変数に格納 :  " & (endTime - startTime)

End Sub


※結果は以下

$無し関数でVariant変数に格納 :  0.20703125
$無し関数で文字列変数に格納 :  0.171875
$あり関数でVariant変数に格納 :  0.09765625
$あり関数で文字列変数に格納 :  0.08984375

$ありと無しでは2倍ほどの差があるが、Variant変数と文字列変数はわずかな違いか
```
### ユニコードで使える特殊文字をVBAで使うには、ChrW関数を使うらしい
[リンク](https://rara-haha.com/2018/10/10/office-9/)

### トラブル時の解決法について雑記　　意味不明の動作不良の対処法なども
```
コード上は問題が無いはずなのに原因不明のエラーが出る場合は、参照設定の Microsoft Scripting Runtime にチェックを入れると解決するかも。
これでなぜ上手く行くのかは不明だが

他のExcelファイルを開く必要がある処理で、処理開始後に該当するブックを開くとする。
何らかのエラーで中断し、エラーメッセージをメッセージボックスで表示する場合、該当のブックを閉じる前に表示するとExcelが一時的にフリーズしたようになる。
これを防ぐには、該当のブックを閉じてからメッセージボックスを表示するといいようだ。
メッセージ格納用の変数を用意し、最終処理辺りで表示するとか
```
### 永久ループなどで完全に操作を受け付けなくなったVBAのコード実行を止める方法
```
「Ctrl+Pause/Breakを押す」、「ESCを連打する」、「ESCを押し続ける」などの方法がある

これでも駄目な場合は、Escキーを押しながらタスクバーのExcelやVBEの最小化ウィンドウを交互にクリックするといいみたい
```
### 改行コード(vbCrLf)は2文字扱い。最後にある改行を削除したいなら、2文字分削ればいい ただし、Chr(13)は1文字扱いなので注意。vbCrLfとChr(13)はどちらも改行だが、別物
```
  ****  改行コード(vbCrLf)は2文字扱い。最後にある改行を削除したいなら、2文字分削ればいい
ただし、Chr(13)は1文字扱いなので注意。vbCrLfとChr(13)はどちらも改行だが、別物  *********
  
  
    Dim str1 As String
    str1 = "AAA" & vbCrLf
    Debug.Print Len(str1)  ' 結果は「5」　vbCrLfは2文字扱い
        
    ' str1に改行が含まれることの確認
    Debug.Print "xxx"
    Debug.Print str1
    Debug.Print "xxx"
    
    str1 = Left(str1, (Len(str1) - 2))
    Debug.Print Len(str1)  ' 結果は「3」
    
    ' str1に改行が含まれていないことの確認
    Debug.Print "xxx"
    Debug.Print str1
    Debug.Print "xxx"
    
    
    ' ただし、Chr(13)は1文字扱いなので注意
    str1 = "AAA" & Chr(13)
    Debug.Print Len(str1)  ' 結果は「4」　Chr(13)は1文字扱い
    
    ' str1に改行が含まれることの確認
    Debug.Print "xxx"
    Debug.Print str1
    Debug.Print "xxx"
    
    
※セル内改行(alt + Enter)はvbLfになる
```
### 個人用マクロブックの保存ディレクトリ
```
C:\Users\(ユーザ名)\AppData\Roaming\Microsoft\Excel\XLStart
```
### プロジェクトにパスワードを設定する
```
VBE
ツール
VBAProjectのプロパティ
保護
プロジェクトのロック　　にチェックを入れる
```
### イミディエイトウインドゥで複数行のコードを実行する
```
「:」で複数行をつなげばOK

for i = 1 to 5: msgbox i: next i
```
### ADODB.Streamを使ってUTF-8・BOM無しのテキストファイルなどを作成する場合、ループ内でADODB.Streamを宣言 していると、2回目の処理時にエラーになるらしい(原因は不明) ループ内で複数回処理したい場合は、別のプロシージャを呼ぶ形にすればOKみたい
```
ADODB.Streamを使ってUTF-8・BOM無しのテキストファイルなどを作成する場合、ループ内でADODB.Streamを宣言していると、2回目の処理時にエラーになるらしい(原因は不明)
ループ内で複数回処理したい場合は、別のプロシージャを呼ぶ形にすればOKみたい



**********   エラーになる例    ****************************
Sub aaa()   ' UTF-8・BOM無しのテキストファイルを作成する(ループ内で全て処理するので、エラーが発生する)

    Dim xStream As New ADODB.Stream   ' ADOのストリーム
    Dim filePath As String
    Dim i As Long
    
    For i = 1 To 5
    
        filePath = "C:\Users\Benten\Desktop\まとめ総合(新)\仮サンプルテキスト\" & CStr(i) & ".txt"
        
        With xStream
        
            .Charset = "UTF-8"   ' 文字コードにUTF-8を指定
            ' ※※ 1回目の処理は問題ないが、2回目の処理ではここでエラーになってしまう。原因は不明
        
            .Open
        
            .WriteText "*************     ", 0
            ' テキストファイルに書込み。第二引数に1を指定すると、行の末尾に改行を入れる(0か省略で改行なし)
            
            ' BOMを削除するための処理
            Dim var1 As Variant
            .Position = 0
            .Type = adTypeBinary
            .Position = 3        ' BOMは先頭の3バイトのデータなので、それを削除するため
            var1 = .Read()       ' テキストの内容を再読込みして、それを3バイトずらして書き込む形
            .Position = 0
            .Write var1
            .SetEOS       ' BOMを削除した分、後ろに不要なデータが残るので、それを捨てる処理らしい
            
            .SaveToFile filePath, 2
            ' テキストファイルを保存する。引数に1を指定すると、同名ファイルがすでに存在する場合にエラーになる。2を指定すると、強制的に上書きする
            
            .Close  ' ストリームを閉じる
        
        End With
    
    Next i
    
End Sub



***********   エラーにならない例    ******************
Sub xxx()   ' UTF-8・BOM無しのテキストファイルを作成する(エラーにならない)

    
    Dim filePath As String
    Dim i As Long
    
    For i = 1 To 5
    
        filePath = "C:\Users\Benten\Desktop\まとめ総合(新)\仮サンプルテキスト\" & CStr(i) & ".txt"
        
        yyy (filePath)   ' Functionを呼ぶとエラーにならない
    
    Next i
    
End Sub


Function yyy(filePath As String)

    Dim xStream As New ADODB.Stream   ' ADOのストリーム

    With xStream
    
        .Charset = "UTF-8"   ' 文字コードにUTF-8を指定
        .Open
    
        .WriteText "*************     ", 0
        ' テキストファイルに書込み。第二引数に1を指定すると、行の末尾に改行を入れる(0か省略で改行なし)
        
        ' BOMを削除するための処理
        Dim var1 As Variant
        .Position = 0
        .Type = adTypeBinary
        .Position = 3        ' BOMは先頭の3バイトのデータなので、それを削除するため
        var1 = .Read()       ' テキストの内容を再読込みして、それを3バイトずらして書き込む形
        .Position = 0
        .Write var1
        .SetEOS       ' BOMを削除した分、後ろに不要なデータが残るので、それを捨てる処理らしい
        
        .SaveToFile filePath, 2
        ' テキストファイルを保存する。引数に1を指定すると、同名ファイルがすでに存在する場合にエラーになる。2を指定すると、強制的に上書きする
        
        .Close  ' ストリームを閉じる
    
    End With

End Function
```