こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

【Access2013】エラー回避 他

https://okwave.jp/qa/q9714515.htmlの続きです。

「書式設定を保持したままエクスポート」というマクロを多用しています。
ここでは細かい設定ができるのでいろいろなAccessで使用していたのですが、出力先フォルダやファイル名が限定されてしまうのがネックになっていました。
そこでhttps://okwave.jp/qa/q9714515.htmlにてVBAでの出力方法をご教示いただいたのですが、3つほど困ったことがあります。


1.「書式設定を保持したままエクスポート」したい

ググると「DoCmd.OutputTo メソッドを使え」とのことですが、添付画像のVBAにどのように組み込めばいいのか分かりません。


2.「名前を付けて保存」画面が出ない

当該Accessを開いた後「Excel出力」ボタンをクリックすると「名前を付けて保存」画面が出ず、タスクマネージャからExcelをダブルクリックしないと表示されないのです。
Accessをデザイン編集したあとクリックすると出てきます。


3.xlsxファイルを開くとエラーが出る

出力したxlsxファイルを開くと、添付画像の「~の一部の内容に~」「~の修復」という2つエラーが出ます。
2つ目のエラーに関しては、「書式設定を保持したままエクスポート」では「修復されたレコード」のみ、VBAでは「削除されたレコード」と「修復されたレコード」が表示されます。
それぞれの方法で保存したデータを見る限り、書式の違いはあるもののデータの抜け等はありませんでした。


これら3つをすべて解決する方法はありませんか?

投稿日時 - 2020-02-27 08:03:21

QNo.9717368

すぐに回答ほしいです

質問者が選んだベストアンサー

同じようなコードがあるので名前を変更していたのですが、一部元に戻し忘れてました。

If sfile = "False" Then
SaveFile_FileDialogEx = ""
Else
SaveFile_FileDialogEx = sfile
End If
のところを以下に変更してください。
If sfile = "False" Then
SaveFile_FileDialog = ""
Else
SaveFile_FileDialog = sfile
End If

投稿日時 - 2020-03-09 17:25:56

お礼

何度もご回答ありがとうございました。

できました!!
Accessファイルを開いてすぐにExcel出力してもエラーが出ずに保存することができました。
前回(https://okwave.jp/qa/q9714515.html)と違い、今回は完全に上書き保存されていました。本来の動作に戻ったようです。

念の為、標準モジュールの「Public Declare Function ShowWindow Lib "user32"~」の”Declare”を”Declare PtrSafe”に変えておきました。

前回「他のAccessでもExcel出力したいものが多々ありますので、早速流用させていただきます」と返答したものの結局は再度質問してしまいましたが、今回ばかりは大丈夫かと思います。
毎回ご回答いただき、本当に感謝しております。

ありがとうございました。

投稿日時 - 2020-03-10 08:18:04

ANo.8

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(8)

ANo.7

あれこれ一度にやったので混乱しますよね。こちらもコードが一時混乱状態になりました。とりあえずこちらの状態を記載します

FindWindowEx Lib のところはいらないので元の ShowWindow Lib にしてください。

こちらの状態です。

標準モジュール

Option Compare Database
Option Explicit
Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long

Private Const SW_SHOWMINIMIZED As Long = 2 ' ウィンドウを最小化する


Public Function SaveFile_FileDialog() As String
Dim oexcel As New Excel.Application
Dim sfile As String

ShowWindow oexcel.hwnd, SW_SHOWMINIMIZED

sfile = oexcel.GetSaveAsFilename( _
FileFilter:="Excelファイル,*.xlsx,全てのファイル,*.*", _
FilterIndex:=1, _
InitialFileName:="管理表", _
Title:="名前を付けて保存")

If sfile = "False" Then
SaveFile_FileDialogEx = ""
Else
SaveFile_FileDialogEx = sfile
End If

Set oexcel = Nothing

End Function




ダイアログの方のモジュール

Private Sub Excel出力_Click()
Dim sFina As String
Dim flg As String

sFina = SaveFile_FileDialog
If sFina <> "" Then
If Dir(sFina) <> "" Then
If vbNo = MsgBox("上書き保存しますか?", vbYesNo + vbQuestion) Then
Exit Sub
End If
End If
DoCmd.OutputTo acOutputQuery, "Q_管理表", acFormatXLSX, sFina
End If
End Sub

投稿日時 - 2020-03-09 13:18:26

お礼

何度もご回答ありがとうございました。

両方コピペしてみました。
Accessファイルは正常に戻りましたが、標準モジュールにて「変数が定義されていません」というコンパイルエラーが出て「SaveFile_FileDialogEx =」が反転してしまいました・・・

投稿日時 - 2020-03-09 16:50:50

ANo.6

> 64bitがダメなんでしょうか・・・

環境がないので試せないのではっきりは言えませんがそうかもしれません。
msoFileDialogSaveAs は Access ではサポートされていないという事なので動かなくても仕方はないのですが…。
ただ、紹介したサイトや私の環境では動いたので32bitはOKでした。

後者のwizhookオブジェクトを使うのも非公開オブジェクトなので、もしかしたら64bitだと駄目かもしれませんね。

となると
> ググって”Declare”を”Declare PtrSafe”にしたらエラーは回避できました。

という事なので、質問にあった
Dim oexcel As New Excel.Application
を使ったやつで
ShowWindow oexcel.hwnd, 2
を試してみてはいかがでしょう。

単に2だと後でわかりにくい場合は(Declare PtrSafeを検索して見つけました)
https://social.msdn.microsoft.com/Forums/sqlserver/ja-JP/47bd4158-bcc9-45f3-8b55-e7526961e28d/accessibleobjectfromwindow-12391-window?forum=vbajp

こちらの
' ウィンドウを非表示/表示/最小化などをするための定数 (ShowWindow 用)
の部分をDeclare PtrSafeの下にコピペして
ShowWindow oexcel.hwnd, SW_SHOWMINIMIZED
としておくと分かりやすいかもしれません。

投稿日時 - 2020-03-03 16:58:37

お礼

何度もご回答ありがとうございました。
新型コロナ対応で多忙だったため、返答が遅くなりました。

わけが分からなくなってしまったので、とりあえず質問に記載したVBAに戻して「Option Compare Database~」と「Public Function SaveFile_FileDialog() As String~」を標準モジュールに記載しました。
しかし、「Option Compare Database~」で「プロシージャの外では無効です。」というコンパイルエラーが出て「oexcel」が反転しました。

---------------------
Option Compare Database
Option Explicit
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, _
ByVal lpsz1 As String, ByVal lpsz2 As String _
) As LongPtr

' ウィンドウを非表示/表示/最小化などをするための定数 (ShowWindow 用)
ShowWindow oexcel.hwnd, SW_SHOWMINIMIZED
---------------------

Accessファイルそのものもおかしくなってしまったので、これでダメだったらVBAはあきらめて「書式設定を保持したままエクスポート」マクロに戻します・・・

投稿日時 - 2020-03-09 12:32:30

ANo.5

> 「変数が定義されていません。」というコンパイルエラーが出
> て、”msoFileDialogSaveAs”が反転しました。

参照設定で「Microsoft Office 15.0 Object Library」を有効にします。
これは実施したでしょうか。64bit(なんですね)だと駄目なのでしょうか。

投稿日時 - 2020-03-02 13:11:04

お礼

何度もご回答ありがとうございました。

「Microsoft Office 15.0 Object Library」は最初から設定済です。

64bitがダメなんでしょうか・・・

投稿日時 - 2020-03-03 15:12:17

ANo.4

あと、Excel.Applicationを使うやつですが
ShowWindow oexcel.hwnd, 1
だとエクセル本体が表示されるので
ShowWindow oexcel.hwnd, 2
で最小化しておくとかでしょうか。

投稿日時 - 2020-02-28 06:56:21

お礼

何度もご回答ありがとうございました。

この件はNo.2と3のエラーが解決するまで保留ですね・・・

投稿日時 - 2020-03-02 12:40:38

ANo.3

No2の一部を修正したほうがいい感じがします。
(修正しなくても動きます)

Function SaveFile_FileDialogMso()

Function SaveFile_FileDialogMso(strFilePath As String)
にして
その中の
.InitialFileName = CurrentProject.Path & "\" & "管理表.xlsx"

.InitialFileName = strFilePath
にして

Private Sub Excel出力_Click()
の中の
sFina = SaveFile_FileDialogMso

sFina = SaveFile_FileDialogMso(CurrentProject.Path & "\" & "管理表.xlsx")
にした方が汎用性がある感じです。
他のイベントプロシージャから(他のフォームも含めて)も
sFina = SaveFile_FileDialogMso(保存先とファイル名)
みたいな感じで利用できます。

投稿日時 - 2020-02-27 16:54:41

お礼

何度もご回答ありがとうございました。

Accessそのものが強制終了してしまいます・・・
No.2のコンパイルエラーが原因でしょうか・・・

投稿日時 - 2020-03-02 12:40:24

ANo.2

> 2.に関してですが、ご教示いただいた”Public Declare Function ~”を最上部=
Public Function SaveFile_FileDialog() As String
のコードを標準モジュールに記載してください。
それで最上部に
Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long
とします。
添付画像を参照してください。

他のやり方の部分ですが
前者後者どちらも
Function
:
End Function
の部分は標準モジュールに記載してください。

前者の方法 (上書きの確認はダイアログの機能としてあります)
参照設定で「Microsoft Office 15.0 Object Library」を有効にします。

Private Sub Excel出力_Click()
Dim sFina As String
Dim flg As String

sFina = SaveFile_FileDialogMso
If sFina <> "" Then
DoCmd.OutputTo acOutputQuery, "Q_管理表", acFormatXLSX, sFina
End If
End Sub

ここから標準モジュールに
Function SaveFile_FileDialogMso()
Dim dlg As Object, boolResult As Boolean
Dim strFiles As String, i As Long
'オブジェクト変数にFileDialogオブジェクトを代入
Set dlg = Application.FileDialog(msoFileDialogSaveAs)
'FileDialogオブジェクトの各種プロパティを設定
With dlg
.Title = "別名保存"
.ButtonName = "保存実行" 'デフォルトは[保存(&S)]
.InitialFileName = CurrentProject.Path & "\" & "管理表.xlsx"
' CurrentProject.Path実行中のAccessのフォルダになります。
'.InitialFileName = "管理表.xlsx"とするとマイドキュメントが開きます。
End With
'[名前を付けて保存]ダイアログボックスを表示する
boolResult = dlg.Show
If boolResult Then
For i = 1 To dlg.SelectedItems.Count
strFiles = strFiles & dlg.SelectedItems(i)
SaveFile_FileDialogMso = strFiles
Next i
'MsgBox "[名前を付けて保存]で指定されたファイル名は、" + vbCrLf + strFiles & "です。"
Else
'[キャンセル]ボタンが押された場合の処理
SaveFile_FileDialogMso = ""
'MsgBox "[キャンセル]ボタンが押されました。"
End If
End Function



後者の方法(非公開オブジェクトなので自己責任みたいです)

Private Sub Excel出力_Click()
Dim ReturnArray As Variant
ReturnArray = GetFileName(False, "Excelファイル (*.xlsx,*.xls)|*.xlsx|*.xls", "Excelファイルの保存", _
CurrentProject.Path & "\" & "管理表.xlsx")
If ReturnArray(0) = -302 Then
'キャンセルボタンが押されたときの処理を記述
' MsgBox "キャンセルが押されました。"
Exit Sub
Else
'ファイルが指定されたとこの処理を記述
If ReturnArray(1) <> "" Then
If Dir(ReturnArray(1)) <> "" Then
If vbNo = MsgBox("上書き保存しますか?", vbYesNo + vbQuestion) Then
Exit Sub
End If
End If
End If
DoCmd.OutputTo acOutputQuery, "Q_管理表", acFormatXLSX, ReturnArray(1)
End If
End Sub

ここから標準モジュールに
Function GetFileName(OpenOrSaveFlg As Boolean, strFilter As String, _
strTitle As String, strFilePath As String) As Variant
Dim returnValue As Integer

If strFilter = "" Then
strFilter = "全てのファイル (*.*)|*.*"
End If
WizHook.Key = 51488399 'WIZHOOK有効
returnValue = WizHook.GetFileName( _
0, "", strTitle, "", strFilePath, "", _
strFilter, _
0, 0, 0, OpenOrSaveFlg _
)
WizHook.Key = 0 ' WizHook 無効
'returnValueとstrFilePathの2つの値を返す
'returnvalueの値を返すことで[キャンセル]が押されたかを判断するため
GetFileName = Array(returnValue, strFilePath)
End Function

投稿日時 - 2020-02-27 14:37:10

お礼

再度のご回答ありがとうございました。

前者のVBAを試してみました。
う~~ん、コンパイルエラーが出てストップしました。

最初「このプロジェクトのコードは、64ビット システムで使用するために更新する必要があります。Declare ステートメントに PtrSafe 属性を設定してください。」というコンパイルエラーが出ましたが、ググって”Declare”を”Declare PtrSafe”にしたらエラーは回避できました。

次は「変数が定義されていません。」というコンパイルエラーが出て、”msoFileDialogSaveAs”が反転しました。
これに関してはググっても解決方法が分かりません・・・

投稿日時 - 2020-03-02 12:40:03

ANo.1

> 3.xlsxファイルを開くとエラーが出る

DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, "Q_管理表", sFina

DoCmd.OutputTo acOutputQuery, "Q_管理表", acFormatXLSX, sFina
にしてください。


ダイアログの件ですが、
最上部に
Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long
として
ShowWindow oexcel.hwnd, 1

SaveFile_FileDialog()
の最初に記載すれば表示されるようになると思いますが、エクセルが起動するので遅いと思います。

以下の方法に変更してみてはいかがでしょう。

VBA:AccessのFileDialogを使用して[名前を付けて保存]ダイアログボックスを表示するサンプルプログラム
https://selifelog.com/blog-entry-249.html
設定は簡単、ただし、保存するファイルの種類を指定(限定)したりすることもできない

種類が指定できるが設定が上記より多少手間かも
Access VBA:WizHookオブジェクトを使用して[ファイルを開く]、[名前を付けて保存]ダイアログボックスを表示するサンプルプログラム
https://selifelog.com/blog-entry-53.html

投稿日時 - 2020-02-27 09:30:15

お礼

ご回答ありがとうございました。

1.と3.に関しては「書式設定を保持したままエクスポート」され、「修復されたレコード」のみのエラーになりました。
助かりました。


2.に関してですが、ご教示いただいた”Public Declare Function ~”を最上部=”Private Sub Excel出力_Click()”の次の段に貼り付けたのですが、赤文字になってしまったのでエラーのようです。
”ShowWindow oexcel.hwnd, 1”の貼り付け位置は”Public Function SaveFile_FileDialog() As String”の上の段でしょうか?貼り付けても”End Sub”の下に表示されてしまいます。

質問にも記載した通り、Accessを開いてデザイン編集しなかった場合は表示されないのに、編集した後はきちんと表示されるのが不思議です・・・


2つのリンクを見てみましたが、さっぱり分かりません・・・
そもそもVBAはネット情報そのままを貼り付けているだけなので、仕組みは全然理解しておりません・・・

投稿日時 - 2020-02-27 12:14:21

あなたにオススメの質問