我在Windows 7中使用Excel 2013.
我在Excel中创建了一个用户窗体,使用Excel中的VBA将数据从Access导入到Excel中,然后点击每个onlinepclearning(点)com / append-and-delete-ms-access-record-sets-from-一个-Excel的用户窗体/。这个网站是他修改Import子程序的地方。
点击“导入”按钮后,Access中的数据应显示在userform的列表框中。数据不会直接导入到用户窗体中,而是导入到工作表中并作为工作表中的命名范围引用(称为DataAccess,其命名范围公式为:OFFSET(导入!$ A $ 1,1,,COUNTA(导入!$) A $ 2:$ A $ 10000),7) - 用户表格中我们从Access到Excel运送的表格有7个字段。
Excel中用户窗体的屏幕截图:
当我单击userform上的“导入”按钮时,我得到“错误380:无法设置RowSource属性”。无效的属性值'。是否存在命名范围或列表框的问题?我看了很多,但没有答案。
我也尝试过改变:
(1)更新1 8/5/2016 - 我已经从DataAccess周围删除了引号而没有引用Sheet2!以便Sub ImportUserForm()中的一行代码读取
Me.lstDataAccess.RowSource = DataAccess
我现在不会收到任何错误信息,但是msgbox说数据已被导入;但是,数据仅出现在OFFSET /命名范围引用的电子表格(Sheet2!aka Import!)上,而不是我的列表框中。
其他教程说设置列宽(我设置为40 pt; 40pt等等...总共7次)和列数(我设置为7)
Excel中的userform上的列表框中仍然没有数据显示。
以下是列表框的代码,名为lstDataAccess以及初始化userform的代码。我不知道为什么他们这样做了双击(不知道这意味着什么)b / c他在教程中所做的就是点击导入按钮,Access表中的所有数据都将导入到Excel用户表单
(Arec1-7是用户窗体上文本框的名称,对应于Access中的字段名称 - 姓氏,名字,地址等)
(lstDataAccess是userform上列表框的名称。)
Private Sub lstDataAccess_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
'dim the variables
Dim i As Integer
'find the selected list item
i = Me.lstDataAccess.ListIndex
Me.lstDataAccess.Selected(i) = True
'add the values to the text boxes
Me.Arec1.Value = Me.lstDataAccess.Column(0, i)
Me.Arec2.Value = Me.lstDataAccess.Column(1, i)
Me.Arec3.Value = Me.lstDataAccess.Column(2, i)
Me.Arec4.Value = Me.lstDataAccess.Column(3, i)
Me.Arec5.Value = Me.lstDataAccess.Column(4, i)
Me.Arec6.Value = Me.lstDataAccess.Column(5, i)
Me.Arec7.Value = Me.lstDataAccess.Column(6, i)
End Sub
Private Sub UserForm_Initialize()
'does not get assigned to any button
Me.Arec1 = Sheet1.Range("J3").Value
End Sub
(同样,所有这些代码都在userform中,而不是教程电子表格部分的模块。)
(1)END OF UPDATE 1 8/5/2016 - (我将在下面的答案中尝试Private Sub Import_Click(),但是没有其他代码可以我看到这将适用于该项目的导入部分。其余的是关闭,打开用户窗体,然后追加和删除数据,但我需要先将数据导入列表框,然后才能解决追加/删除问题。)< / p>
(2)UPDATE 8/5/2016 - 为了清楚起见,我已将整个代码替换为Sub ImportUserForm()的代码。
我只能添加两个链接b / c我需要根据论坛规则获得10个声誉,但我已经添加了命名范围的范围和用户表单的镜头。数据从Access表导入Sheet2!根据指定范围内的OFFSET公式的电子表格,将其添加到A2并超过7列所有原因,如果需要,可以降至A10000。它目前看起来像这样:
单元格A1:ID |细胞B2:姓氏|单元格C3:FirstName |单元格D4:地址| Cell E5:电话| Cell F6:手机| Cell G7:电子邮件
它的包装但是标题遍历Excel中的7列,数据从第2行(A2到G2)开始,一直到第7行b / c我在Access中只有7行数据。 / p>
(3)2016年8月6日更新以下是从Google文档下载文件的链接。请参阅下面的注释b / c它半工作但我想在名称mgr中使用OFFSET函数而不是我现在使用绝对范围的修复。
-Excel wkbk和userform - (我不允许包含更多链接,请参阅下文)https(冒号)// docs(dot)google(dot)com / spreadsheets / d / 1tRF3bJf4ng-bM6Kiefptpbrw9jr4T_BGZ0gKm9S9614 / edit ?USP =共享 (只需单击Export wksht上的按钮,单击Userform,激活userform。我不需要任何工作表上的任何其他按钮的帮助,包括Import wksht上的Import按钮。)
-Access DB with PhoneList table - https(冒号)// drive(dot)google(dot)com / file / d / 0B9IyKJSJ52ghNEFfYVNWUE1wcEU / view?usp = sharing
如何工作:我想导入的原因是b / c我需要查看追加/删除按钮是否适用于用户窗体。您应该能够将Access表PhoneList中的数据导入到Excel userform的列表框中,它实际导入到Import wksht并通过命名范围DataAccess反映到列表框中。然后,您应该能够从列表框中选择一行导入数据,它将显示在上面的文本框中,以便您可以根据需要更改数据,然后将表附加到Access中,或者您只需通过以下方法删除数据行:添加或删除按钮。
请注意:用户窗体上的导入现在会将数据导入到用户窗体上的列表框中,但仅在我关闭并打开用户窗体后。我应该可以单击“导入”按钮,即使其旁边的搜索框中没有任何内容,也可以从Access数据库导入所有数据。您必须从导入工作表中删除数据以清除用户窗体上的数据并重新开始。
我转到了用户窗体列表框的属性并更改了:
列数为7
列宽为40 pt
多选到1-fmmultiselectmulti
要导入的RowSource!DataAccess(我相信这是一个很大的关键)
以上工作我必须更改DataAccess命名范围并使其成为绝对范围并删除OFFSET函数。 (顺便说一句,带有OFFSET的命名范围不会出现在范围选择器框中,所以现在它出现在范围选择器中)。名为mgEP的名称mgr中的命名范围是使用OFFSET函数的DataAccess的旧命名范围。如果可以的话,我想用这个。
我尝试使用Private Sub FillListBoxFromOffsetRange()但收到错误
arr.Data = Application.Range(&#34; DataAccess&#34;)
突出显示为黄色。我也尝试从我的ImportUserForm代码中调用它,但它没有工作(也许我做错了),但互联网说你需要从第二个模块调用私有子。我放弃了尝试,并开始在上面的第1步工作并取得半成功,但仍然需要帮助。
END OF UPDATE 8/6/2016
(以下是原帖的延续)
P.S。在将新代码添加到用户窗体之前,我没有双击我的表单上的“导入”按钮,但我没有使用其他按钮,并且它适用于用户窗体。此外,我将代码添加到userform而不是模块(这是我们用来通过Excel工作表上的某些按钮导入和导出btw Access和Excel)。
我是VBA和userforms的新手。以下是他对网站的更正以及摘录代码:
提前谢谢
(1)UPDATE 2 8/5/2016 - 我在下面添加了Sub ImportUserForm()的完整代码。
'Import button click event
Private Sub cmdImport_Click()
ImportUserForm
'Inform the user that the macro was executed successfully.
MsgBox "Congratulation the data has been successfully Imported",
vbInformation, "Import successful"
End Sub
_____
Sub ImportUserForm()
'we are not importing the data directly into user form but importing onto
'the worksheet and referencing _
'it as a named range in the user form
'he made a slight change to the code per his Append and Delete webpage b/c
'once we delete and append data we want to import back into _
'list box again to show new values have been removed or appended
'Declaring the necessary variables.
Dim cnn As ADODB.Connection 'dim the ADO collection class
Dim rs As ADODB.Recordset 'dim the ADO recordset class
Dim dbPath As String
Dim SQL As String
Dim i As Integer
Dim var
'add error handling
On Error GoTo errHandler:
'Disable screen flickering.
Application.ScreenUpdating = False
'clear the values from the worksheet
Sheet2.Range("A2:G10000").ClearContents
'get the path to the database
dbPath = Sheet1.Range("I3").Value
'set the search variable
var = Me.txtSearch
Set cnn = New ADODB.Connection ' Initialise the collection class variable
'Connection class is equipped with a —method— named Open
'—-4 aguments—- ConnectionString, UserID, Password, Options
'ConnectionString formula—-Key1=Value1;Key2=Value2;Key_n=Value_n;
cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath
'Create the SQL statement to retrieve the data from table.
If CheckBox1 = True Then
SQL = "SELECT * FROM PhoneList WHERE SURNAME = '" & var & "'"
Else
SQL = "SELECT * FROM PhoneList WHERE SURNAME LIKE '" & var & "%" & "'"
End If
'Create the ADODB recordset object.
Set rs = New ADODB.Recordset 'assign memory to the recordset
'ConnectionString Open '—-5 aguments—-
'Source, ActiveConnection, CursorType, LockType, Options
rs.Open SQL, cnn
'Check if the recordset is empty. 'EOF is end of file
If rs.EOF And rs.BOF Then
'Close the recordet and the connection.
rs.Close
cnn.Close
'clear memory
Set rs = Nothing
Set cnn = Nothing
'Enable the screen.
Application.ScreenUpdating = True
'In case of an empty recordset display an error.
'DataAccess is a named range in the worksheet _
'OFFSET(Import!$A$1,1,,COUNTA(Import!$A$2:$A$10000),7)
MsgBox "There are no records in the recordset!", vbCritical, "No Records"
Me.lstDataAccess.RowSource = ""
Exit Sub
End If
'Write the reocrdset values in the sheet.
Sheet2.Range("A2").CopyFromRecordset rs
'Close the recordset and the connection.
rs.Close
cnn.Close
'clear memory
Set rs = Nothing
Set cnn = Nothing
'Enable the screen.
Application.ScreenUpdating = True
Me.lstDataAccess.RowSource = DataAccess
'Me.lstDataAccess.ColumnCount =
Sheets("Import").Range("DataAccess").Columns.Count
'error handler
On Error GoTo 0
Exit Sub
errHandler:
'clear memory
Set rs = Nothing
Set cnn = Nothing
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure
Import_Data"
End Sub
答案 0 :(得分:4)
我们一直在为所有细节背后隐藏的答案打我们的脑袋。这是你的范围定义问题。
即使您正在使用命名范围 - 如果查看名称管理器中的值,也可以立即看到问题。他们没有定义。
同样,如果使用VBA运行命名范围,则可以立即看到问题。 VBA没有看到Offset函数返回一个范围 - 它返回一个范围的引用 - 格式实际上是一个Variant数组。
在测试功能中,您可以通过向[DataAccess]
添加手表来查看您的范围。它是一个二维Variant数组。
所以简单的答案是:
您无法直接将RowSource设置为使用偏移功能的命名范围
可能有办法将变量数组转换为实数范围,但您不能将此类型的范围名称视为真实范围。
只需尝试使用Debug.Print Range("DataAccess").Cells.Address
或向Range("DataAccess")
添加监视,它就会出现与其他引用单元格的基本范围名称不同的错误。
您可以通过将范围名称包装在方括号中来访问此类型的范围值。 [DataAccess]
编辑 - 您可以使用OFFSET范围填充ListBox,方法是在结果数组上使用AddItem方法。
我仍然相信你的OFFSET公式有问题,因为从我的测试中你最终只得到数组中的1个填充列。
但是 - 如果没有确认您的列表框属性,查看数据的屏幕截图,查看实际的记录集字段,或者填写电子表格的代码(而不是&#34;等等等等等),它就是&#39难以测试甚至猜测。
但是此代码将根据使用OFFSET函数的Range名称填充ListBox:
将.Rowsource = DataAccess
替换为FillListBoxFromOffsetRange
将此代码添加到UserForm模块
Private Sub FillListBoxFromOffsetRange()
Dim arrData As Variant
Dim intRow As Integer
Dim intCol As Integer
Dim strRowData As String
With ListBox1
.Clear 'Make sure the Listbox is empty
.ColumnCount = 7 'Set number of columns
' In order to access Workbook ranges need to use Application Object
arrData = Application.Range("DataAccess")
For intRow = LBound(arrData, 1) To UBound(arrData, 1)
' Process first column of new row
intCol = 1
strRowData = arrData(intRow, intCol)
.AddItem strRowData ' Add the first Column of the row
' Append remaining columns to end of row
For intCol = LBound(arrData, 2) + 1 To UBound(arrData, 2)
strRowData = arrData(intRow, intCol)
' List rows have zero-based index
.List(intRow - 1, intCol) = strRowData
Next intCol
Next intRow
End With
End Sub
没问题 - 按预期工作 - 您的数据 - 模拟用户形式
我所做的更改都是完全按照我的建议使用我的上述功能,并注明了您的代码
FillListBoxFromOffsetRange
'Me.lstDataAccess.RowSource = DataAccess
'Me.lstDataAccess.ColumnCount =
'Sheets("Import").Range("DataAccess").Columns.Count
并更改With ListBox1
以匹配实际的列表框名称With lstDataAccess
结果: