vba Access 2010 64bit 是否有打开文件对话框?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4746938/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 11:05:14  来源:igfitidea点击:

Is there an Open File dialog for Access 2010 64bit?

ms-accessvbaaccess-vbaopenfiledialogms-access-2010

提问by Greg Finzer

How do I get an Open File dialog for Access 2010 64bit? Normally I would use the common dialog control but that is 32bit and cannot be used with Access 2010 64 bit.

如何获得 Access 2010 64 位的“打开文件”对话框?通常我会使用通用对话框控件,但它是 32 位的,不能与 Access 2010 64 位一起使用。

采纳答案by Greg Finzer

This guy has a tool that generates code that is 64 bit compatible for opening a file. It is freeware.

这家伙有一个工具可以生成与打开文件的 64 位兼容的代码。它是免费软件。

http://www.avenius.de/en/index.php?Products:IDBE_Tools

http://www.avenius.de/en/index.php?Products:IDBE_Tools

This was the only thing that worked.

这是唯一有效的方法。

回答by Albert D. Kallal

You can use the built in file dialog. It been there since access 2003.

您可以使用内置的文件对话框。它自 2003 年访问以来一直存在。

Dim f    As FileDialog 
Set f = Application.FileDialog(msoFileDialogFilePicker) 
f.Show 
MsgBox "file choose was " & f.SelectedItems(1) 

You can late bind if you wish:

如果您愿意,您可以延迟绑定:

above needs: Microsoft Office 14.0 Object library

以上需求:Microsoft Office 14.0 Object library

If you remove the reference to the 14.0 object library, then the following code will work without any references:

如果删除对 14.0 对象库的引用,则以下代码将在没有任何引用的情况下工作:

Dim f    As Object 
Set f = Application.FileDialog(3) 
f.AllowMultiSelect = True 
f.Show 

MsgBox "file choosen = " & f.SelectedItems.Count 

So, above works in runtime or regular edition from 2003 onwards, and also works for either 32 or 64 bit editions of access 2010.

因此,上述适用于 2003 年以后的运行时或普通版,也适用于 32 位或 64 位版本的 access 2010。

回答by Tony Toews

I've never used a control for the open File dialog as it's just a wrapper for the API call anyhow. Call the standard Windows File Open/Save dialog boxIn addition there can be distribution and versioning problems with controls so I do my best to avoid them.

我从来没有使用过打开文件对话框的控件,因为它只是 API 调用的包装器。 调用标准的 Windows 文件打开/保存对话框此外,控件可能存在分发和版本控制问题,因此我会尽力避免它们。

回答by Max Albanese

I was working with this problem for a long while...

我在这个问题上工作了很长时间......

Everything you have said above works but there is one last piece to add ... under the WITH OFN declaration you need to change

您上面所说的所有内容都有效,但还有最后一项要添加...在 WITH OFN 声明下,您需要更改

.lStructSize = Len(ofn)

to

.lStructSize = LenB(ofn)

And then everything works.

然后一切正常。

回答by Cody Gray

First of all, the "CommonDialog Class" doesn't even appear to work on a 32-bit version of Office. It gives the same OleDb error. As one of the commenters points out, this isn't the control you should be using. And while there might be another ActiveX control you could use, there's really no guarantee that it will be available on every machine that you want to deploy your database on. My dev box has Visual Studio 6, VS 2008, and VS 2010 on it, in addition to Office and other programs, all of which provide ActiveX DLLs that a typical user could not be expected to have. Additionally, many of these libraries are not redistributable, or pose unique installation hurdles that may simply not be worth the trouble.

首先,“CommonDialog 类”甚至似乎不适用于 32 位版本的 Office。它给出了相同的 OleDb 错误。正如一位评论者指出的那样,这不是您应该使用的控件。虽然您可能会使用另一个 ActiveX 控件,但实际上并不能保证它在您想要部署数据库的每台机器上都可用。我的开发箱上装有 Visual Studio 6、VS 2008 和 VS 2010,以及 Office 和其他程序,所有这些程序都提供典型用户无法拥有的 ActiveX DLL。此外,这些库中的许多都不可再分发,或者造成独特的安装障碍,可能根本不值得麻烦。

By far, the simplest, most universal solution is to call the Open dialog from the Windows API.It's located in comdlg32.dll, which is available on every version of Windows you could possibly be targeting, and doesn't impose any dependencies on comdlg32.ocx. It also provides better performance than using an ActiveX control because it doesn't require an additional module to be loaded into memory.

到目前为止,最简单、最通用的解决方案是从 Windows API 调用打开对话框。它位于 comdlg32.dll 中,它在您可能定位的每个 Windows 版本上都可用,并且不会对 comdlg32.ocx 强加任何依赖项。它还提供比使用 ActiveX 控件更好的性能,因为它不需要将额外的模块加载到内存中。

The code that is required isn't very complicated either. You need to provide a declaration for the function GetOpenFileName, which creates the Open dialog box. It takes a single parameter, an instance of the OPENFILENAMEstructurethat contains information used to initialize the dialog box, as well as receiving the path to the file selected by the user. So you'll also need to provide a declaration of this structure. The code in VBA would look something like this:

所需的代码也不是很复杂。您需要为函数提供一个声明GetOpenFileName,它会创建打开对话框。它接受一个参数,一个包含用于初始化对话框的信息的OPENFILENAME结构实例,以及接收用户选择的文件的路径。因此,您还需要提供此结构的声明。VBA 中的代码如下所示:

Private Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As String
    lpstrCustomFilter As String
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As String
    nMaxFile As Long
    lpstrFileTitle As String
    nMaxFileTitle As Long
    lpstrInitialDir As String
    lpstrTitle As String
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As String
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
End Type

Private Declare Function GetOpenFileName Lib "comdlg32.dll" _
    Alias "GetOpenFileNameA" (ByRef lpofn As OPENFILENAME) As Long

There are also a couple of constants you can pass as flags to customize the dialog's behavior. For completeness, here's the full list:

还有一些常量可以作为标志传递来自定义对话框的行为。为完整起见,以下是完整列表:

Private Const OFN_ALLOWMULTISELECT As Long = &H200
Private Const OFN_CREATEPROMPT As Long = &H2000
Private Const OFN_ENABLEHOOK As Long = &H20
Private Const OFN_ENABLETEMPLATE As Long = &H40
Private Const OFN_ENABLETEMPLATEHANDLE As Long = &H80
Private Const OFN_EXPLORER As Long = &H80000
Private Const OFN_EXTENSIONDIFFERENT As Long = &H400
Private Const OFN_FILEMUSTEXIST As Long = &H1000
Private Const OFN_HIDEREADONLY As Long = &H4
Private Const OFN_LONGNAMES As Long = &H200000
Private Const OFN_NOCHANGEDIR As Long = &H8
Private Const OFN_NODEREFERENCELINKS As Long = &H100000
Private Const OFN_NOLONGNAMES As Long = &H40000
Private Const OFN_NONETWORKBUTTON As Long = &H20000
Private Const OFN_NOREADONLYRETURN As Long = &H8000&
Private Const OFN_NOTESTFILECREATE As Long = &H10000
Private Const OFN_NOVALIDATE As Long = &H100
Private Const OFN_OVERWRITEPROMPT As Long = &H2
Private Const OFN_PATHMUSTEXIST As Long = &H800
Private Const OFN_READONLY As Long = &H1
Private Const OFN_SHAREAWARE As Long = &H4000
Private Const OFN_SHAREFALLTHROUGH As Long = 2
Private Const OFN_SHAREWARN As Long = 0
Private Const OFN_SHARENOWARN As Long = 1
Private Const OFN_SHOWHELP As Long = &H10
Private Const OFS_MAXPATHNAME As Long = 260

And for convenience, I've wrapped this whole mess inside of a helper function that you can call from within VBA. It accepts as parameters the properties you will most commonly need to set for the open file dialog, handles calling the Windows API itself, and then returns either the full path to the file selected by the user, or an empty string (vbNullString) if the user clicked the Cancel button. You can test the return value in the calling code to determine which course of action to take.

为方便起见,我将整个混乱包装在一个辅助函数中,您可以在 VBA 中调用该函数。它接受您最常需要为打开文件对话框设置的属性作为参数,处理调用 Windows API 本身,然后返回用户选择的文件的完整路径,或者vbNullString如果用户单击取消按钮。您可以测试调用代码中的返回值以确定要采取的操作过程。

'This function shows the Windows Open File dialog with the specified
' parameters, and either returns the full path to the selected file,
' or an empty string if the user cancels.
Public Function OpenFile(ByVal Title As String, ByVal Filter As String, _
    ByVal FilterIndex As Integer, ByVal StartPath As String, _
    Optional OwnerForm As Form = Nothing) As String

    'Create and populate an OPENFILENAME structure
    'using the specified parameters
    Dim ofn As OPENFILENAME
    With ofn
        .lStructSize = Len(ofn)
        If OwnerForm Is Nothing Then
            .hwndOwner = 0
        Else
            .hwndOwner = OwnerForm.Hwnd
        End If
        .lpstrFilter = Filter
        .nFilterIndex = FilterIndex
        .lpstrFile = Space$(1024) & vbNullChar & vbNullChar
        .nMaxFile = Len(ofn.lpstrFile)
        .lpstrFileTitle = vbNullChar & Space$(512) & vbNullChar & vbNullChar
        .nMaxFileTitle = Len(.lpstrFileTitle)
        .lpstrInitialDir = StartPath & vbNullChar & vbNullChar
        .lpstrTitle = Title
        .flags = OFN_FILEMUSTEXIST
    End With

    'Call the Windows API function to show the dialog
    If GetOpenFileName(ofn) = 0 Then
        'The user pressed cancel, so return an empty string
        OpenFile = vbNullString
    Else
        'The user selected a file, so remove the null-terminators
        ' and return the full path
        OpenFile = Trim$(Left$(ofn.lpstrFile, Len(ofn.lpstrFile) - 2))
    End If
End Function

Wow that ended up being long. There are a lot of declarations you'll need to copy and paste into a module, but the interface you actually have to deal with is surprisingly simple. Here's a sample of how you might actually use this in your code to show the open file dialog and get the path to a file:

哇,结果很长。您需要将许多声明复制并粘贴到模块中,但您实际需要处理的接口却出奇地简单。下面是一个示例,说明如何在代码中实际使用它来显示打开文件对话框并获取文件路径:

Public Sub DoWork()
    'Set the filter string (patterns) for the open file dialog
    Dim strFilter As String
    strFilter = "Text Files (*.txt)" & vbNullChar & "*.txt*" & vbNullChar & _
                "All Files (*.*)" & vbNullChar & "*.*" & vbNullChar & vbNullChar

    'Show the open file dialog with the custom title, the filters specified
    ' above, and starting in the root directory of the C: drive.
    Dim strFileToOpen As String
    strFileToOpen = OpenFile("Choose a file to open", strFilter, 0, "C:\")

    'See if the user selected a file
    If strFileToOpen = vbNullString Then
        MsgBox "The user pressed the Cancel button."
    Else
        MsgBox "The user chose to open the following file: " & _
               vbNewLine & strFileToOpen 
    End If
End Sub

The longest part of writing and testing this solution was actually trying to find how to open the VBA editor and write a macro in Access. The Ribbon might be a great invention for people who use the menu primary for "Paste" and "Save", but what a pain. I spend all day using software, and I still can't find stuff. [/rant]

编写和测试此解决方案的最长部分实际上是试图找到如何打开 VBA 编辑器并在 Access 中编写宏。对于使用菜单主菜单“粘贴”和“保存”的人来说,功能区可能是一项伟大的发明,但这是多么痛苦。我整天都在使用软件,但我仍然找不到东西。[/咆哮]

回答by David-W-Fenton

I missed the 64-bit Access detail. It's very unlikely that you should be running it, but if you are, here is an article for your consideration that explains how you have to alter your API call to work -- you have to use the new long pointer data type:

我错过了 64 位访问细节。您不太可能应该运行它,但如果您是,这里有一篇文章供您考虑,它解释了您必须如何更改 API 调用才能工作——您必须使用新的长指针数据类型:

Compatibility Between the 32-bit and 64-bit Versions of Office 2010

Office 2010 32 位和 64 位版本之间的兼容性

If you alter the API code accordingly, it should work fine on 64-bit Access.

如果您相应地更改 API 代码,它应该可以在 64 位 Access 上正常工作。

But you should really ask why you're using 64-bit Access. It's really not at all recommended by MS that anyone use 64-bit Office unless they have specific reasons why they need it (such as needing to use the extra memory it provides, particularly for things like complex Excel spreadsheet models). Access is definitely not one of the apps that benefits much from the conversion to 64-bit.

但是您真的应该问一下为什么要使用 64 位 Access。MS 完全不建议任何人使用 64 位 Office,除非他们有特定的原因需要它(例如需要使用它提供的额外内存,特别是对于复杂的 Excel 电子表格模型之类的东西)。Access 绝对不是从转换到 64 位中获益良多的应用程序之一。

Detailed discussion of the subject:

主题的详细讨论:

In short, most people shouldn't be running 64-bit Office, precisely for the reason you encountered -- it causes legacy code with outside dependencies on 32-bit components and APIs to fail.

简而言之,大多数人不应该运行 64 位 Office,这正是您遇到的原因——它会导致对 32 位组件和 API 具有外部依赖性的遗留代码失败。

回答by w5m

I've just been wrestling with resolving this issue in a 64-bit version of Excel 2013.

我一直在努力在 64 位版本的 Excel 2013 中解决这个问题。

A combination of...

组合...

  1. Using the LongPtrdata type for 3 of the items (hwndOwner, hInstance, lpfnHook) in the OPENFILENAMEstructure passed to GetOpenFileNameA
  2. Replacing the Lenfunction with the LenBfunction when obtaining the size of the OPENFILENAMEstructure (as mentioned by Max Albanese)
  1. 使用传递给的结构中的LongPtr3 个项目 ( hwndOwner, hInstance, lpfnHook)的数据类型OPENFILENAMEGetOpenFileNameA
  2. 在获取结构的大小时LenLenB函数替换函数OPENFILENAME(如 Max Albanese 所述)

...did the trick, thanks to guidance documented here: https://gpgonaccess.blogspot.co.uk/2010/03/work-in-progress-and-64-bit-vba.html

...做到了这一点,感谢此处记录的指导:https: //gpgonaccess.blogspot.co.uk/2010/03/work-in-progress-and-64-bit-vba.html