【问题标题】:Getting an Access 2007 table (.accdb extension) in ArcMap programmatically以编程方式在 ArcMap 中获取 Access 2007 表(.accdb 扩展名)
【发布时间】:2023-03-26 07:10:01
【问题描述】:

我最近从 ArcScripts 中找到了一个关于如何以编程方式在 ArcGIS 中获取 Access 表的脚本,它运行良好。但这是针对 Access 2003(.mdb 扩展名)及更早版本的。代码贴在下面,我想知道如何修改它以使用 Access 2007(.accdb 扩展名)和更高版本的数据库。

Attribute VB_Name = "Access_connect"
Sub Open_Access_Connect()
  'V. Guissard Jan. 2007

  On Error GoTo EH

  Dim data_source As String
  Dim pTable As ITable
  Dim TableName As String

  Dim pFeatWorkspace As IFeatureWorkspace
  Dim pMap As IMap
  Dim mxDoc As IMxDocument
  Dim pPropset As IPropertySet
  Dim pStTab As IStandaloneTable
  Dim pStTabColl As IStandaloneTableCollection
  Dim pWorkspace As IWorkspace
  Dim pWorkspaceFact As IWorkspaceFactory


  Set pPropset = New PropertySet
  ' Get MDB file name
  data_source = GetFolder("mdb")
  ' Connect to the MDB database
  pPropset.SetProperty "CONNECTSTRING", "Provider=Microsoft.Jet.OLEDB.4.0;" _
  & "Data source=" & data_source & ";User ID=Admin;Password="

  Set pWorkspaceFact = New OLEDBWorkspaceFactory
  Set pWorkspace = pWorkspaceFact.Open(pPropset, 0)
  Set pFeatWorkspace = pWorkspace

  ' Get table name
  TableName = SelectDataSet(pFeatWorkspace, "Table")
  ' Open the table
  Set pTable = pFeatWorkspace.OpenTable(TableName)
  'Create Table collection and add the table to ArcMap
  Set mxDoc = ThisDocument
  Set pMap = mxDoc.FocusMap
  Set pStTab = New StandaloneTable
  Set pStTab.Table = pTable
  Set pStTabColl = pMap
  pStTabColl.AddStandaloneTable pStTab

  ' Update ArcMap Source TOC
  mxDoc.UpdateContents

  Exit Sub

EH:

  MsgBox "Access connect: " & Err.Number & " " & Err.Description

End Sub

Public Function GetFolder(Optional aFilter As String) As String
  ' Open a GUI to let the user select a Folder path name (by default) or :
  ' Set aFilter = "shp" to get a shapefile name
  ' Set aFilter = "mdb" to get an MS Access file name
  ' Return the Folder Path or phath & file name As String
  ' V. Guissard Jan. 2007

  Dim pGxDialog As IGxDialog
  Dim pFilterCol As IGxObjectFilterCollection
  Dim pCurrentFilter As IGxObjectFilter
  Dim pEnumGx As IEnumGxObject

  Select Case aFilter
    Case "shp"
      Set pCurrentFilter = New GxFilterShapefiles
      aTitle = "Select Shapefile"
    Case "mdb"
      Set pCurrentFilter = New GxFilterContainers
      aTitle = "Select MS Access database"
    Case Else
      Set pCurrentFilter = New GxFilterBasicTypes
      aTitle = "Select Folder"
  End Select

  Set pGxDialog = New GxDialog
  Set pFilterCol = pGxDialog
  With pFilterCol
    .AddFilter pCurrentFilter, True
  End With
  With pGxDialog
    .Title = aTitle
    .ButtonCaption = "Select"
  End With

  If Not pGxDialog.DoModalOpen(0, pEnumGx) Then
    Smp = MsgBox("No selection : Exit", vbCritical)
    End
    'Exit Function 'Exit if user press Cancel
  End If
  GetFolder = pEnumGx.Next.FullName

End Function

Public Function SelectDataSet(pWorkspace As IWorkspace, Optional theDataType As String) As String
  ' Open a GUI to let the user select a DataSet into a Workspace
  ' (Table or Request into an MS Access Database or a Geodatabase File)
  ' Set pWorkspace to the DataSet IWorkspace
  ' Set theDataType = "Table" to select a Table name of the DataSet
  ' Return the selected Table or Request Table name As String
  ' V. Guissard Jan. 2007

  Dim aDataset As Boolean
  Dim boolOK As Boolean
  Dim DataSetList As New Collection
  Dim datasetType As Integer
  Dim n As Integer

  Dim pDataSetName As IDatasetName
  Dim pListDlg As IListDialog
  Dim pEnumDatasetName As IEnumDatasetName

  ' Set the Dataset Type
  Select Case theDataType
    Case "Table"
      datasetType = 10
    Case Else
      Answ = MsgBox("Need a Dataset Type : Exit", vbCritical, "SelectDataset")
      End
  End Select

  ' Get the Dataset Names included in the workspace
  Set pEnumDatasetName = pWorkspace.DatasetNames(datasetType)

  ' Create the Dataset Names List Dialog
  aDataset = False
  Set pListDlg = New ListDialog
  pEnumDatasetName.Reset
  Set pDataSetName = pEnumDatasetName.Next
  Do While Not pDataSetName Is Nothing

       pListDlg.AddString pDataSetName.name
       DataSetList.Add (pDataSetName.name)
        Set pDataSetName = pEnumDatasetName.Next
        aDataset = True
  Loop

  ' Open a GUI for the user to select a dataset
  If aDataset Then
    boolOK = pListDlg.DoModal("Select a " & theDataType, 0, Application.hwnd)
    n = pListDlg.choice
    If (n <> -1) Then
        SelectDataSet = DataSetList(n + 1)
    Else
        Sup = MsgBox("No DataSet selected : EXIT", vbCritical, "SelectDataset")
        End
    End If
  End If
End Function

这里是 ArcScript 的链接:http://arcscripts.esri.com/Data/AS14882.bas

PS 我知道这段代码是用 VBA 编写的,我不知道修改后的版本是用 VB.NET 还是其他语言。

谢谢, 阿德里安

【问题讨论】:

    标签: ms-access ms-access-2007 arcgis esri arcobjects


    【解决方案1】:

    Access 2007 的连接字符串是

    Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\myFolder\myAccess2007file.accdb;Persist Security Info=False;
    

    所以

    pPropset.SetProperty "CONNECTSTRING", "Provider=Microsoft.ACE.OLEDB.12.0;" _
    & "Data source=" & data_source & ";User ID=Admin;Password="
    

    -- http://www.connectionstrings.com/access-2007

    【讨论】:

    • 请注意,OLEDB 不能处理数据库密码,但 ODBC 可以。
    【解决方案2】:

    当试图找出 ArcObjects 的连接属性时,我发现使用 GUI 在 arccatalog 中设置 OleDB 连接很有帮助。一旦测试成功,我就会运行这个 VBA 脚本来列出连接属性,然后我可以将其复制并粘贴到我的代码中。

    Sub ListConnProps()
        Dim pGxApp As IGxApplication
        Set pGxApp = Application
        If Not TypeOf pGxApp.SelectedObject Is IGxDatabase Then
            Debug.Print "select a geodb first"
            Exit Sub
        End If
        Dim pGXdb As IGxDatabase2
        Set pGXdb = pGxApp.SelectedObject
        Dim names As Variant, values As Variant
        Debug.Print pGXdb.WorkspaceName.WorkspaceFactoryProgID
        pGXdb.WorkspaceName.ConnectionProperties.GetAllProperties names, values
        Dim l As Long
        For l = 0 To UBound(names)
            Debug.Print names(l), values(l)
        Next l
    
    End Sub
    

    更新:这是我在从here 下载提供程序后成功测试的一些代码,以及从here 下载的测试 accdb 文件。我没有使用密码,所以无法测试。

    public static void TestOleDB()
    {
        IWorkspaceFactory wsf = new OLEDBWorkspaceFactoryClass();
        IPropertySet ps = new PropertySetClass();
        string connStr = "Provider=Microsoft.ACE.OLEDB.12.0;"
            + @"Data Source=D:\Projects\AmberGIS\Forums\MikeGarage\MikeGarage.accdb;"
            + "Persist Security Info=False";
    
        // if you're using a password, use next line (??)
        //((IOleDBConnectionInfo)wsf).SetParameters(connStr, "");
        ps.SetProperty("CONNECTSTRING", connStr);
        IWorkspace ws = wsf.Open(ps, 0);
        IEnumDatasetName enumDsn = ws.get_DatasetNames(esriDatasetType.esriDTAny);
        IDatasetName dsn;
        while((dsn=enumDsn.Next())!= null)
            Debug.Print(dsn.Name);
    
    }
    

    【讨论】:

    • Remou,我本来想早点写的,我试过了,结果出错了。 Kirk,我运行了该代码,它提供连接字符串的方式很好,但是当我将它放入现有代码时,我得到了同样的错误。我得到的错误是“5 个无效的过程调用或参数”。还有什么我想念的吗?还是因为accdb不能直接与ArcGIS一起使用而无法正确处理的问题?谢谢
    • 虽然 ESRI 不像支持 .mdb 文件那样支持地理数据库的 .accdb 文件,但它们确实支持 OleDB。您可以通过 arccatalog 中的 oleDB 连接查看表吗?您也可以在使用您的属性集调用 open 之前尝试在 workspacefactory 上调用 IOleDBConnectionInfo.SetParameters。
    • 是的,我可以在 ArcCatalog 中查看它们并将它们带入 ArcGIS。我尝试使用 IOleDBConnectionInfo 接口,但遇到了同样的错误。由于它是accdb,我还缺少其他东西吗?或者您能否提供一个示例,说明所有需要在 arcobjects 中组合在一起以便以编程方式获取这些表的示例?就像我的意思一样,我需要将哪些变量和接口链接在一起(从 IOleDBConnectionInfo 到什么?)谢谢!
    • 柯克,不知何故,我刚刚在上面看到了您编辑的代码。它工作得很好,并进入 accdb 数据库给我每个表的名称。这很好,但我如何实际访问这些表?我想最后我想将 ITable 接口分配给该数据库中的特定表。如果这很明显,我很抱歉,我只是错过了正确的链接。请告诉我!谢谢!
    • Kirk,我通过将 IFeatureWorkspace 与 IWorkspace 接口一起使用,然后在其中使用“OpenTable”方法解决了这个问题。
    猜你喜欢
    • 1970-01-01
    • 2011-10-13
    • 2013-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 1970-01-01
    相关资源
    最近更新 更多