質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

Q&A

3回答

4772閲覧

AccessVBAから、「開いているExcelブック/シートを1つにまとめて保存」という処理を行いたい

NGK

総合スコア1

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

0グッド

0クリップ

投稿2021/01/10 03:27

編集2021/01/11 06:32

AccessVBAから、「開いているExcelブック/シートを1つにまとめて保存」という処理を行いたいです。

AccessVBAでExcelを操作する」を参考にしつつ以下のようなコードを書いてみたのですが、「実行時エラー9:インデックスが有効範囲にありません」のエラーが出てしまいます。エラー箇所は、「For i = 2 to ExApp.Workbooks(ExApp.Workbooks.Count)」です。

以下のコードをどのように改善すれば、エラーを解消し想定通りの動きをすることが出来るのでしょうか?

Sub AccessVBAでExcelブックを1つにまとめて保存() Dim ExApp As Object Set ExApp = CreateObject("Excel.Application") ExApp.Visible = True 'Excelの可視化 Dim DesktopPath As String, FilePath As String, WSH As Variant Set WSH = CreateObject("Wscript.Shell") DesktopPath = WSH.SpecialFolders("Desktop") FilePath = DesktopPath & "\保存名.xlsx" 'メイン処理 Dim i As Integer '開いているExcelブック数を数えて、2個目以降のブックのSheets(1)を1個目のブックに追加して閉じていく For i = 2 to ExApp.Workbooks(ExApp.Workbooks.Count) ExApp.Workbooks(i).Worksheets(1).copy _ Before:=ExApp.Workbooks(1).Sheets(1) 'ワークブック1にシートを追加してコピー ExApp.Workbooks(i).Close next i ExApp.Workbooks(1).SaveAs FileName:=FilePath ExApp.Workbooks(1).Close ExApp.Quit Set ExApp = Nothing Set WSH = Nothing MsgBox "完了しました。" End Sub

追記:2021/01/11 15:30
事前にエクセルを開いているコードはこちらです。
標準モジュールに書いた以下のコードを、フォームのクリック時イベントで複数回よびだしてExcelブックを開いています。

Function ExcelData(frm As Form) On Error GoTo Err_cmdExcel_Click 'DAOで抽出結果のクローンを作成 Dim xlsx As Object 'Excel.Applicationを代入するオブジェクト変数 Dim wkb As Object 'Excel.Wookbookを代入するオブジェクト変数 Dim rst As DAO.Recordset '現在のレコードセットを入れる変数 Dim idx As Long 'フィールド数変数 Dim j As Long ' 最終行取得用 Const xlUp As Integer = -4162 Set rst = Nothing 'データリストの初期化 Set rst = frm.RecordsetClone 'フォームのレコードセットのクローンを代入 'レコードが存在しない場合、処理を中止 If rst.BOF = True And rst.EOF = True Then MsgBox "出力出来るデータがありません。", vbOKOnly + vbExclamation, "出力不可" 'レコードセットを閉じる rst.Close: Set rst = Nothing Exit Function End If 'レコードが存在する場合、Excelに出力 'レコードセットの最初のデータにカーソルを移動 rst.MoveFirst 'Excelファイルを内部的に作成 Set xlsx = CreateObject("Excel.Application") '作成されたExcelファイルにワークブックを追加 Set wkb = xlsx.Workbooks.Add() '追加されたワークブックに、レコードセットのデータをコピー With wkb.Worksheets(1) For idx = 1 To rst.Fields.Count .cells(1, idx).Value = rst.Fields(idx - 1).Name Next .Range("A2").CopyFromRecordset Data:=rst 'レコードセットを閉じる rst.Close: Set rst = Nothing 'Excelデータを表示 xlsx.Visible = True xlsx.UserControl = True 'メモリに展開されたExcel用オブジェクト変数を開放 Set wkb = Nothing Set xlsx = Nothing Exit_cmdExcel_Click: Exit Function Err_cmdExcel_Click: MsgBox "エラーのため、Excelへ出力できません。" & vbCrLf & "一旦フォームを閉じ、再度トライしてください。" & vbCrLf & Err.Number & Err.Description, _ vbOKOnly + vbCritical, "Excel出力不可!" Resume Exit_cmdExcel_Click End Function

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/01/11 06:41

いまソースを読み込んでるんですが、実際のソースはきちんとインデントされてるんですよね?
NGK

2021/01/11 06:57

インデントとは、例えばIf構文を使った時に「If Else End」の文頭をそろえることで認識あっているでしょうか。その意味であっていれば、追記に記載したものはコピペでずれてしまいましたが、実際のソースではインデントをそろえているつもりです。(インデントがコードに影響することはあるのでしょうか、単に見やすくするためのものだと思っていたのですが)
退会済みユーザー

退会済みユーザー

2021/01/11 07:21

VBA ではインデントが実行に影響することはありませんが、可読性向上のためにインデントを揃えます。 で、お願いなのですが、CreateObject() → GetObject() に修正した最新ソースを提示していただけますか。 別途コメントしましたが、私の環境では umau さんのソースは正しく動作しましたので。
NGK

2021/01/11 07:30

なるほど、今回は回答者様方の可読性のためにきちんとインデントまで整えるべきでした。甘えてしまい申し訳ありません。 理由は分からないのですが、一度PCを再起動したところ、私のPC環境でもきちんとumau さんのソースがただしく動作してくれました。こちら参考に、いったん自分の希望している動作も実行できないか試してみます。その後、再度追記にソースコードをアップさせていただきます。
退会済みユーザー

退会済みユーザー

2021/01/11 07:44

よろしくお願いします。
hatena19

2021/01/11 09:20

ユーザーがエクセルを起動させて新規ブックを追加した場合は、umau さんのソースでも動作すると思いますが、Access VBAでCreateObject("Excel.Application")でエクセルを複数生成した場合はうまく動作しないと思います。その辺の切り分けを確認してください。
guest

回答3

0

vba

1 '開いているExcelブック数を数えて、2個目以降のブックのSheets(1)を1個目のブックに追加して閉じていく 2 For i = 2 to ExApp.Workbooks(ExApp.Workbooks.Count)

まず、上記の
For i = 2 to ExApp.Workbooks(ExApp.Workbooks.Count))
は下記に修正してください。
For i = 2 to ExApp.Workbooks.Count

ただし、提示のコードではワークブックを開くコードがないので、この時点では、ExApp.Workbooks.Count は 0 です。
ですので、Forループは実行されずには、次の、
ExApp.Workbooks(1).SaveAs FileName:=FilePath
で同様のエラーになりますね。

「開いているExcelブック/シートを1つにまとめて保存」の「開いている」というのは、どのように開いているのでしょうか。あるいは、開くのでしょうか。

ユーザーが既に手作業でいくつかのブックを開いておいて、それを対象とするでしょうか。
あるいは、特定のフォルダー内のブックを対象とするのでしょうか。
それとも、、、

その辺を明確に提示してください。

追記されたコードについて

CreateObject("Excel.Application")は新規のエクセルアプリケーションを生成します。
もし、これを繰り返す実行すると複数のエクセルアプリケーションが開いてしまいます。
(タスクマネージャーで確認してみてください。)
それぞれのWorkbooks.Add()で新規ブックを一つ開いていることになります。

下記の点を考慮してコーディングしてください。

  • Dim xlsx As Object の宣言は標準モジュールの冒頭で宣言する。モジュールの冒頭だとモジュールの実行後自動解放されるので以降参照できない。また、モジュール内で解放しないようにする。
  • CreateObject("Excel.Application")は最初の一回のみ実行する。複数のエクセルアプリケーションを開かないようにする。

上記を考慮すると、

vba

1Option Compare Database 2Option Explicit 3 4Dim xlsx As Object 'Excel.Applicationを代入するオブジェクト変数 5 6Function ExcelData(frm As Form) 7 On Error GoTo Err_cmdExcel_Click 8 'DAOで抽出結果のクローンを作成 9 Dim wkb As Object 'Excel.Wookbookを代入するオブジェクト変数 10 Dim rst As DAO.Recordset '現在のレコードセットを入れる変数 11 Dim idx As Long 'フィールド数変数 12 Dim j As Long ' 最終行取得用 13 Const xlUp As Integer = -4162 14 15'****中略***** 16 17 'Excelアプリケーションを生成(事前に生成されていない場合のみ) 18 If xlsx Is Nothing Then 19 Set xlsx = CreateObject("Excel.Application") 20 End If 21 22 'Excelアプリケーションにワークブックを追加 23 Set wkb = xlsx.Workbooks.Add() 24 25 '追加されたワークブックに、レコードセットのデータをコピー 26 With wkb.Worksheets(1) 27 28'****中略***** 29 30 'Excelデータを表示 31 xlsx.Visible = True 32 xlsx.UserControl = True 33 'メモリに展開されたExcel用オブジェクト変数は解放しない 34 'Set wkb = Nothing 35 'Set xlsx = Nothing 36 End With 37 38'****中略***** 39 40End Function 41 42Sub AccessVBAでExcelブックを1つにまとめて保存() 43 44 If xlsx Is Nothing Then 45 MsgBox "開いているブックはありません。" 46 Exit Sub 47 End If 48 49 Dim DesktopPath As String, FilePath As String, WSH As Variant 50 Set WSH = CreateObject("Wscript.Shell") 51 DesktopPath = WSH.SpecialFolders("Desktop") 52 FilePath = DesktopPath & "\保存名.xlsx" 53 54 'メイン処理 55 Dim i As Integer 56 57 '開いているExcelブック数を数えて、2個目以降のブックのSheets(1)を1個目のブックに追加して閉じていく 58 'ブックを閉じる場合は、最後のブックから閉じていかないとうまくいかない 59 For i = xlsx.Workbooks.Count To 2 Step 1 60 xlsx.Workbooks(i).Worksheets(1).Copy _ 61 Before:=xlsx.Workbooks(1).Sheets(1) 'ワークブック1にシートを追加してコピー 62 xlsx.Workbooks(i).Close 63 Next i 64 65 xlsx.Workbooks(1).SaveAs FileName:=FilePath 66 xlsx.Workbooks(1).Close 67 68 MsgBox "完了しました。" 69 70End Sub

生成したExcelアプリケーションは、適切なタイミングで、終了、解放しておく必要があります。
不必要になった時とか、Accessを閉じる前とか、・・・

vba

1xlsx.Quit 2Set xlsx = NoThing

「AccessVBAでExcelブックを1つにまとめて保存」プロシージャでブックを保存してますので、その最後でExcelアプリケーションを終了、解放してもいいかもです。

投稿2021/01/10 04:03

編集2021/01/11 16:21
hatena19

総合スコア33715

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NGK

2021/01/11 04:50

「開いているExcelブック/シートを1つにまとめて保存」の「開いている」というのは、どのように開いているのでしょうか。あるいは、開くのでしょうか。 >>>今回の処理を行う前に、別のAccessVBAコードで、いくつかのブックが開かれることになっています。そちらを対象に、「開いているExcelブック/シートを1つにまとめて保存」したいと考えています。 なので1つ以上のExcelブックは開かれている状態で、今回の処理を行いたいのですが、開いているExcelブックを認識してくれません。こちら原因分かりますでしょうか、、、?「Msgbox = ExApp.Workbooks.Count」としても、0になってしまいます。
hatena19

2021/01/11 05:01 編集

> 別のAccessVBAコードで、いくつかのブックが開かれることになっています。 どのように開いてますか。そのコードを提示してください。 また、そのコードをどこに記述してますか。標準モジュールあるいはフォームのモジュール、どちらですか。
hatena19

2021/01/11 05:54

CreateObject("Excel.Application") は新規に空のエクセルアプリケーションを開きます。その場合、ブックは自動では開きません。よって、Workbooks.Count は 0 です。
NGK

2021/01/11 06:13

フォームのモジュール(ボタンのクリック時イベント)で、標準モジュールに書いた以下のコードを複数回呼び出して複数のExcelブックを開いています。 Function ExcelData(frm As Form) On Error GoTo Err_cmdExcel_Click 'DAOで抽出結果のクローンを作成 Dim xlsx As Object 'Excel.Applicationを代入するオブジェクト変数 Dim wkb As Object 'Excel.Wookbookを代入するオブジェクト変数 Dim rst As DAO.Recordset '現在のレコードセットを入れる変数 Dim idx As Long 'フィールド数変数 Dim j As Long ' 最終行取得用 Const xlUp As Integer = -4162 Set rst = Nothing 'データリストの初期化 Set rst = frm.RecordsetClone 'フォームのレコードセットのクローンを代入 'レコードが存在しない場合、処理を中止 If rst.BOF = True And rst.EOF = True Then MsgBox "出力出来るデータがありません。", vbOKOnly + vbExclamation, "出力不可" 'レコードセットを閉じる rst.Close: Set rst = Nothing Exit Function End If 'レコードが存在する場合、Excelに出力 'レコードセットの最初のデータにカーソルを移動 rst.MoveFirst 'Excelファイルを内部的に作成 Set xlsx = CreateObject("Excel.Application") '作成されたExcelファイルにワークブックを追加 Set wkb = xlsx.Workbooks.Add() '追加されたワークブックに、レコードセットのデータをコピー With wkb.Worksheets(1) For idx = 1 To rst.Fields.Count .cells(1, idx).Value = rst.Fields(idx - 1).Name Next .Range("A2").CopyFromRecordset Data:=rst 'レコードセットを閉じる rst.Close: Set rst = Nothing 'Excelデータを表示 xlsx.Visible = True xlsx.UserControl = True 'メモリに展開されたExcel用オブジェクト変数を開放 Set wkb = Nothing Set xlsx = Nothing Exit_cmdExcel_Click: Exit Function Err_cmdExcel_Click: MsgBox "エラーのため、Excelへ出力できません。" & vbCrLf & "一旦フォームを閉じ、再度トライしてください。" & vbCrLf & Err.Number & Err.Description, _ vbOKOnly + vbCritical, "Excel出力不可!" Resume Exit_cmdExcel_Click End Function
hatena19

2021/01/11 06:16

このコードを回答に追記してください。回答は編集できます。
NGK

2021/01/11 06:32

追記させていただきました、引き続きよろしくお願いいたします。
guest

0

Sub hoge() Dim ExApp As Object On Error GoTo exception ' CreateObject ではすでに開いているExcelが取れないようです。 Set ExApp = GetObject(, "Excel.Application") Dim i ' To ExApp.Workbooks(ExApp.Workbooks.Count)) は間違いです。 For i = 1 To ExApp.Workbooks.Count MsgBox ExApp.Workbooks(i).Name Next i exception: MsgBox Err.Description End Sub

投稿2021/01/10 05:11

umau

総合スコア805

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NGK

2021/01/11 04:53

回答ありがとうございます。頂いたコードのように変更してみたのですが、開いているExcelブックを認識してくれません。こちら原因分かりますでしょうか、、、?「Msgbox = ExApp.Workbooks.Count」としても、0になってしまいます。
退会済みユーザー

退会済みユーザー

2021/01/11 07:13

Word のマクロで umau さんの回答を実行したところ、開いている Excel ファイル名が順次メッセージ表示されました。
guest

0

これでどうでしょう。

VBA

1For i = 2 To ExApp.Workbooks.Count 2 'ワークブック1にシートを追加してコピー 3Next

投稿2021/01/10 04:50

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NGK

2021/01/11 04:52

回答ありがとうございます。頂いたコードのように変更してみたのですが、開いているExcelブックを認識してくれません。こちら原因分かりますでしょうか、、、?「Msgbox = ExApp.Workbooks.Count」としても、0になってしまいます。
hatena19

2021/01/11 05:54

CreateObject("Excel.Application") は新規に空のエクセルアプリケーションを開きます。その場合、ブックは自動では開きません。よって、Workbooks.Count は 0 です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問