简体   繁体   English

VBA-Excel从不同位置的不同工作表获取相同的数据

[英]VBA - Excel Getting same data from different sheets at different positions

I want to make a macro that will open all excel books in a folder, read the filled information and store them in a sheet which will represent my database. 我想创建一个宏,该宏将打开一个文件夹中的所有excel书籍,读取填充的信息并将它们存储在代表我的数据库的工作表中。 I need to know your suggestions and what is the best way to do that, to get a fast and flexible result. 我需要了解您的建议,以及做到这一点的最佳方法是什么,以获得快速而灵活的结果。

To help you understand my question, let us suppose that I have 3 excel templates containing First Name, Last Name and Country, but at different positions like these pictures 为了帮助您理解我的问题,让我们假设我有3个excel模板,其中包含名字,姓氏和国家/地区,但这些图片的位置不同

Template 1 范本1 模板1

Template 2 范本2 模板2

Template 3 范本3 模板3

Based on that, the final result that I would like to get is : 基于此,我想得到的最终结果是: 结果

The exemple that I am giving by these pictures is really very simple, but it was just to help you understand what I want. 这些图片提供的示例确实非常简单,但这只是为了帮助您了解我想要的。 Now I will detail about the real need. 现在,我将详细介绍真正的需求。 In fact, I have 3 templates, but each of them contains about 80 fields of data to collect (not only first name, last name and country). 实际上,我有3个模板,但是每个模板都包含大约80个数据字段(不只是名字,姓氏和国家)。 And i don't have to read only 3 files, but I have to read about 200 files placed in a folder and each of them is either template1, or 2 or 3. In the future we may have a template 4 that's why I need something flexible. 而且我不必只读取3个文件,但是我必须读取放置在一个文件夹中的大约200个文件,每个文件要么是template1,要么是2或3。将来我们可能会有一个模板4,这就是为什么我需要一些灵活的东西。

I thought about named ranges, but the template 1,2,3 already exists, and I can't collect from the 200 users the 200 existing excels files, and before launching my macro, giving a named range to the 80 field at each file. 我考虑过命名范围,但是模板1,2,3已经存在,我无法从200个用户中收集200个现有的excel文件,并且在启动宏之前,无法给每个文件的80个字段指定命名范围。 I can use named range if in the future they will be a template 4, so before sending the files to the final user who will fill the excel we name the ranges and send it to him, but before the template 4,i have to fix the problem of the current 3 existing templates. 我可以使用命名范围,如果将来它们将是模板4,那么在将文件发送给将填充Excel的最终用户之前,我们先将范围命名并发送给他,但是在模板4之前,我必须修复当前3个现有模板的问题。

I also thought about reading data based on columns and row indexes,for exemple I check the type of file and if I am reading a file template one, I get first name from the cell (2,3), and If it's a template 2, i get the information from cell (5,6) and if it's a template 3, i get the information from Cel (9,4), but the problem is that my code will not be at all flexible. 我还考虑过基于列和行索引读取数据,例如,我检查文件的类型,如果正在读取文件模板,则从单元格(2,3)中获得名字,如果它是模板2 ,我从单元格(5,6)获得信息,如果它是模板3,我从Cel(9,4)获得信息,但是问题是我的代码根本不灵活。

I also said, I may do like a sheet called reference, in which I define the positions of each field based on the template model, for example I say that the first name is for template 1 at the position 2,3 for the template 2, first name is at 5,6 and for template3 it's at 9,4. 我也说过,我可能会像称为参考的工作表那样工作,在该工作表中,我根据模板模型定义每个字段的位置,例如,我说名字是模板1的名称,位于模板2的位置2,3处。 ,名字是5,6,而template3的名字是9,4。 Like the following picture, and when I loop through my 200 files, I check, if it's template 1 i read the sheet of reference and I know that the first name will be at this position, same for template 2 and so on....this solution looks like previous one, but more flexible, because all we have to change is the reference table if something changes, but I am wondering if it will be fast or slow if for each field i have to come read 2 cells in the reference sheet to know the position. 如下图所示,当我遍历我的200个文件时,我检查了是否是模板1我已阅读参考表,并且知道名字将在此位置,与模板2相同,依此类推... 。此解决方案看起来像上一个解决方案,但是更灵活,因为如果有任何更改,我们要做的就是更改参考表,但是我想知道如果对于每个字段我都必须读取2个单元格,它是快速还是慢速?参考表了解位置。 工作表参考

I am really lost because I have to choose the best way to do what I want before start coding to avoid time wasting. 我真的迷失了,因为在开始编码之前,我必须选择最佳方法来完成自己想要的事情,以避免浪费时间。 If any expert can help by telling me what is best or giving me more ideas than what I thought about I will really appreciate. 如果有专家可以告诉我什么是最好的,或者给我更多的想法,而不是我的想法,我将不胜感激。

Thanks in advance to any helper 在此先感谢任何帮助者

EDIT: @PEH, what do you think about if I make my lookup table like that ? 编辑:@PEH,如果我像这样制作查找表,您会怎么想? 在此处输入图片说明

EDIT2: @PEH, that's what is suggested in last comment EDIT2:@PEH,这就是最近的评论中所建议的 在此处输入图片说明

The basic idea (beside looping through your files): 基本思想(除了遍历文件之外):

  1. Change your lookup data into the following: 将您的查找数据更改为以下内容:

    在此处输入图片说明

  2. Then read Cells(1, 6) to get your model. 然后阅读Cells(1, 6)获得模型。

     Dim Model As String Model = Worksheets("MyTemplate").Cells(1, 6).Value 
  3. Use the WorksheetFunction.Match method to find your field in the lookup table. 使用WorksheetFunction.Match方法在查找表中查找您的字段。

     Dim FieldRow As Long FieldRow = Application.WorksheetFunction.Match(Model & "-First name", Worksheets("LookupTable").Range("A:A"), 0) 
  4. Use … 采用 …

     fRow = Worksheets("LookupTable").Cells(FieldRow, 2) fColumn = Worksheets("LookupTable").Cells(FieldRow, 3) 

    To get row and column where to look for that field in your template. 获取行和列的位置,以在模板中查找该字段。

If you put the field lookup stuff into a handy function, the code would get easier to maintain. 如果将字段查找内容放入方便的函数中,则代码将更易于维护。 For example put the following into a module: 例如,将以下内容放入模块中:

Option Explicit

Public LookupCache As Variant
Public LookupResults As Variant

Public Function ReadField(Ws As Worksheet, FieldName As String) As Variant
    'Here we cache the lookup table. It reads the sheet LookupTable into an 
    'array if the array does not exist yet. If the function runs a second time,
    'the array exists already and is used directly (saves time).
    'Lookup in arrays is much faster than in cells.
    'Caching makes this function about 2 times faster than without.
    If IsEmpty(LookupCache) Or IsEmpty(LookupResults) Then
        With ThisWorkbook.Worksheets("LookupTable")
            Dim LastLookupRow As Long
            LastLookupRow = .Cells(.Rows.Count, "A").End(xlUp).Row
            LookupCache = .Range("A2", "A" & LastLookupRow).Value
            LookupResults = .Range("B2", "C" & LastLookupRow).Value
        End With
    End If

    Dim ModelName As String
    ModelName = Ws.Cells(1, 6).Value

    Dim LookupRow As Long
    On Error Resume Next
    LookupRow = Application.WorksheetFunction.Match(ModelName & "-" & FieldName, LookupCache, 0)
    On Error GoTo 0

    If LookupRow = 0 Then
        'field not found
        ReadField = CVErr(xlErrNA)
        Exit Function
    End If

    Dim fRow As Long, fColumn As Long
    fRow = LookupResults(LookupRow, 1)
    fColumn = LookupResults(LookupRow, 2)

    ReadField = Ws.Cells(fRow, fColumn).Value
End Function

So you could read a field like 所以你可以读一个像

Debug.Print ReadField(MyLoopWorkbook.Worksheets("MyTemplate"), "First name")
'MyLoopWorkbook should be the current workbook in your files loop

Edit according to the comment … 根据评论进行编辑...

If we added a new field Company to a new model4,a user must go to the sheet lookuptable and add Model4-Company at line 11 with the row and col, but also in the code he has to go and add ReadField(MyLoopWorkbook.Worksheets("MyNewTemplate"), "Company") , right? 如果我们增加了一个新的领域Company到一个新的model4,用户必须到片LookupTable中,并添加Model4-Company在与ROW和COL线11条,而且在他去,并添加代码ReadField(MyLoopWorkbook.Worksheets("MyNewTemplate"), "Company") ,对吗? That's why I am not understanding how I can count only on persons who don't code to add that? 这就是为什么我不理解如何只能依靠那些不编写代码的人的原因? Can you clarify please because what you said is really important. 您能否请您澄清一下,因为您的发言确实很重要。

If you make the ReadField part dynamic you don't need to code here too. 如果使ReadField部分动态化,则也不需要在此处编写代码。 For example if you want to end up with a table like that: 例如,如果要结束一个像这样的表:

在此处输入图片说明

You would just add a new header in column 4 called like the field eg Company . 您只需在第4列中添加一个新标题即可,例如Company And write a loop that loops throug the columns of that header row to collect all fields. 并编写一个循环遍历该标题行的列以收集所有字段的循环。

Sub ReadAllFields()
    Dim wsData As Worksheet
    Set wsData = Worksheets("CollectedData")

    Dim FreeRow As Long 'find next free row in table
    FreeRow = wsData.Cells(wsData.Rows.Count, "A").End(xlUp).Row + 1

    Dim Fields() As Variant 'read headers into array
    Fields = wsData.Range("A1", wsData.Cells(1, wsData.Columns.Count).End(xlToLeft)).Value

    Dim iCol As Long
    For iCol = 1 To UBound(Fields, 2) 'loop through header columns
        wsData.Cells(FreeRow, iCol).Value = ReadField(MyLoopWorkbook.Worksheets("MyNewTemplate"), Fields(1, iCol)) 
        'reads fields dynamically depending on which headers exist in data sheet
    Next iCol
End Sub

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 VBA-从不同的工作表获取具有相同标题的数据 - VBA - getting data that has same header from different sheets 如何动态复制Excel VBA中两个不同工作表中的数据? - How to copy data from two different sheets in excel VBA dynamically? Excel VBA-链接来自不同工作表的行 - Excel VBA - link rows from different sheets 在Excel中将2个不同的工作表与相同的数据合并 - Combine 2 different sheets with same data in Excel VBA代码用于在同一Excel工作簿中使用来自两个不同工作表的更新来填充MI电子表格 - VBA Code to populate an MI spreadsheet with updates from two different sheets in the same Excel workbook 通过比较 Excel VBA 中两个不同工作表的 ID 来获取数据时出现问题。 给出不正确的数据 - Issue while fetching data by comparing IDs from two different sheets in Excel VBA. Gives incorrect data 用于从oracle获取数据到excel的代码,并将具有相同单元名称的数据发送到excel中的不同工作表 - Code to fetch data from oracle to excel and send the data which has same cell name to different sheets in excel 从相同的 Excel 文件但在不同的工作表上迭代读取 Excel - Reading from Excel iteratively from same excel file but on different sheets 如何从工作簿中的不同工作表中获取宏拉数据。 Excel VBA - How do I make macro pull data from different sheets within a workbook. Excel VBA 如何将 excel 中 2 个不同工作表的值与 VBA 匹配 - How to match values from 2 different sheets in excel with VBA
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM