将数据从一个工作表复制到另一个工作簿(同一工作簿),具有相同的列名(不一定是相同的顺序)

时间:2015-04-01 19:44:38

标签: vba excel-vba worksheet excel

我在名为“Data”的工作表上有两列Data1Data。我在名为“MasterData”的工作表上有相同的列名。我想阅读“Data”工作表中的内容,并根据列名称MasterData& Data)复制到“Data1”。另外,假设我将10个数据点复制到“MasterData”,下次我想将数据保存在那里,但是将新数据从工作表“Data”复制到“{{1通过检查特定列中的第一个空单元格(在本例中为单元格编号11)。这需要继续,因为“MasterData”将存储所有历史数据。

MasterData

1 个答案:

答案 0 :(得分:0)

这对Stack Overflow来说不是一个好问题。这个网站是供程序员互相帮助开发的。你的问题读作:“我想要一个宏来做到这一点。写给我听。“不是一种流行的问题风格。

在此页面的右上角,您会看到一个“帮助”按钮。你会发现很多好的,但一般的建议。在这个答案中,我将尝试提供更具体的建议。

您必须学习VBA的基础知识。你本可以用很少的知识自己回答这个问题。花在学习上的几个小时很快就会得到回报。在网上搜索“Excel VBA教程”。有很多可供选择。尝试一些并完成最接近您学习风格的那个。我更喜欢书。我参观了一个好的图书馆;回顾了他们的Excel VBA入门;在购买我认为最好的永久参考书之前,借用了最有希望在家尝试的人。

这个网站不是一个提出设计问题的好地方。你需要按照它的小步骤打破你的要求。这里有很多问题和答案,可以解决您的总要求的各个步骤,但据我所知,并非符合您的完整要求。

您通常可以通过思考如何手动解决此问题来创建简单的设计:

  1. 在工作表主数据列中找到最后使用的单元格。调用最后一个使用过的单元格下面的单元格:Target。
  2. 在工作表数据的数据列中找到最后使用的单元格。
  3. 从第一个数据单元格中选择到最后一个单元格。
  4. 将选区复制到单元格Target。
  5. 对列Data1重复上述步骤。
  6. VBA语句相当于步骤1到4.您可以选择并复制为VBA中的单独步骤,但这不是一个好习惯;有一个VBA语句将它们组合起来更快更整洁。

    有几个VBA语句允许您使用不同的参数重复(循环)代码块,以实现稍微不同的效果。

    这看起来不是很容易吗?我们有一系列简单的步骤,而不是模糊的描述。我希望任何教程都能解释如何在前几页中执行这些步骤。在我的代码中,我使用了一些可能不在教程开头的技术。我解释了为什么我使用它们。有关其他信息,请搜索“Excel VBA函数数组”或“Excel VBA常量”或类似内容。如有必要,请回答问题,但是你自己发现的越多,你的发展就越快。

    欢迎来到编程的乐趣。

    Option Explicit
    
      ' * I have a system of naming my variabls that I have used for years. I can
      '   look at macros I wrote years ago and immediately know what all the
      '   variables. I am not asking you to like my system but to develop your own
      '   system.
      ' * My naming system using a sequence of words that get more and precise
      '   until I have a unique name.  The first word what the variable is being
      '   used for. "Col" means its associated with columns of a worksheet or a
      '   two-dimensional array. If I have multiple worksheets and/or arrays, the
      '   next word identifies whch worksheet or array.  If I have multiple
      '   columns, the next word identifies which column.
      ' * Constants make code easier to read and easiest to maintain. Instead of a
      '   literal, such as 2, you have a meaningful name, ColDataData.  Columns
      '   can be identified by code or number: A=1, B=2, C=3 and so on. I have used
      '   numbers which I normally find more convenient although I could have used
      '   codes here.
    
      Const ColDataData As Long = 2
      Const ColDataData1 As Long = 4
      Const ColMasterData As Long = 1
      Const ColMasterData1 As Long = 2
      Const RowDataFirstData As Long = 2  ' Adjust according to how many header
                                          ' rows you have in worksheet "Data"
    
    Sub AddToMasterColumn()
    
      Dim ColDataCrnt As Long
      Dim ColMasterCrnt As Long
      Dim ColsData() As Variant
      Dim ColsMaster() As Variant
      Dim InxCols As Long
      Dim Rng As Range
      Dim RowDataLast As Long
      Dim RowMasterTgt As Long
      Dim WshtData As Worksheet
      Dim WshtMaster As Worksheet
    
      ' * Processing for your two sets of columns is the same so we can use a loop
      '   with parameters so says which pair of columns each loop is to handle.
      ' * Array() is a convenient way to load an array although the array must be
      '   variant.  Since I am loading different data types (String and Long) to
      '   the same array, this is required anyway.
      ' * These two arrays MUST have the same number of elements.
      ColsData = Array(ColDataData, ColDataData1)
      ColsMaster = Array(ColMasterData, ColMasterData1)
    
      ' Debug.Assert is a convenient way of testing for program errors during
      ' development. If UBound(ColsData) and UBound(ColsMaster) are not equal,
      ' execution will stop here.
      Debug.Assert UBound(ColsData) = UBound(ColsMaster)
    
      ' I could have used Worksheets("Data") where ever I use WshtData below.
      ' Using WshtData is slightly faster and, in my view, neater. If you change
      ' names of one of the worksheets, one change here will fix the macro.
      Set WshtData = Worksheets("Data")
      Set WshtMaster = Worksheets("MasterData")
    
      For InxCols = LBound(ColsData) To UBound(ColsData)
    
        With WshtMaster
          ' Get the destination column in worksheet Master for the current loop
          ColMasterCrnt = ColsMaster(InxCols)
          ' Find the last used row in ColMasterCrnt and add one to it to get the target cell
          RowMasterTgt = .Cells(Rows.Count, ColMasterCrnt).End(xlUp).Row + 1
        End With
    
        With WshtData
          ' Get the source column in worksheet data for the current loop
          ColDataCrnt = ColsData(InxCols)
          ' Find the last used row in ColDataCrnt
          RowDataLast = .Cells(Rows.Count, ColDataCrnt).End(xlUp).Row
          ' Specify the range to be copied
          Set Rng = .Range(.Cells(RowDataFirstData, ColDataCrnt), .Cells(RowDataLast, ColDataCrnt))
        End With
    
        ' Copy data
        Rng.Copy Destination:=WshtMaster.Cells(RowMasterTgt, ColMasterCrnt)
    
      Next
    
    End Sub
    

    Additon以响应额外要求

    我相信Function FindColumnByName()可以满足您的所有要求。我有更复杂的变化,如果有必要我可以提供。例如,我有一个搜索多行标题的变体。但是,让我们开始吧。

    您需要删除:

    Const ColDataData As Long = 2
    Const ColDataData1 As Long = 4
    Const ColMasterData As Long = 1
    Const ColMasterData1 As Long = 2
    

    并添加到AddToMasterColumn的顶部:

    Dim ColDataData As Long:
    Dim ColDataData1 As Long
    Dim ColMasterData As Long
    Dim ColMasterData1 As Long
    

    并在设置WshtData和WshtMaster之后添加:

    ColDataData = FindColumnByName(WshtData, “Data”)
    ColDataData1 = FindColumnByName(WshtData, “Data1”)
    ColMasterData = FindColumnByName(WshtMaster, “Data”)
    ColMasterData1 = FindColumnByName(WshtMaster, “Data2”)
    

    测试例程TestFCBN显示了在开发的这个阶段可能有用或可能令人困惑的技术。快速浏览,但如果您对它有任何困难,请稍后再忽略它。使用我的测试工作表,它输出:

    Column 2 of worksheet Data is named Data
    Column 4 of worksheet Data is named Data1
    There is no column named X in worksheet Data
    Column 1 of worksheet MasterData is named Data
    Column 2 of worksheet MasterData is named Data1 
    

    新代码:

    Sub TestFCBN()
    
      Dim ColName As String
      Dim ColTgt As Long
      Dim InxTV As Long
      Dim TestValues As Variant
      Dim WshtName As String
    
      TestValues = Array("Data", "Data", "Data", "Data1", "Data", "X", _
                         "MasterData", "Data", "MasterData", "Data1")
      ' There must be an even number of values in TestValues.  The first of each
      ' pair is the name of a worksheet, the second the name of a column in that
      ' worksheet.
    
      For InxTV = LBound(TestValues) To UBound(TestValues) Step 2
    
        WshtName = TestValues(InxTV)
        ColName = TestValues(InxTV + 1)
        ColTgt = FindColumnByName(Worksheets(WshtName), ColName)
        If ColTgt = 0 Then
          Debug.Print "There is no column named " & ColName & " in worksheet " & WshtName
        Else
          Debug.Print "Column " & ColTgt & " of worksheet " & WshtName & _
                      " is named " & ColName
        End If
    
      Next
    
    End Sub
    Function FindColumnByName(Wsht As Worksheet, ColName As String) As Long
    
      ' This function scans row 1 for a cell with a value of ColName.
      ' If found, it returns the number of that column.
      ' If not found, it returns 0
    
      Dim ColCrnt As Long
      Dim ColLast As Long
    
      With Wsht
        ColLast = .Cells(1, Columns.Count).End(xlToLeft).Column
        For ColCrnt = 1 To ColLast
          If .Cells(1, ColCrnt).Value = ColName Then
            FindColumnByName = ColCrnt
            Exit Function
          End If
        Next
      End With
    
      FindColumnByName = 0
    
    End Function