Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 根据用户定义的变量路径从关闭的工作簿复制数据_Vba_Excel_Excel 2007_Xlm - Fatal编程技术网

Vba 根据用户定义的变量路径从关闭的工作簿复制数据

Vba 根据用户定义的变量路径从关闭的工作簿复制数据,vba,excel,excel-2007,xlm,Vba,Excel,Excel 2007,Xlm,我已经用尽了我的搜索能力来寻找解决方案。以下是我想做的事情的概要: 用户打开启用宏的Excel文件 立即提示用户输入或选择所需工作簿的文件路径。他们需要选择两个文件,并且文件名可能不一致 输入文件位置后,第一个文件选择的第一个工作表将复制到启用宏的工作簿的第一个工作表,第二个文件选择的第一个工作表将复制到启用宏的工作簿的第二个工作表 我遇到过一些关于ADO的引用,但我还不太熟悉 编辑:我找到了一个从关闭的文件导入数据的代码。我需要调整范围以返回变量结果 Private Functio

我已经用尽了我的搜索能力来寻找解决方案。以下是我想做的事情的概要:

  • 用户打开启用宏的Excel文件
  • 立即提示用户输入或选择所需工作簿的文件路径。他们需要选择两个文件,并且文件名可能不一致
  • 输入文件位置后,第一个文件选择的第一个工作表将复制到启用宏的工作簿的第一个工作表,第二个文件选择的第一个工作表将复制到启用宏的工作簿的第二个工作表
我遇到过一些关于ADO的引用,但我还不太熟悉

编辑:我找到了一个从关闭的文件导入数据的代码。我需要调整范围以返回变量结果

    Private Function GetValue(path, file, sheet, ref)

    path = "C:\Users\crathbun\Desktop"
    file = "test.xlsx"
    sheet = "Sheet1"
    ref = "A1:R30"

     '   Retrieves a value from a closed workbook
    Dim arg As String

     '   Make sure the file exists
    If Right(path, 1) <> "\" Then path = path & "\"
    If Dir(path & file) = "" Then
        GetValue = "File Not Found"
        Exit Function
    End If

     '   Create the argument
    arg = "'" & path & "[" & file & "]" & sheet & "'!" & _
    Range(ref).Range("A1").Address(, , xlR1C1)

     '   Execute an XLM macro
    GetValue = ExecuteExcel4Macro(arg)
End Function

Sub TestGetValue()

    path = "C:\Users\crathbun\Desktop"
    file = "test"
    sheet = "Sheet1"

    Application.ScreenUpdating = False
    For r = 1 To 30
        For C = 1 To 18
            a = Cells(r, C).Address
            Cells(r, C) = GetValue(path, file, sheet, a)
        Next C
    Next r

    Application.ScreenUpdating = True
End Sub
私有函数GetValue(路径、文件、工作表、参考)
path=“C:\Users\crathbun\Desktop”
file=“test.xlsx”
sheet=“Sheet1”
ref=“A1:R30”
'从关闭的工作簿中检索值
作为字符串的Dim arg
'确保该文件存在
如果正确(路径,1)“\”则路径=路径&“\”
如果Dir(路径和文件)=“”,则
GetValue=“未找到文件”
退出功能
如果结束
'创建参数
arg=“”&path&“[”&file&“]”&sheet&“!”&_
范围(参考)。范围(“A1”)。地址(,xlR1C1)
'执行XLM宏
GetValue=ExecuteExcel4Macro(arg)
端函数
子TestGetValue()
path=“C:\Users\crathbun\Desktop”
file=“test”
sheet=“Sheet1”
Application.ScreenUpdating=False
对于r=1到30
对于C=1到18
a=单元(r,C).地址
单元格(r,C)=GetValue(路径、文件、工作表、a)
下一个C
下一个r
Application.ScreenUpdating=True
端接头

现在,我需要一个命令按钮或userform,它将立即提示用户定义文件路径,并从该文件导入数据。

下面的函数从关闭的Excel文件读取数据,并以数组形式返回结果。它会丢失格式、公式等。您可能希望在主代码中调用isArrayEmpty函数(位于底部),以测试该函数是否返回了某些内容

Public Function getDataFromClosedExcelFile(parExcelFileName As String, parSheetName As String) As Variant
'see http://www.ozgrid.com/forum/showthread.php?t=19559
'returns an array (1 to nRows, 1 to nCols) which should be tested with isArrayEmpty in the calling function

  Dim locConnection As New ADODB.Connection
  Dim locRst As New ADODB.Recordset
  Dim locConnectionString As String
  Dim locQuery As String
  Dim locCols As Variant
  Dim locResult As Variant
  Dim i As Long
  Dim j As Long

  On Error GoTo error_handler

  locConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _
  & "Data Source=" & parExcelFileName & ";" _
  & "Extended Properties=""Excel 8.0;HDR=YES"";"

  locQuery = "SELECT * FROM [" & parSheetName & "$]"

  locConnection.Open ConnectionString:=locConnectionString
  locRst.Open Source:=locQuery, ActiveConnection:=locConnection
  If locRst.EOF Then 'Empty sheet or only one row
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ''''''         FIX: an empty sheet returns "F1"
    ''''''         http://support.microsoft.com/kb/318373
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    If locRst.Fields.Count = 1 And locRst.Fields(0).Name = "F1" Then Exit Function 'Empty sheet
    ReDim locResult(1 To 1, 1 To locRst.Fields.Count) As Variant
    For i = 1 To locRst.Fields.Count
      locResult(1, i) = locRst.Fields(i - 1).Name
    Next i
  Else
    locCols = locRst.GetRows
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ''''''         FIX: an empty sheet returns "F1"
    ''''''         http://support.microsoft.com/kb/318373
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    If locRst.Fields.Count = 1 And locRst.Fields(0).Name = "F1" And UBound(locCols, 2) = 0 And locCols(0, 0) = "" Then Exit Function 'Empty sheet

    ReDim locResult(1 To UBound(locCols, 2) + 2, 1 To UBound(locCols, 1) + 1) As Variant

    If locRst.Fields.Count <> UBound(locCols, 1) + 1 Then Exit Function 'Not supposed to happen

    For j = 1 To UBound(locResult, 2)
      locResult(1, j) = locRst.Fields(j - 1).Name
    Next j
    For i = 2 To UBound(locResult, 1)
      For j = 1 To UBound(locResult, 2)
        locResult(i, j) = locCols(j - 1, i - 2)
      Next j
    Next i
  End If

  locRst.Close
  locConnection.Close
  Set locRst = Nothing
  Set locConnection = Nothing

  getDataFromClosedExcelFile = locResult

  Exit Function
error_handler:
  'Wrong file name, sheet name, or other errors...
  'Errors (#N/A, etc) on the sheet should be replaced by Null but should not raise an error
  If locRst.State = ADODB.adStateOpen Then locRst.Close
  If locConnection.State = ADODB.adStateOpen Then locConnection.Close
  Set locRst = Nothing
  Set locConnection = Nothing

End Function

Public Function isArrayEmpty(parArray As Variant) As Boolean
'Returns false if not an array or dynamic array that has not been initialised (ReDim) or has been erased (Erase)

  If IsArray(parArray) = False Then isArrayEmpty = True
  On Error Resume Next
  If UBound(parArray) < LBound(parArray) Then isArrayEmpty = True: Exit Function Else: isArrayEmpty = False

End Function

我不介意在这个过程中打开文件。我只是不希望用户必须单独打开文件。我只需要他们能够选择或导航到所需的文件

下面是一个基本代码。此代码要求用户选择两个文件,然后将相关工作表导入当前工作簿。我有两个选择。你挑吧:)

经过尝试和测试

选项1(直接导入图纸,而不是复制到图纸1和2中)

选项2(将工作表内容导入工作表1和2中)


您已经构建了一些代码了吗?你被困在哪里?@JMax-我添加了目前可用的代码。这并不多,我甚至不确定我是否朝着正确的方向前进。@user955289:你有什么理由不想打开这两个文件吗?使用工作簿从这些文件导入工作表的代码简单明了。open()我不介意在导入过程中是否打开这些文件。我只是不希望用户必须单独打开文件。我只需要他们能够选择或导航到所需的文件。@user955289:几分钟后发布代码……哇!这太完美了。我已经尝试了两种选择,并且很可能会使用第二种选择。非常感谢你!!我登录只是为了感谢你并向你致意,悉达思·劳特。你的这段代码是一件真正的艺术品。我一直在寻找这样的代码很长时间了。很高兴我找到了它。从现在起,我的电子表格将采用完全不同的方法。感谢您分享这一惊人的知识。:)谢谢你的邀请。我想暂时远离ADO,直到我能够进一步研究它。当我更熟悉ADO时,我将保留此作为参考。您还可以使用range对象上的
CopyFromRecordset
方法将记录集转储到工作表中。
Sub test()

  Dim data As Variant

  data = getDataFromClosedExcelFile("myFile.xls", "Sheet1")
  If Not isArrayEmpty(data) Then
    'Copies content on active sheet
    ActiveSheet.Cells(1,1).Resize(UBound(data,1), UBound(data,2)) = data
  End If

End Sub
Option Explicit

Sub Sample()
    Dim wb1 As Workbook, wb2 As Workbook
    Dim Ret1, Ret2

    Set wb1 = ActiveWorkbook

    '~~> Get the first File
    Ret1 = Application.GetOpenFilename("Excel Files (*.xls*), *.xls*", _
    , "Please select first file")
    If Ret1 = False Then Exit Sub

    '~~> Get the 2nd File
    Ret2 = Application.GetOpenFilename("Excel Files (*.xls*), *.xls*", _
    , "Please select Second file")
    If Ret2 = False Then Exit Sub

    Set wb2 = Workbooks.Open(Ret1)
    wb2.Sheets(1).Copy Before:=wb1.Sheets(1)
    ActiveSheet.Name = "Blah Blah 1"
    wb2.Close SaveChanges:=False

    Set wb2 = Workbooks.Open(Ret2)
    wb2.Sheets(1).Copy After:=wb1.Sheets(1)
    ActiveSheet.Name = "Blah Blah 2"
    wb2.Close SaveChanges:=False

    Set wb2 = Nothing
    Set wb1 = Nothing
End Sub
Option Explicit

Sub Sample()
    Dim wb1 As Workbook, wb2 As Workbook
    Dim Ret1, Ret2

    Set wb1 = ActiveWorkbook

    '~~> Get the first File
    Ret1 = Application.GetOpenFilename("Excel Files (*.xls*), *.xls*", _
    , "Please select first file")
    If Ret1 = False Then Exit Sub

    '~~> Get the 2nd File
    Ret2 = Application.GetOpenFilename("Excel Files (*.xls*), *.xls*", _
    , "Please select Second file")
    If Ret2 = False Then Exit Sub

    Set wb2 = Workbooks.Open(Ret1)
    wb2.Sheets(1).Cells.Copy wb1.Sheets(1).Cells
    wb2.Close SaveChanges:=False

    Set wb2 = Workbooks.Open(Ret2)
    wb2.Sheets(1).Cells.Copy wb1.Sheets(2).Cells
    wb2.Close SaveChanges:=False

    Set wb2 = Nothing
    Set wb1 = Nothing
End Sub