[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『別ブックにシートコピー』(りおりお)
ダイアログで指定した別ブックにシート名:データをコピーしたいのですが下記マクロで「インデックスが有効範囲にありません」とエラーになりできません。解決方法を教えてください。
Sub 別ブックの先頭にコピーする()
Dim FileName As Variant FileName = Application.GetOpenFilename(FileFilter:="Excelファイル,*.xls*") If FileName = False Then Exit Sub End If ThisWorkbook.Worksheets("データ").Copy _ Before:=Workbooks(FileName).Worksheets(1) End Sub
< 使用 Excel:Microsoft365、使用 OS:Windows11 >
ブックを開いていないからだと思うよ ただ、これだと読み取り専用で開いていた場合とか、すでにブックを開いていた場合のエラー処理がないから、いろんな人が使う場合はもう少し工夫必要かも Sub 別ブックの先頭にコピーする() Dim FileName As Variant Dim WB As Workbook '★ FileName = Application.GetOpenFilename(FileFilter:="Excelファイル,*.xls*") If FileName = False Then Exit Sub End If Set WB = Workbooks.Open(FileName) '★ ThisWorkbook.Worksheets("データ").Copy _ Before:=WB.Worksheets(1) '★ End Sub (稲葉) 2023/01/05(木) 15:22:39
その勢いは好きですが、若干不安覚えるお礼いただいたので補足を・・・
WBっていう箱の中に、開いたワークブックを入れておくイメージです。 「箱に入れる」という命令がSetなので、「SetしてOpen」ではなく、「OpenしてSet」のほうがニュアンスとして近いかも・・・
最初の頃ってSetとかオブジェクトとか難しいですよね。 ブックとかシートの処理って、やりたい処理よりエラー処理のほうが長くなるので参考までにエラー出たときに見直してみてください。 Sub 別ブックの先頭にコピーする() Dim FileName As Variant Dim WB As Workbook '★ Dim コピーシート名 As String コピーシート名 = "データ"
'コピー先ブックの選択 FileName = Application.GetOpenFilename(FileFilter:="Excelファイル,*.xls*") If FileName = False Then MsgBox "ファイルが選択されなかったため、処理を中断します" Exit Sub End If
'指定したブックが開かれているかチェックし、開かれていなければ開く On Error Resume Next Set WB = Workbooks(FileName) On Error GoTo 0 If WB Is Nothing Then Set WB = Workbooks.Open(FileName) '★ End If
'読み取り専用かのチェック If WB.ReadOnly = True Then If MsgBox("ブックは読み取り専用です。処理を続けますか?", vbYesNo) <> vbYes Then MsgBox "処理を中断しました" Exit Sub End If End If
'開いたブックに同じシート名があるかチェック WB.Activate If Application.Evaluate("ISREF('" & コピーシート名 & "'!A1)") = True Then MsgBox "すでに同じシートがあります。処理を中断します" Exit Sub End If
'実際の処理 ThisWorkbook.Worksheets(コピーシート名).Copy _ Before:=WB.Worksheets(1) '★ MsgBox "処理が完了しました" End Sub (稲葉) 2023/01/05(木) 16:06:53
■1
少し誤解されていた部分があるとおもいますが、↓はブックを開く命令ではありません。
FileName = Application.GetOpenFilename(FileFilter:="Excelファイル,*.xls*")
上記では[FileName]にダイアログで選択したファイルのフルパス(文字列)が格納されるだけです。
よって、実際に操作対象にするのであれば、別途開く必要があります。
■2
おそらく、問題が発生した時点では指摘があるようにブックが開かれていなかったのだとおもいますが、ブックが開かれていたとしても↓だと問題があります。
〜〜 Before:=Workbooks(FileName).Worksheets(1)
すなわち「■1」で述べたように「FileName」にはフォルダを含めたフルパスが格納されていますから、例えば【C:\work】というフォルダにある【hoge.xls】というブックを指定したら↓のようになります。
〜Before:=Workbooks("C:\work\hoge.xls").Worksheets(1)
これを踏まえて↓を実行してみるとわかりますが、仮に対象のブックを事前に開くようにしていたとしてもエラーになります。
Sub 実験() Dim ファイルパス As String Dim WB As Workbook
ファイルパス = Application.GetOpenFilename(FileFilter:="Excelファイル,*.xls*") Workbooks.Open (ファイルパス) '←ここで開いても Set WB = Workbooks(ファイルパス) '←ここでフルパスをブック名にしているためエラー MsgBox WB.Name End Sub
つまり、「インデックスが有効範囲にありません」というエラーは、「そんな(C:\work\hoge.xlsという)名前のブックがないよ!」とエクセル君から言われていた状態だったということです。
■3
>Set して Open するのですね
既に理解できたかもしれませんが、問題点は冒頭に述べたように【挿入される側のブックの指定が正しくなかった】ことです。
したがって、変数に格納するというのは1つの方法という話であって
(1)対象のブックを開く処理を追加する (2)【フルパス】から【ブック(ファイル)名】をとりだして、ちゃんとブック名で指定する
という点を修正すれば、↓のように当初のコードでもちゃんと動作したでしょう。
Sub 研究用01() Dim FileName As Variant
FileName = Application.GetOpenFilename(FileFilter:="Excelファイル,*.xls*") If FileName = False Then Exit Sub Else '▼ブックを開く命令を追加 Workbooks.Open FileName
'▼Dir関数を使ってファイルパスからブック名を取り出すように修正 ThisWorkbook.Worksheets("データ").Copy Before:=Workbooks(Dir(FileName)).Worksheets(1) End If End Sub
■4
以下は完全に蛇足ですが、「Application.GetOpenFilename」で指定したブックが既に開いているかどうかは↓では確認できません。(理由の1つは■2のとおり)
FileName = Application.GetOpenFilename(FileFilter:="Excelファイル,*.xls*")
On Error Resume Next Set WB = Workbooks(FileName) '←ここでフルパスを指定しているためSetに失敗する On Error GoTo 0
If WB Is Nothing Then
そして、二つ目の理由が【ファイルパス】から【ファイル名】を取り出したとしても、同名のブックが開いているかどうかの確認しかできません。
(すでに開いているブックが、別フォルダの同名ブックである可能性があります)
なので、個人的はあれこれ悩むよりも↓のように、同名ブックが開いていれば閉じてからやり直させるというアプローチのほうがいいんじゃないかと思います。 (自分しか使わないならどちらでもよいでしょうが)
Sub 研究用02() Dim ファイルパス As String, ファイル名 As String Dim WB As Workbook
ファイルパス = Application.GetOpenFilename(FileFilter:="Excelファイル,*.xls*") ファイル名 = Split(ファイルパス, "\")(UBound(Split(ファイルパス, "\")))
Stop 'ブレークポイントの代わり
If ファイルパス = "" Then MsgBox "ブックが指定されませんでした" & vbLf & "処理を中止します" Exit Sub End If
On Error Resume Next Set WB = Workbooks(ファイル名) On Error GoTo 0
If Not WB Is Nothing Then MsgBox "既に【" & WB.Name & "】が開かれています。" & vbLf & "該当ブックを閉じてからやり直してください" Exit Sub End If
With Workbooks.Open(ファイルパス) ThisWorkbook.Worksheets("データ").Copy Before:=.Worksheets(1) '開いたブックの1番目のシートの前にコピー挿入しなさい .SaveAs .Path & "\【済】" & .Name '(ブックを)(同じフォルダに)別名で保存しなさい .Close False '(ブックを)閉じなさい End With End Sub
なお、読み取り専用でブックが開かれていたとしても別名であれば保存できますし、コピー挿入であればシート名が被ってもエクセル君が適宜処理してくれますますので、その辺はご自身で具合の良いように調整されるとよいとおもいます。
(もこな2) 2023/01/10(火) 12:26:27
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.