アプリ版:「スタンプのみでお礼する」機能のリリースについて

お世話になります。
参照先で選択したファイルをコピーし、出力先に【完成版】データ.xlsxと名前を付けて保存したいのですが、調べながらコードを書いてみたのですが、つぎはぎになってしまい色々考えているのですが、どうしてもうまくいきません。大変恐縮ですが以下についてご教示いただけないでしょうか。


①各ボタンにマクロを設定しましたが、wsの宣言は以下の形でいいのでしょうか?
②出力先のフォルダ選択ボタンのコードで、キャンセルボタンが押された場合の処理を書くとエラーになるのですが理由がわからないのですが、ファイルを選択した場合とフォルダの選択だと、制御がことなるのでしょうか?
③出力先の値をB9に表示させたいのですがなぜかL1セルにパスが表示されてしまいます。
④最後のファイルをコピーして名前をつけて保存の記述ですが、上2つのプロシージャ―で使った変数を引き継ぐことができず、どのように記述すればよいかご教示いただけないでしょうか。

Option Explicit
Dim ws As Worksheet

Sub ファイルを選択() ’「ファイルを選択」ボタン
Dim fType, prompt As String
Dim fPath As Variant

Set ws = Worksheets("sheet1")
fType = "Excelファイル(*.xlsx),*xlsx"
prompt = "ファイルを選択してください"
fPath = Application.GetOpenFilename(fType, , prompt)

If fPath = False Then 'ダイアログでキャンセルボタンが押された場合は処理を終了
End
End If
ws.Cells(5, 2).Value = fPath 'B5セルにパスを表示させる
End Sub


Sub 出力先() '「フォルダー選択」ボタン
Dim 出力先 As String
Dim ws2 As Worksheet

Set ws = Worksheets("sheet1")
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = True Then
出力先 = .SelectedItems(1)
End If
End With
If 出力先 = False Then 'ダイアログでキャンセルボタンが押された場合は処理を終了
End
End If

ws.Cells(9.2).Value = 出力先 'B9に出力先フォルダを表示
End Sub

Sub データ処理
 filecopysource:=Range("B5").value,destination:=Range("B9").value & "【完成版】データ.xlsx"
End sub

「VBA 参照先で選んだファイルをコピーし」の質問画像

A 回答 (8件)

#1


>最後の「変数を使用する時には変数の値を確認するロジック」とは、どういったものでしょうか。

#3様が回答しているような状態(同名ファイルの上書き)を防ぐとか

例えば
メイン処理の前に(おわびも含め 少しコード足し、変数を変えました)

'出力先フルパス作成
newfllPath = outputPath & "\" & Format(Date, "yy_mm_dd") & "【完成版】データ.xlsx"
'同名ファイルチェック
If Dir(newfllPath) <> "" Then
'分岐処理UI
rc = MsgBox("同名ファイルが存在します 処理を行いますか?", vbYesNo + vbQuestion, "確認")
If rc = vbNo Then MsgBox "出力処理を中止します": Exit Sub
End If

’メイン処理
FileCopy Source:=fPath, Destination:=newfllPath
'情報出力



1つのプロシージャにした方が、簡単・・・かと

中間の
End Sub
Sub 出力先() '「フォルダー選択」ボタン
End Sub
Sub データ処理
を削除
変数を整理
キャンセル時、実行時の分岐を確認

取得、加工、メイン、結果出力 のような流れで上から処理を組み直す
    • good
    • 1
この回答へのお礼

お礼コメント内の質問に対しご回答いただき誠にありがとうございます。なるほど、そういった内容なんですね。一番このあたりがまだよくわからない部分で、勉強が必要です。アドバイスを元に考えてみたいと思います。またコード記載いただいてありがとうございました!!大変参考になります。

お礼日時:2022/05/14 11:33

本件の回答でなくてすみません。


あなたが質問したこちらについて、回答しようとしたところ、
既に締め切られていて回答できませんでした。
https://oshiete.goo.ne.jp/qa/12945379.html
もし、この質問がまだ未解決なら、回答の用意がありますので、
再度、質問を起こしていただければ、回答いたします。
(いくつか不明点がありますので、まずはその確認からになりますが・・・)
    • good
    • 0
この回答へのお礼

ご連絡ありがとうございます。以下質問を投稿しました。
https://oshiete.goo.ne.jp/qa/12947180.html
こちらにてご回答いただけると大変嬉しく思います。

本質問は、そのデータ取り込みと出力に関する内容です。
自分で考えたのは、1つ目のブックを複製し、それにデータを追記していく方法で、まずそれに似た作業を行いたく、本質問をさせていただきました。
どうぞよろしくお願いいたします。

お礼日時:2022/05/14 12:07

No3です。



>ひとつのコードとして記載することはできるのでしょうか?
基本的に、コードは記載順に処理されますので(例外はありますが)、一つのプロシージャにまとめてしまうことで可能になります。

あるいは、せっかく機能ごとに分けて作成してあるので、全体を通して処理するプロシージャを別に作成しても良いです。
 Sub Main()
  Call ファイルを選択
  Call 出力先
  Call データ処理
 End Sub
としておいて、こちらを実行すれば、それぞれのプロシージャを順に(連続して)実行することができます。

ただし、ご提示の内容の場合、いきなりダイアログが2回連続して表示されてしまうことになるので、ご自身が使う場合には(内容が分かっているので)問題はありませんけれど、他の人が使う場合には「何を選択すれば良いのかわからない」事態になりかねませんね。
ですので、そのような場合には、なんらかの工夫が必要かもしれません。

ダイアログのタイトルに指定の文字列を表示することが可能なので、これを利用する方法はありそうですが、必ずそこを見てくれるとは限らないでしょうから、それで充分とは言えないように思われます。
メッセージボックス等で入力内容を知らせたり、ユーザーフォームをモードレスで表示して入力内容を表示しておくなどで、わかるようにしておく方が良いかもしれません。

あるいは、連続して処理する場合には、間違えて入力してしまった際を考慮して、戻れるようにしておいたり、確認をすることも必要になるのかも知れませんね。
(人間は、間違えるものですので・・)
どのようなUIにしておくのが一番良いのかは、実際の状況をご存じの質問者様にしかわかりませんので・・
    • good
    • 1
この回答へのお礼

補足での質問に対してのご回答、誠にありがとうございます。なるほど、callを用いて呼び出す形にすればよいのですね。その際に出てくる、ユーザー視点でのわかりづらさを回避する方法のご提案も大変勉強になります。本番ツールは他に動きがさらに加わるのですが、ひとつひとつテストして作っていきたいと思います。ご記載いただくことひとつひとつが本当に勉強になります。どうもありがとうございました。

お礼日時:2022/05/14 11:26

#4締め切りにならず良かった・・・



せっかく確認して頂きましたが、間違いの上塗りをしてしまいました
大変恥ずかしいのですが、そのままには私的に出来ませんので
連続投稿いたします

一方 問題の・・・
説明(意味内容が違う)

正しくは
一方 問題の Application.FileDialog(msoFileDialogFolderPicker)
でキャンセルボタンを押すと
If .Show = True Thenにより
= .SelectedItems(1)は実行されず
変数の初期値 "" Emptyが返ります
変数がStringの場合は "" が返り If 出力先 = "" Thenで良いです
As Variantでも If 出力先 = "" Thenで良いです

補:もし.SelectedItems(1)を参照した場合
.SelectedItems(1)はキャンセルの場合、無いので エラー#5
呼び出し又は引数不正のエラーが返ります

結果が同様でも内容が違うので重ねてお詫びします
    • good
    • 1
この回答へのお礼

ご回答誠にありがとうございます。If.show~の部分はネットで拾ったもので、正直何をしているのか、なんのために必要なのか?がよくわかりません。
そのため、ご回答いただいた内容を私自身がよく理解することができず、申し訳ございません。

お礼日時:2022/05/14 11:28

#1の回答をした者です


誤りな情報を記しましたので訂正いたします
② 
If 出力先 = False Then 型が違います
Dim 出力先 As String (Variantでないので)
〇 If 出力先 = "" Then
VariantならfPathと同じでOK
これは誤りです

正しくは
If 出力先 = False Then 型が違います
〇 If 出力先 = "" Then

Application.GetOpenFilenameのキャンセルボタンを押すと
False か返ります(As Boolean)
受ける変数がStringの場合は "False"の文字列が返ります
従って
そのまま 
Dim fPath As Variant で If fPath = False Then

Dim fPath As String とした場合は If fPath = "False" Then


一方 問題の Application.FileDialog(msoFileDialogFolderPicker)
でキャンセルボタンを押すとEmptyが返ります
受ける変数がStringの場合は "" が返り If 出力先 = "" Thenで良いです
As Variantで合っても Variant/String となり If 出力先 = "" Thenで良いです

何か分かり難くなってしまいましたが VariantならfPathと同じでOKは
間違えなので訂正いたします。すみません
    • good
    • 1
この回答へのお礼

ありがとうございます!先ほどVariantに書き換えることで、正常に動きましたが、教えて頂いた通り、Stringで""thenでも問題なく動きました。ローカルウインドウで値も確認しました!大変勉強になりました。

お礼日時:2022/05/13 23:15

こんばんは



コードだけを見せられても、本当は何をしたいのかがよくわからないのですが・・・

①wsの宣言は以下の形でいいのでしょうか?
別に問題はありませんけれど、シートモジュールに宣言する場合は共通変数として使用する場合です。
一方で、ご提示のコードではそのような使い方をしている様には見受けられませんので、意味が分からない間は、各プロシージャ内で宣言しておいた方がよろしいかと。
例えば、出力先()の中では ws2 を宣言していますが、使っていなかったりと・・
(=問題にはなりませんけれど、整理できていないように感じます)

②エラーになるのですが理由がわからないのですが、~~
どこでエラーが発生しているのかを確認してください。
ご提示の場合は、変数宣言が文字列になっている変数に対して真偽値であるかを判定しようとしているので、おかしなことになっています。
尚、プロシージャ名と同じ変数名を使用するのも、混乱の元なのでやめた方が良いでしょう。

>ファイルを選択した場合とフォルダの選択だと、制御がことなるのでしょうか?
ダイアログの扱い方が異なっていますよね?
ご自分のその前のコードをよくご確認ください。
異なる方法で扱っているので、異なる結果になります。

③出力先の値をB9に表示させたいのですがなぜかL1セルにパスが表示されてしまいます
タイプミスでは?
>ws.Cells(9.2).Value
は、引数がひとつしかないので、全体のセルの中から(9.2を整数化して)9番目のセルの意味と解釈されます。
ですので、L1ではなくI1セルになっていませんか?

④最後のファイルをコピーして名前をつけて保存の記述ですが、上2つのプロシージャ―で使った変数を引き継ぐことができず、どのように記述すればよいかご教示いただけないでしょうか。

想像するところ全体で一連の処理のように見受けられるので、バラバラに記述する意図がわかりかねますが・・
プロシージャ間で変数の値を引き継ぎたければ、前述の共通変数を用いるか、シート上のセルなどを利用することになります。
(共通変数はエクセルをクローズすると消えますが、セル値であればそのまま保存できるという違いがあります)
ご提示のコードではセルに記述しているので、そのセルの値を読み込めば引き継ぐことができると思います。
ご提示のコードも、同様のことを意図しているように受け取れますが?

ちなみに、ご提示のコードだと
>filecopysource
というメソッドとして解釈されるので、エラーになると思います。
また、フォルダパスとファイル名を直接連結しているようですけれど、その結果がどうなるかは、事前に確認しておいた方がよさそうに思います。

書き込み先のチェック(既存で同名のファイルがないか)などを行っていないので、それで問題がないのかも気になるところではありますが・・・

※ 以上、ざっと見て、とりあえず気づいた点のみですけれど・・
    • good
    • 1
この回答へのお礼

ありがとうございます。書かれていることなんとなくはわかるのですが勉強が足りず読み解くことができません。申し訳ございません。一点伺いたいのですが、バラバラに記述しないで、ひとつにしたいのですが、ボタンそれぞれに動作を持たせているので、このような書き方しか思いつきません。ひとつのコードとして記載することはできるのでしょうか?

お礼日時:2022/05/13 23:02

見落としました


filecopysource:=Range("B5").value,destination:=Range("B9").value & "【完成版】データ.xlsx"
\が抜けていますね(たぶん)
〇 & "\【完成版】データ.xlsx"
    • good
    • 1

こんばんは


① 
良いと思いますよ・・シート名がSheet1ならば
② 
If 出力先 = False Then 型が違います
Dim 出力先 As String (Variantでないので)
〇 If 出力先 = "" Then
VariantならfPathと同じでOK

タイプミス? × ws.Cells(9.2) 〇 ws.Cells(9, 2)


モジュールレベル変数で宣言します
(Dim ws As Worksheet)で既に行っている方法

正しプロシージャ名と同じ変数名は使えません
Dim 出力先 As String
Sub 出力先()

また、その変数を使用する時には変数の値を確認するロジックを
出来れば追加しましょう(思わぬエラーに躓く可能性があります)

filecopysource:=Range("B5").value,destination:=Range("B9").value & "【完成版】データ.xlsx"
半角スペースは重要です

もう少しで完成と存じますので、コードは割愛します
    • good
    • 1
この回答へのお礼

ご丁寧に教えて頂き、ありがとうございました。ご指摘のように直したところすべて正しく動作しました。1点うかがいたいのですが、最後の「変数を使用する時には変数の値を確認するロジック」とは、どういったものでしょうか。
debug.printが思い浮かびましたが、この方法だと自分しか確認できないので違うのかなと思ったのですが・・。よろしければ教えていただけますと幸いです。どうぞよろしくお願いいたします。

お礼日時:2022/05/13 23:06

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!