質問するログイン新規登録

回答編集履歴

2

質問①の回答を追記

2018/09/29 12:05

投稿

退会済みユーザー
answer CHANGED
@@ -1,33 +1,43 @@
1
- 今回エラー原因は本来Range.PasteSpecialにしか存在しなパラメーPaste:=」をWorksheet.PasteSpecialに対て使用してるためで
1
+ > ①B集約管理ファイルを閉じていると開くですが、開ていたらッセジボックスは表示されずファイルが見つかりません。ファイル名保存場所が正しいか・・」と出ます。
2
2
 
3
+ とりあえず既に開いている場合に閉じる処理が無いのが問題ですね。
4
+
5
+ > ②ActiveSheet.PasteSpecialから進めなくなりました。
6
+
7
+ このエラーの原因は本来Range.PasteSpecialにしか存在しないパラメータ「Paste:=」をWorksheet.PasteSpecialに対して使用しているためですね。
8
+ どちらも同じ名称のメソッドですから、編集の過程で変えてしまったのでしょう。
9
+ 本件はコピー&ペーストが必要ない事例ですが、そこが質問のキモなのでそのまま残しています。
10
+
3
11
  しかし、色々とバグの原因が混ざっているので順番に指摘していきます。
4
12
 
5
13
  1.DisplayAlertsの位置が良くない。
6
-  この手のスイッチは必要最小限な範囲に使うように心がけたほうが良いです。
14
+ この手のスイッチは必要最小限な範囲に使うように心がけたほうが良いです。
7
- 例えば今回の場合はOpen時の様々な警告を無視するためだと思いますのでOpenだけに適用しています。
15
+ 例えば今回の場合はOpen時の様々な警告を無視するためだと思いますのでOpenだけに適用しています。
8
16
 
9
17
  2.Withの使い方がおかしい。
10
- WithステートメントはWorkbook、Worksheet、Rangeなどの変数の代替するためのものです。
18
+ WithステートメントはWorkbook、Worksheet、Rangeなどの変数の代替するためのものです。
11
- 利用するにはドットから初めなければなりませんが、提示されたコードではドットが付いていません。
19
+ 利用するにはドットから初めなければなりませんが、提示されたコードではドットが付いていません。
12
20
 
13
21
  3.極力ActiveSheetや省略Cellsは使わないように。
14
- Withが上手く使えていないのが原因で、「Cells(x, 2).Value = "*"」などはActiveSheetが省略されたものとして動作します。※プログラムを標準モジュールに書いた場合
22
+ Withが上手く使えていないのが原因で、「Cells(x, 2).Value = "*"」などはActiveSheetが省略されたものとして動作します。
23
+ ※プログラムを標準モジュールに書いた場合
15
- 従って、前に記載されている「Sheets("list").Activate」の影響でlistに対して処理することになり、意図したように動作しないはずです。
24
+ 従って、前に記載されている「Sheets("list").Activate」の影響でlistに対して処理することになり、意図したように動作しないはずです。
16
- 基本的にシートオブジェクトは指定するようにしてください。
25
+ 基本的にシートオブジェクトは指定するようにしてください。
17
-  たとえば、せっかく「Set wS = wB.Worksheets("list")」としているのに、すぐ下でActiveSheet.PasteSpecialとしていますよね。
18
-  同じオブジェクトを指すのですからwSを使いましょう。
19
-  今回の場合、Open直後に「Sheets("list").Activate」を実行しているので、この時点で変数に代入しておけばOKです。
20
26
 
21
- 4.インデントは手を抜かないこと。
22
- コードが読みづらなるということは、ミス発見ずらくなります。
27
+ たとえば、せっか「Set wS = wB.Worksheets("list")」してるの、すぐ下でActiveSheet.PasteSpecialとていますよね
23
- 面倒でもインデン(TAB)はきれに整えましょう。
28
+ 同じオブジェクを指すのですからwSを使いましょう。
29
+ 今回の場合、Open直後に「Sheets("list").Activate」を実行しているので、この時点で変数に代入しておけばOKです。
24
30
 
25
- 5.処理中のRange.Selectは使わないこと。
31
+ 4.インデントに手を抜かないこと。
26
-  下記のコードを見て分かしく書けばSelectは必要ありません
32
+ コードが読みづらくなといことはミスを発見ずらりま
27
-  もしアクティブブック・シートが切り替わった状態でSelectするとエラーの原因となりますので、どうしても使うときはブックやシートもActiveにしましょう。
28
-  本来マクロの最後、マクロ実行後に選択ていてほしい箇所をSelectするよな目的で使うのが正しい使い方です
33
+ 面倒でもインデント(TAB)きれい整えまう。
29
-  とはいえ、デバッグのときは処理工程でSelectしてくれたほうが、わかりやすくて便利なので一応コメントで残しています。
30
34
 
35
+ 5.処理中にRange.Selectは使わないこと。
36
+ 下記のコードを見て分かるように、正しく書けばSelectは必要ありません。
37
+ もしアクティブブック・シートが切り替わった状態でSelectするとエラーの原因となりますので、どうしても使うときはブックやシートもActiveにしましょう。
38
+ マクロの最後に、マクロ実行後に選択していてほしい箇所をSelectするような目的で使うのが正しい使い方です。
39
+ とはいえ、デバッグのときは処理工程でSelectしてくれたほうが、わかりやすくて便利なので一応コメントで残しています。
40
+
31
41
  できるだけ構造を変えないように修正したものがこちらです。
32
42
  一応ローカル環境でデバッグしたので動くと思いますが、ご自分でも良くデバッグしてください。
33
43
  ```VBA
@@ -38,13 +48,20 @@
38
48
 
39
49
  '①A入力用(転記元)の"D1"を参照し、B共有フォルダの「管理状況」にある
40
50
  '集約管理(転記先)のブックを開く
41
-
42
51
  myPath = "共有サーバー\管理状況\"
43
52
  fN = "【共有】集約管理" & Range("D1").Value & "月" & ".xlsx"
44
53
  'ローカルテスト用
45
54
  'myPath = "C:\tmp\"
46
55
  'fN = "管理用B.xlsx"
47
56
 
57
+ '既にfNを開いていたら閉じる
58
+ On Error Resume Next
59
+ Set wB = Workbooks(fN)
60
+ On Error GoTo 0
61
+ If Not wB Is Nothing Then
62
+ wB.Close False
63
+ End If
64
+
48
65
  Application.DisplayAlerts = False
49
66
  Set wB = Workbooks.Open(Filename:=myPath & fN, Notify:=False)
50
67
  Application.DisplayAlerts = True

1

文章の改定

2018/09/29 12:04

投稿

退会済みユーザー
answer CHANGED
@@ -1,3 +1,7 @@
1
+ 今回のエラーの原因は本来Range.PasteSpecialにしか存在しないパラメータ「Paste:=」をWorksheet.PasteSpecialに対して使用しているためですね。
2
+
3
+ しかし、色々とバグの原因が混ざっているので順番に指摘していきます。
4
+
1
5
  1.DisplayAlertsの位置が良くない。
2
6
   この手のスイッチは必要最小限な範囲に使うように心がけたほうが良いです。
3
7
  例えば今回の場合はOpen時の様々な警告を無視するためだと思いますのでOpenだけに適用しています。
@@ -10,16 +14,25 @@
10
14
  Withが上手く使えていないのが原因で、「Cells(x, 2).Value = "*"」などはActiveSheetが省略されたものとして動作します。※プログラムを標準モジュールに書いた場合
11
15
  従って、前に記載されている「Sheets("list").Activate」の影響でlistに対して処理することになり、意図したように動作しないはずです。
12
16
  基本的にシートオブジェクトは指定するようにしてください。
17
+  たとえば、せっかく「Set wS = wB.Worksheets("list")」としているのに、すぐ下でActiveSheet.PasteSpecialとしていますよね。
18
+  同じオブジェクトを指すのですからwSを使いましょう。
19
+  今回の場合、Open直後に「Sheets("list").Activate」を実行しているので、この時点で変数に代入しておけばOKです。
13
20
 
14
21
  4.インデントは手を抜かないこと。
15
22
  コードが読みづらくなるということは、ミスに発見しずらくなります。
16
23
  面倒でもインデント(TAB)はきれいに整えましょう。
17
24
 
25
+ 5.処理中のRange.Selectは使わないこと。
26
+  下記のコードを見て分かるように、正しく書けばSelectは必要ありません。
27
+  もしアクティブブック・シートが切り替わった状態でSelectするとエラーの原因となりますので、どうしても使うときはブックやシートもActiveにしましょう。
28
+  本来はマクロの最後に、マクロ実行後に選択していてほしい箇所をSelectするような目的で使うのが正しい使い方です。
29
+  とはいえ、デバッグのときは処理工程でSelectしてくれたほうが、わかりやすくて便利なので一応コメントで残しています。
30
+
18
31
  できるだけ構造を変えないように修正したものがこちらです。
19
32
  一応ローカル環境でデバッグしたので動くと思いますが、ご自分でも良くデバッグしてください。
20
33
  ```VBA
21
34
  Sub 転記()
22
- Dim wB1 As Workbook, wS1 As Worksheet
35
+ Dim wB As Workbook, wS As Worksheet
23
36
  Dim myPath As String, fN As String
24
37
  Dim x As Long
25
38
 
@@ -33,18 +46,18 @@
33
46
  'fN = "管理用B.xlsx"
34
47
 
35
48
  Application.DisplayAlerts = False
36
- Set wB1 = Workbooks.Open(Filename:=myPath & fN, Notify:=False)
49
+ Set wB = Workbooks.Open(Filename:=myPath & fN, Notify:=False)
37
50
  Application.DisplayAlerts = True
38
51
 
39
- If wB1.ReadOnly Then
52
+ If wB.ReadOnly Then
40
53
  MsgBox "他の人が作業中です。しばらく経ってから転記し直してください。"
41
- wB1.Close False
54
+ wB.Close False
42
55
  Exit Sub
43
56
  Else
44
- Set wS1 = wB1.Sheets("list")
57
+ Set wS = wB.Sheets("list")
45
- wB1.Activate '←普通は必要ないが、一応。
58
+ wB.Activate '←普通は必要ないが、一応。
46
- wS1.Activate
59
+ wS.Activate
47
- wS1.Range("A1") = Now
60
+ wS.Range("A1") = Now
48
61
  End If
49
62
 
50
63
  '②A入力用(転記元)のB列「*」の一つ下のC列からM列までをコピー
@@ -57,8 +70,10 @@
57
70
 
58
71
  '③共有フォルダの「管理状況」にある集約管理へ転記
59
72
  '----B列の最終ひとつ下を選択してから値として貼り付け
60
- With wS1.Cells(wS1.Rows.Count, 2).End(xlUp).Offset(1, 0)
73
+ With wS.Cells(wS.Rows.Count, 2).End(xlUp).Offset(1, 0)
74
+ 'wB.Activate '←Selectを使いたいときはコレも書いたほうが安全
75
+ 'wS.Select '←Selectをry
61
- .Select
76
+ '.Select '←省略可
62
77
  .PasteSpecial Paste:=xlPasteValues, _
63
78
  Operation:=xlNone, SkipBlanks:=False, Transpose:=False
64
79
  End With
@@ -68,14 +83,20 @@
68
83
  End With
69
84
  Application.CutCopyMode = False
70
85
 
86
+ 'データの末尾の次の行を選択
87
+ wB.Activate
88
+ wS.Select
89
+ wS.Cells(wS.Rows.Count, 2).End(xlUp).Offset(1, 0).Select
90
+
71
91
  Application.DisplayAlerts = False
72
- wB1.Save
92
+ wB.Save
73
93
  Application.DisplayAlerts = True
74
- wB1.Close False '----元のファイルを保存し閉じる
94
+ wB.Close False '----元のファイルを保存し閉じる
75
95
 
76
96
  MsgBox "転記しました。"
77
97
 
78
98
  Workbooks.Open Filename:=myPath & fN, ReadOnly:=True '----読み取り専用で開く
99
+
79
100
  End Sub
80
101
  ```
81
102
  ---