将 Excel 中的动态和静态范围导入到 MS-Access 中,而不是从单元格 A1 开始
Posted
技术标签:
【中文标题】将 Excel 中的动态和静态范围导入到 MS-Access 中,而不是从单元格 A1 开始【英文标题】:Import Dynamic and Static ranges from Excel in to MS-Access that do not start at cell A1 【发布时间】:2013-04-10 16:00:29 【问题描述】:如何链接 Excel 电子表格中的数据范围,以便该范围内的数据在 Access 中显示为可用表?
链接到具有从单元格 A1 开始的数据的 Excel 工作表很容易,但是 Excel 电子表格中的数据从工作表的其他位置开始,我不确定如何让 Access 精确定位它,特别是如果非 A1 范围是动态的。
通过导入/链接向导时,访问似乎没有选择命名/动态范围。
真实世界场景:
我有一个 Excel 电子表格文件,我们称之为“ExcelFile1.xls”,它是从外部提供给我的(因此我无法真正更改其格式)。
1 个工作表/选项卡,我们称之为“Dynamic”,有一个我希望在 Access 中用作表格的数据范围,但它的列标题从第 14 行开始,一直到列埃尔。我希望 Access 将这个数据范围作为一个表格。此外,“ExcelFile1.xls”也将定期更新,即“ExcelFile.xls”文件的新版本将可用,但在第 14 行的列标题下方有更多数据,所以理想情况下我会就像 Access 一样,每当我覆盖以前版本的“ExcelFile1.xls”时,都会在这个范围内获取新数据。
我还有另一个 Excel 电子表格文件,我们称之为“ExcelFile2.xls”,再次由外部提供给我。
这有一个工作表/选项卡,我们称之为“Static”,它同样有一个我想要在 Access 中作为表格的数据范围,同样,会有更新版本的“ExcelFile2.xls”,它将覆盖我希望 Access 能够继续使用的以前的版本。这个范围是A14:O19
,并且永远是这个范围(即静态范围)。
总而言之:我想将 Access 链接到来自 2 个各自 Excel 文件的 2 个数据范围,以在 Access 中生成 2 个单独的表。源数据范围中的 1 个是动态的,另一个是静态的。如果可能的话,我希望 Access 通过使用完全相同的文件名和路径的新版本覆盖源 Excel 文件来获取新数据。
【问题讨论】:
【参考方案1】:好的,从这里关于这个问题的有用指针,以及我在其他地方提出的其他一些问题,我认为对于任何想要从 Excel 电子表格中提取数据作为动态范围或静态数据的人来说,我有一个相当简单的解决方案Excel 中的数据不在单元格 A1 中开始的范围。
这两个示例都使用按钮来启动代码。您显然不必这样做,但如果这样做,您需要创建一个表单和按钮,然后从按钮上运行代码生成器,并用下面您需要的任何解决方案替换该代码。
动态范围:
请注意,此动态范围示例假定您在 Excel 中的单元格范围始终从相同的最左上角位置开始,并且列数始终相同 - 即唯一动态的是底部单元格范围的行号。
您需要根据自己的设置换出的参考资料:
C:\Users\Matt\Desktop\ExcelFile1.xls
替换为您的 Excel 文件的完整路径
Dynamic
替换为您的 Excel 文件中包含的工作表的名称
A14:A2000
替换为您要测试的范围以查看有多少非空单元格。这个范围应该: 从列标题所在的数据行开始;覆盖您要导入的数据中永远不会有空单元格条目的列;覆盖的范围足够大,以至于它总是会超过 Excel 电子表格中包含实际数据的行数。
ExcelDynamicRangeData
替换为您想要在 Access 中调用包含从 Excel 范围中提取的数据的表。
Dynamic!A14:EL
替换为工作表名称、Excel 范围的最顶部/最左侧单元格引用和最右侧列字母。不要包含最底部/最右侧的行号,因为这是需要动态的,因此将其分配给 numberofrows
并稍后将其连接到此范围的末尾。
numberofrows = 13 ...
将 13 替换为列标题开始位置上方的行数。例如。如果您的列标题从第 4 行开始,则此数字需要为 3。
Command0
替换为用于启动所有此代码的按钮的名称。
Sub ImportDataFromRange()
' Assign the Excel Object
Dim excelapp As Object
Set excelapp = CreateObject("excel.application")
' Assign the workbook
Dim wb As Object
Set wb = excelapp.Workbooks.Open("C:\Users\Matt\Desktop\ExcelFile1.xls")
' Assign the result of your CountA function used in the next line
Dim numberofrows As Integer
' Get the bottom-most row number needed to complete our dynamic range address
numberofrows = 13 + excelapp.Application.CountA(wb.worksheets("Dynamic").Range("A14:A2000"))
' Delete any previous access table, otherwise the next line will add an additional table each time it is run
DoCmd.DeleteObject acTable, "ExcelDynamicRangeData"
' Import data from Excel using a range that now knows where bottom row number is
DoCmd.TransferSpreadsheet acLink, acSpreadsheetTypeExcel9, "ExcelDynamicRangeData", "C:\Users\Matt\Desktop\ExcelFile1.xls", True, "Dynamic!A14:EL" & numberofrows
' Close and clean
wb.Close
Set wb = Nothing
excelapp.Quit
Set excelapp = Nothing
End Sub
Private Sub Command0_Click()
ImportDataFromRange
End Sub
静态范围:
这要简单得多,因为无需打开 Excel 工作簿即可对数据应用 CountA
函数。
您需要根据自己的设置换出的参考资料:
C:\Users\Matt\Desktop\ExcelFile2.xls
替换为您的 Excel 文件的完整路径
ExcelStaticRangeData
替换为您想要在 Access 中调用包含从 Excel 范围中提取的数据的表。
Static!A14:EL20
替换为工作表的名称,以及要导入的 Excel 中单元格的完整范围地址。由于此方法描述了如何从 Excel 中获取 静态 范围的数据以访问 Excel 中的数据,因此您要导入的数据永远不应超出此范围。
Command0
替换为用于启动所有此代码的按钮的名称。
Sub ImportDataFromRange()
' Delete any previous access table, otherwise the next line will add an additional table
DoCmd.DeleteObject acTable, "ExcelStaticRangeData"
' Import data from Excel using a static range
DoCmd.TransferSpreadsheet acLink, acSpreadsheetTypeExcel9, "ExcelStaticRangeData", "C:\Users\Matt\Desktop\ExcelFile2.xls", True, "Static!A14:EL20"
End Sub
Private Sub Command0_Click()
ImportDataFromRange
End Sub
注意:
两种方法中的acSpreadsheetTypeExcel9
位指的是您正在导入的 Excel 文件的版本;在我的示例中,我正在导入 Excel 2000 格式;您可能正在导入不同版本的 Excel,因此请参阅 this 以查看您需要在代码中引用哪个版本; .xlsx 文件未列出,但应该是 acSpreadsheetTypeExcel12Xml
。
我的示例将数据作为源数据的活动链接引入 Access。如果您有大量数据,您可能会发现将数据实际导入并存储到 Access 中会更好,因为链接可能会导致一些性能问题。如果是这种情况,请将acLink
换成acImport
。
如果您尚未在 Access 中手动创建一个空白表(与您的代码中引用的相同表名),那么您要么需要这样做,要么第一次注释掉 DoCmd.DeleteObject acTable, "yourAccessTable"
代码运行,然后恢复这部分。
可能还有更多工作可以做 - 即,如果您的数据源具有不同数量的列,则调整 CountA 函数以考虑动态列数。
再次感谢 @david-zemens、@gord-thompson 以及其他 *** 用户帮助我实现这一目标 - 这对我和其他人都非常有用。
【讨论】:
【参考方案2】:我不是 Access 人,但让我给你一些应该能够帮助你的建议。
1 个工作表/选项卡,我们称之为“动态”,具有我想要的数据范围 在 Access 中以表格形式提供,但其列标题从行开始 14,穿过EL栏。我想要访问做的是拿起 这个数据范围作为一个表格。此外,“ExcelFile1.xls”还将 定期更新,即“ExcelFile.xls”的新版本 文件将可用,但在第 14 行的列下方有更多数据 标题,所以理想情况下我希望 Access 在 每当我覆盖以前版本的 “ExcelFile1.xls”。
好的,因此您需要在此工作表上建立一个动态命名范围。基本上,您创建一个公式来确定/调整范围的大小,只要向其中添加新数据。
有关如何创建动态命名范围的概述,请从这里开始:
http://support.microsoft.com/kb/830287
使用 VBA,最坏的情况是您可以访问此命名范围,将其内容读入数组变量或简单地遍历行/列,然后将这些内容写入您的 Access 表。但是,不是 Access 程序员,可能有一些更有效的方法来做到这一点。
这有一个工作表/选项卡,我们称之为“静态”,它同样有一个 我想要在 Access 中作为表的数据范围,并且再次,会有更新的 将覆盖以前版本的“ExcelFile2.xls”版本 理想情况下,我希望 Access 能够接受。这个范围是 A14:O19 并且永远是这个范围(即静态范围)。
您同样可以创建另一个命名范围,定义为=$A$14:$O$19
,这将是一个静态命名范围。然后,您可以像上面一样对待它。
编辑 这是获取 Excel 数据然后遍历行和列的示例,您只需添加代码以将字段/记录/等添加到 Access 中的表中。
Sub ImportDataFromRange()
'Access variables
Dim dbFile As Database
Dim tbl As TableDef, fld As Field
'Excel variables
Dim xlApp As Excel.Application
Dim xlFile As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlRange As Excel.Range
Dim r#, c#
Dim clVal As String 'string to hold cell's value, may need to modify this type.
Set dbFile = CurrentDb
'Use this to create a new table definition
' Set tbl = dbFile.CreateTableDef("Test")
'Use this if your table already exists:
Set tbl = dbFile.TableDefs("Test")
'Get the info from Excel:
Set xlApp = New Excel.Application
Set xlFile = xlApp.Workbooks.Open("C:\Users\david_zemens\desktop\Book1.xlsx")
Set xlSheet = xlFile.Sheets("Sheet1")
Set xlRange = xlSheet.Range("A1:B10")
For r = 1 To xlRange.Rows.Count
For c = 1 To xlRange.Columns.Count
'Add code to append new fields/records/etc to your table
Next c
Next r
xlApp.Quit
Set xlApp = Nothing
End Sub
希望这足以让您入门!
【讨论】:
谢谢大卫。我已经熟悉在 Excel 中创建动态范围,但像您一样,不太熟悉使用 Access VBA 将其引入 Access。也许其他阅读本文的人可以让我开始使用 VBA 语法,如果这是解决此问题的最佳方法。 @MattHall 我添加了一个示例,它可以完成所有操作但 构建表(因为我不知道该怎么做)。但它至少应该让您开始阅读 Excel 数据,并遍历行/列。然后你可以添加一些代码写到表中。 谢谢大卫。我假设Set xlRange = xlSheet.Range("A1:B10")
部分将接受我在 Excel 中指定的动态范围,即用 A1:B10
位替换我给出的动态范围名称?
@MattHall 我倾向于在 Access VBA 函数中使用此答案中的代码来“搜索”Excel 中的单元格范围并将该范围作为字符串返回。然后我会使用该字符串作为DoCmd.TransferSpreadsheet acLink, acSpreadsheetTypeExcel12Xml, "ExcelLinkedData", "C:\__tmp\Book1.xlsx", True, "Sheet1!B4:D6"
的最后一个参数。这将在 Access 中创建一个包含 Excel 数据的“链接表”。
我会将你的答案标记为@David-Zemmens,因为我相信比我更懂 VBA 的读者将能够弄清楚如何获取你的代码和@Gord-汤普森建议一起工作。我在其他地方问过another question,这可能会帮助我以更简单(对我而言)的方式获得我需要的东西。由于我需要传递给@Gord-Thompson 建议的参数的范围始终是相同的起始位置和相同的列数,所以我真正需要的是访问来确定有多少行,所以我可以传递类似@ 987654328@以上是关于将 Excel 中的动态和静态范围导入到 MS-Access 中,而不是从单元格 A1 开始的主要内容,如果未能解决你的问题,请参考以下文章
将多个 csv 文件中的数据导入一个 Excel 工作表并计算平均值
将超过 255 个字符从 excel 导入到 sql server(上一个问题 - 如何使用 ssis 将文本限定 CSV 动态加载到 sql server)