LoginSignup
1
0

More than 1 year has passed since last update.

ExcelVBA  注意すべきこと

Last updated at Posted at 2022-09-03

自分用のメモなので、形は整ってないです。

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
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0