自分用のメモなので、形は整ってないです。
Cells(1, 1)は必ずしもA1セルを指すとは限らない。Range指定がある場合は、Cells(1, 1)はRangeの左上セルを指す
Sub qqq()
Range(Cells(1, 1), Cells(10, 1)).Value = "AAA" 'A列
Range(Cells(1, 2), Cells(10, 2)).Value = "BBB" 'B列
Debug.Print Range("B1:B10").Cells(1, 1).Value
'これは "BBB" になる。Range指定がある場合は、Cells(1, 1)はRangeの左上セルを指す
'通常はA1セルになるが、Range指定がある場合は注意
'Rangeオブジェクトに対して、Cells(*,*)でセル取得すると、正しいアドレスにならないかも?
Debug.Print Range(Cells(1, 1), Cells(10, 3)).Cells(1, 1).Address
Debug.Print Range(Cells(1, 1), Cells(10, 3)).Cells(3, 2).Address
'Rangeに対しては以下のようにしたほうが確実な気がする
Debug.Print Range(Cells(1, 1), Cells(10, 3))(1, 1).Address
Debug.Print Range(Cells(1, 1), Cells(10, 3))(3, 2).Address
Debug.Print Cells.[_Default](1, 1)
'ちなみに、これでRangeオブジェクトのデフォルトプロパティ(Value)を取得できる
'Valueは省略しても取得できるが、正確には[_Default]を取得している
End Sub
シートをコピーする場合の注意点 Set wsX = ActiveSheet というコードは、間違いが起きやすいので使わないように 非表示のシートも注意
Sub aaa()
Dim wsX As Worksheet
Worksheets("シート1").Copy After:=Worksheets(Worksheets.Count)
'「シート1」をコピーし、末尾に移動する
Set wsX = Worksheets(Worksheets.Count)
'コピー直後に末尾のシートをSetすれば、ほぼ間違いなくコピーしたシートが対象になるはず
wsX.name = "コピーしたシート"
'※ Set wsX = ActiveSheet というコードは、間違いが起きやすいので使わないように
'***** 非表示のシートについて **************
'Worksheets("隠しシート").Copy 非表示のシートの場合、このコードはエラーになる
Worksheets("隠しシート").Visible = xlSheetVeryHidden 'VBAでしか再表示できないように非表示にする
'Worksheets("隠しシート").Visible = xlSheetHidden ' これは普通に非表示
If Worksheets("隠しシート").Visible = xlSheetHidden Or _
Worksheets("隠しシート").Visible = xlSheetVeryHidden Then
'非表示シート、またはVBAでしか再表示できないように非表示になっている場合
Worksheets("隠しシート").Visible = xlSheetVisible
End If
Worksheets("隠しシート").Copy After:=Worksheets(Worksheets.Count)
Set wsX = Worksheets(Worksheets.Count)
wsX.name = "コピーした隠しシート"
'ここまでやれば安全だろうか
End Sub
VBAの関数とワークシート関数では、同名の関数でも処理が違うことがある(Roundが有名) ワークシート関数にあわせるのが無難か
Debug.Print Application.WorksheetFunction.Round(2.5, 0) '3 になる
Debug.Print Round(2.5, 0) '2 になる
'ワークシート関数ROUNDは、通常の四捨五入処理をする
'VBA関数ROUNDは、銀行型の丸め処理をするので、整数部1桁の数値により四捨五入の仕方が変わる
Debug.Print "----------------"
Debug.Print Application.WorksheetFunction.Round(1.5, 0) '2 になる
Debug.Print Round(1.5, 0) '2 になる
オブジェクト型の変数を宣言する場合は、Newを使わないようにするべき。バグの原因になる
Sub aaa()
Dim col1 As Collection
Set col1 = New Collection
col1.Add "AAA"
Set col1 = Nothing 'ここでNothingにする
On Error Resume Next
col1.Add "BBB" 'このコードはエラーになる
If Err.Number <> 0 Then MsgBox "エラー"
Stop 'col1の内容はNothing
On Error GoTo 0
Dim col2 As New Collection 'Newで宣言
col2.Add "AAA"
Set col2 = Nothing 'ここでNothingにする
On Error Resume Next
col2.Add "BBB" 'このコードはエラーにならない
If Err.Number <> 0 Then MsgBox "エラー"
Stop 'col2の内容は、"BBB" だけが入っている
'オブジェクト化多の変数をNewで宣言した場合、インスタンスが生成されるのは宣言時ではなく、
'変数が使用される時になるらしい。Newで宣言するのはバグの原因になる
End Sub
コントロール(リストボックス等)の、ValueとTextの違い ValueはNullを取り得る
1セルだけの範囲をVariant型に入れて配列にした場合、配列にはならない。さらにその1セルが空白だと、Empty値になるらしい。1セルだけも、空白でなければEmpty値にならにない。複数のセル範囲だと、空白セルだけでもEmptyにならないみたい
Sub kkk()
'1セルだけの範囲をVariant型に格納した場合、配列にならない
'その1セルが空白だと、Empty値になるらしい
'1セルだけも、空白でなければEmpty値にならにない
Dim var1 As Variant
Cells(1, 1).Value = ""
var1 = Range(Cells(1, 1), Cells(1, 1)).Value '1セルのみの範囲で、そのセルが空白
Debug.Print VarType(var1) '0 Empty値
Cells(1, 1).Value = 500
var1 = Range(Cells(1, 1), Cells(1, 1)).Value '1セルのみの範囲で、そのセルが空白
Debug.Print VarType(var1) '5 Doubleの数値
'配列ではないので、以下のコードはエラーになることに注意
'Debug.Print UBound(var1, 1)
'複数のセル範囲だと、空白セルだけでもEmptyにならないみたい
Dim var2 As Variant
Cells(1, 1).Value = ""
Cells(2, 1).Value = ""
var2 = Range(Cells(1, 1), Cells(2, 1)).Value
Debug.Print VarType(var2) '8204
'セル範囲をVariantに格納するときは、VarTypeで判定するといいかも
End Sub
セルの書式を通貨型にすると、VBA内では、小数部は4桁目までの四捨五入丸めになってしまうらしい
0.123456 → 0.1235 になる セルの表示は4桁目以降も出ているし、値も同じだが、VBA内での扱いが違うか
Sub nnnn()
Cells.Clear
Cells(1, 1).NumberFormatLocal = "\#,##0.000000;\-#,##0.000000"
'セルの書式を通貨型にする 小数部分は6桁
Cells(1, 1).Value = 0.123456789
Debug.Print Cells(1, 1).Value '0.1235
'セルの書式を通貨型にすると、小数部は4桁目までの四捨五入丸めになってしまうらしい
Debug.Print Cells(1, 1).Value = 0.1235 'True
Cells(1, 1).Value = 0.1
Debug.Print Cells(1, 1).Value '0.1
Cells(1, 1).Value = 0.12
Debug.Print Cells(1, 1).Value '0.12
Cells(1, 1).Value = 0.123
Debug.Print Cells(1, 1).Value '0.123
Cells(1, 1).Value = 0.1234
Debug.Print Cells(1, 1).Value '0.1234
Cells(1, 1).Value = 0.12345
Debug.Print Cells(1, 1).Value '0.1235
Debug.Print VarType(Cells(1, 1)) '6 通貨型 Doubleとは判定されないらしい。これで判断すべきか
End Sub
vbCrLf、vbLf、vbCrを互いに置換する場合は注意が必要。LFをCRLFに置換すると、CRLFはCRCRLFになってしまう
Sub kkkk()
Dim str1 As String
str1 = "aa" & vbCrLf & "bb" & vbLf
str1 = Replace(str1, vbLf, vbCrLf) 'LFをCRLFに置換
Debug.Print str1 = "aa" & vbCrLf & "bb" & vbCrLf 'False
Debug.Print str1 = "aa" & vbCr & vbCrLf & "bb" & vbCrLf 'True
'どうしてこうなるかというと、LFをCRLFに置換すると、CRLFはCRCRLFになってしまうかららしい
'CRLF LF CRが混在する文字列をCRLFで統一するには、以下のように全てLFにしてからCRLFにすると分かりやすいかも
str1 = "aa" & vbCrLf & "bb" & vbLf & "cc" & vbCr & "dd" & vbCrLf
str1 = Replace(str1, vbCrLf, vbLf)
str1 = Replace(str1, vbCr, vbLf)
str1 = Replace(str1, vbLf, vbCrLf)
Debug.Print str1 = "aa" & vbCrLf & "bb" & vbCrLf & "cc" & vbCrLf & "dd" & vbCrLf 'True
End Sub
セル内の一部だけのフォント設定(フォント色等)を変更している場合、セルのフォント設定を取得するとNull値がリターンされるので注意 フォント色・太字・フォントサイズ・フォント名・下線付き・斜め字体などは全てNullになってしまう
Sub vvv()
' Cells(1, 1)のテキストは、一部だけを赤のフォント色にしてある
Debug.Print Cells(1, 1).Font.Color '結果はNull
Debug.Print VarType(Cells(1, 1).Font.Color) '1 Null値
' Cells(2, 1)のテキストは、一部だけを「メイリオ」フォントにしてある
Debug.Print Cells(2, 1).Font.name '結果はNull
Debug.Print VarType(Cells(2, 1).Font.name) '1 Null値
' Cells(3, 1)のテキストは、一部だけを太字フォントにしてある
Debug.Print Cells(3, 1).Font.Bold '結果はNull
Debug.Print VarType(Cells(3, 1).Font.Bold) '1 Null値
' Cells(4, 1)のテキストは、一部だけを20サイズのフォントにしてある
Debug.Print Cells(4, 1).Font.Size '結果はNull
Debug.Print VarType(Cells(4, 1).Font.Size) '1 Null値
' Cells(5, 1)のテキストは、一部だけを下線付きにしてある
Debug.Print Cells(5, 1).Font.Underline '結果はNull
Debug.Print VarType(Cells(5, 1).Font.Underline) '1 Null値
' Cells(6, 1)のテキストは、一部だけを斜め字体のフォントにしてある
Debug.Print Cells(6, 1).Font.Italic '結果はNull
Debug.Print VarType(Cells(6, 1).Font.Italic) '1 Null値
'セル内の一部のテキストだけが変更されている場合、フォントの各種設定を取得すると全てNullが返されることになるようだ
End Sub