如何合并Excel中具有相同列的两个表?


11

在Excel中,我有一个电子表格,可以将SQL数据库中的数据提取到表中,然后根据该数据生成报告。不幸的是,此SQL数据库中的数据不完整,我想在结果集中包括其他手动输入到电子表格中的行。

尽我所能,我不能只是手动将这些多余的行插入表中,因为每当Excel从SQL数据库中提取新数据时,它们都会被删除。因此,相反,我正在考虑在新工作表上创建具有相同列标题的单独表并在其中输入数据,然后在另一工作表上创建第三个表,该表以某种方式合并了从SQL和SQL Server提取数据的表中的行。我手动输入数据的表格。我该怎么做?(或者,是否有一种更好的方法使我不知所措?)


例:

Table 1 (From Database):

  | Person | Week Of | Task | Hours |
  | Bob    | 1/6/13  | Foo  | 12    |
  | Mary   | 1/6/13  | Foo  | 7     |
  | Mary   | 1/6/13  | Bar  | 5     |
  | John   | 1/6/13  | Foo  | 5     |
  | John   | 1/13/13 | Foo  | 13    |

--

Table 2 (Entered Manually): 
  | Person | Week Of | Task | Hours |
  | Bob    | 1/6/13  | Baz  | 3     |
  | Mary   | 1/6/13  | Baz  | 2     |
  | John   | 1/13/13 | Baz  | 5     |

--

Result:
  | Person | Week Of | Task | Hours |
  | Bob    | 1/6/13  | Foo  | 12    |
  | Mary   | 1/6/13  | Foo  | 7     |
  | Mary   | 1/6/13  | Bar  | 5     |
  | John   | 1/6/13  | Foo  | 5     |
  | John   | 1/13/13 | Foo  | 13    |
  | Bob    | 1/6/13  | Baz  | 3     |
  | Mary   | 1/6/13  | Baz  | 2     |
  | John   | 1/13/13 | Baz  | 5     |

如果您手动添加的数据低于SQL数据,可以吗?还是必须按日期对它们进行排序。Excel不会覆盖现有SQL数据行正下方的行。但是,如果必须对两种数据类型都进行排序,则整个过程会更加复杂。
nixda 2013年

好吧,我希望对它们进行排序,但这不是完全必要的。重要的是,我能够使用数据透视表和其他excel工具来分析整个数据集(包括手动和自动填充的表)。我还需要能够继续从SQL自动提取新数据。
Ajedi32

这种行为会解决吗?在第一个查询之后和第二个查询之后。当然,当您打开工作簿时,Excel会自动更新您的SQL。
nixda 2013年

我猜那行得通。我宁愿将数据放在单个表中,以便可以进行过滤,排序等操作,但是就像我之前所说的那样,这并不是完全必要的。
Ajedi32

也许我们会为您的排序问题找到解决方案。但是第一步,只需在新工作簿中第一次查询您的SQL。之后,在其下方添加您的手动输入。现在用第二个(和更大的)查询进行测试。它们不会被覆盖。这是一种标准行为。没什么特别的事。
nixda 2013年

Answers:


2

这是一个没有VBA的纯Excel解决方案。它通过使用INDEX函数来逐步降低SQL数据的行和跨列,直到值用尽并导致错误情况为止。IFERROR函数捕获错误,并使用第二个INDEX函数逐步降低手动输入数据的行和跨列,直到这些值用尽并导致错误情况为止。第二个IFERROR函数捕获错误并返回破折号(“-”)。(必须通过功能区刷新SQL数据,公式才能产生正确的结果。)

使用以下公式为Sheet1中的SQL数据创建一个动态的命名范围SQLDB:

=OFFSET(Sheet1!$A$2,0,0,COUNTA(Sheet1!$A:$A)-1,COUNTA(Sheet1!$1:$1))

使用以下公式为在Sheet2中手动输入的数据创建第二个动态命名范围EXCELRNG:

=OFFSET(Sheet2!$A$1,1,0,COUNTA(Sheet2!$A:$A)-1,COUNTA(Sheet2!$1:$1))

这两个命名范围均假定在两个工作表的每行的第1行中输入了变量名。

在Sheet3的第1行中输入变量名称(从单元格A1开始)。

在Sheet3的单元格A2中输入以下公式:

=IFERROR(INDEX(SQLDB,ROWS(A$2:A2),COLUMN(A2)),IFERROR(INDEX(EXCELRNG,ROWS(A$2:A2)-ROWS(SQLDB),COLUMN(A2)),"-"))

公式复制到变量名列中,然后在各行中向下复制,直到公式的结果全部为破折号(“-”)。

下一步可以在另一个工作表中创建数据透视表以进行分析和组织。

同样,第一步将是创建一个动态的命名范围,例如RESULTRNG,在名称管理器输入框中为该命名范围插入以下公式:

=OFFSET(Sheet3!$A$1,0,0,COUNTA(Sheet1!$A:$A)+COUNTA(Sheet2!$A:$A)-1,COUNTA(Sheet1!$1:$1))

然后在新工作表中创建数据透视表,将RESULTRNG设置为要分析的表。这将滤除Sheet3中公式表中的所有尾部破折号。

之所以可行,是因为RESULTRNG公式会计算Sheet1和Sheet2中的总行数(不包括Sheet2中的标题)和Sheet1中的总列数,并根据这些计数设置其范围,但不包括任何尾随行中的任何破折号( (或列)在Sheet3公式表中。


如果我以这种方式进行操作,尽管合并表不必一定是固定大小的吗?而且,如果使表大于所需的大小,那么如果我尝试使数据透视表能够处理组合表中的数据,这不会让我感到困惑吗?(因为表中的某些值是'-'字符?)还是有办法解决这些问题?
Ajedi32

(顺便说一句,我通常更喜欢像这样的纯Excel解决方案,因为它们不需要用户在开始工作之前就启用宏。)
Ajedi32 2013年

这将需要一些手动维护,以确保公式捕获了两个表中的所有数据。为了避免破折号,您只需要将公式复制到它们返回数据的位置,而不是破折号。
chuff

是否可以创建另一个命名范围,使其仅包含合并表中非空白(用'-'字符填充)的行?这样,我只需设置数据透视表即可从该范围获取数据,而不必担心破折号。
Ajedi32

我已经扩展了答案,以解释如何创建不包含破折号的数据透视表。尝试放置“无破折号”表只会将破折号问题转移到另一张纸上,在破折号单元格中使用#N / A,除非每次更改源数据中的行数时都要手动调整新表的大小。
chuff

5

我找到了一种方法。这种解决方案有些棘手,它要求两个表都具有自己的单独工作表(上面没有其他内容),但除此之外,它几乎可以完全满足我的要求。(这里似乎还有很多潜力可以进行更复杂的操作,例如联接。)

转到功能区上的“数据”选项卡,单击“来自其他来源”,然后单击“来自Microsoft Query”。然后单击“ Excel文件”,选择当前正在使用的文件,然后单击“确定”。然后,单击“取消”,当系统提示您是否要继续在Microsoft Query中进行编辑时,单击“是”。在这里,您可以单击SQL按钮,然后在电子表格中的任何工作表上编写自定义SQL查询。就我而言:

SELECT *
FROM `'Sheet1$'` `'Sheet1$'`
UNION ALL
SELECT *
FROM `'Sheet2$'` `'Sheet2$'`

注意:对我来说,此方法在我关闭文件并再次打开后会停止工作。无论如何,我都会在这里发布它,以防万一这只是我的计算机出现问题或其他人可以使它正常工作。


1
连接两个不同的工作簿可以正常工作。那正是我所需要的。谢谢!
daVe 2015年

这种方法对我来说非常有效。执行查询,然后简单地复制数据并将其复制到excel中。但是,请务必注意,它将从数据中删除所有重复的行,我希望您不要介意我对此编辑内容进行一点编辑。
Some_Guy

加上因为这实际上是我的事,几乎用它来将一堆销售数据合并到1个电子表格中,然后再制作数据透视表以获取总计,而如果多次出售相同数量的产品,我会遇到一些错误被错过了。
Some_Guy

@Some_Guy只需使用UNION ALL。
Ajedi32 '16

3

如果您对VBA解决方案感兴趣,那么我可以进行以下工作:

  • 为要从SQL Server提取的数据设置动态命名范围。打开名称管理器,输入新名称(例如“ SQLDB”),然后在“引用至”输入框中复制以下公式。我假设您导入的数据在Sheet1中:

    =OFFSET(Sheet1!$A$1,0,0,COUNTA(Sheet1!$A:$A),COUNTA(Sheet1!$1:$1))
    
  • 为输入手动数据的范围设置另一个命名范围。我使用了EXCELRNG这个名字,并假设它在Sheet2中。命名范围从第2行开始,以排除标题行。此处的公式与第一个公式相同,不同之处在于它所涉及的工作表:

    =OFFSET(Sheet2!$A$1,1,0,COUNTA(Sheet2!$A:$A)-1,COUNTA(Sheet2!$1:$1))
    
  • 这是我用于连接到SQL表的第一组设置。通过在功能区上的“数据”选项卡中选择“连接”,可以访问该对话框。禁用后台刷新可确保VBA宏暂停,直到完成Excel工作表中的数据刷新为止。在工作表打开时可能不需要刷新连接,但是我想确保在运行宏之前进行任何身份验证。

连接设置

  • 这是第二组设置。这些可以在“数据”选项卡的“属性”部分中找到(在导入的SQL表中选择一个单元格时)。尽管我选择了“为新数据插入整个行,删除未使用的单元格”选项,但是使用“插入单元格...”选项实际上并没有遇到任何麻烦。

连接属性

  • 最后,这是VBA代码。若要将其插入,请在“开发人员”选项卡下选择“ Visual Basic”。在左侧列表中突出显示工作表名称。它将被称为“ VBA项目(工作表名称)。然后在屏幕顶部的菜单栏中选择“插入模块”,然后将代码粘贴到新模块中。请注意,我将合并表放在Sheet3中。宏不会对新表进行排序,尽管添加起来并不难。

    Sub StackTables()
    
       Dim Rng1 As Range, Rng2 As Range
    
       Set Rng1 = ThisWorkbook.Names("SQLDB").RefersToRange
       Set Rng2 = ThisWorkbook.Names("EXCELRNG").RefersToRange
    
       ' refresh the SQL table
       ThisWorkbook.Connections(1).Refresh
    
       ' clear the consolidated table range  
       Sheet3.Cells.ClearContents
    
       ' copy the SQL data into the consolidation range
       Rng1.Copy
       Sheet3.Range("A1").PasteSpecial xlPasteValues
    
       'copy the manually entered data into the consolidate range
       Rng2.Copy
       Sheet3.Range("A1").Offset(Rng1.Rows.Count, 0).PasteSpecial xlPasteValues
       Application.CutCopyMode = False
    
       Sheets("Sheet3").Activate
       ActiveSheet.Range("A1").Select
    
    End Sub
    

这看起来是一个非常可靠的解决方案。我确实有几个问题。是什么触发了这个宏?它在刷新数据连接时自动运行,还是必须按一个单独的按钮才能手动运行它?其次,这适用于表格吗?(不仅是未格式化为表格的范围)如果是这种情况,表格本身不能处理排序吗?(不是像您建议的那样,而是由VBA宏进行排序?)
Ajedi32

1
就目前而言,您可以通过从“开发人员”选项卡中选择“宏”,然后选择并运行该宏来运行宏。两种选择:将其分配给功能区上的自定义按钮,然后使用它来运行它。或将其作为宏代码嵌入到Worksheet_Activate事件中。只要您选择合并表,就会运行它。它将与可以进行排序的表一起使用。但是,我不确定添加数据时表是否会自动求助。
chuff

3

这是@chuff的 “ Pure Excel”解决方案的一个版本,专门用于处理表。(IE,您要合并的两个数据源是表。)

此方法与他的回答中发布的一个方法之间的主要区别在于,您无需为要合并的两个数据集定义命名范围,因为它们是表并且已经具有自己的命名范围。因此,继续命名您的第一个表Table1和第二个表Table2

现在,在新工作表的左上角创建一个新表,并为其指定与其他两个表相同的列名。然后在刚创建的工作表的单元格A2中输入以下公式:

=IFERROR(INDEX(Table1,ROWS(A$2:A2),COLUMN(A2)), IFERROR(INDEX(Table2,ROWS(A$2:A2)-ROWS(Table1),COLUMN(A2)), "-"))

接下来,将该公式复制到所有表列中,然后向下复制行,直到公式的结果全部为破折号(“-”)。注意:对这个新表进行排序不会做任何事情,因为每个单元格的内容实际上是相同的(它们都包含相同的公式)。

如果合并表中的列在显示空白单元格时显示为0,则可以使用替代函数将公式包装在该列中,如下所示:

=SUBSTITUTE(<old expression here>, 0, "")

如果要创建使用该新表中数据的数据透视表,则必须创建一个命名范围。首先,为表格命名Table3。现在,转到“公式”选项卡,然后单击“定义名称”。给引用命名,并为其值输入以下方程式(“引用”):

=OFFSET(Table3[#All],0,0,ROWS(Table1)+ROWS(Table2)+1)

然后,您可以将此命名引用用作数据透视表的范围。


0

如果您只想一次性获得结果,则可以使用一个网站为您合并两个表:https : //office-tools.online/table/merge/

您将表粘贴到网页中,然后选择相关参数。这是内置示例的屏幕快照,指示如何使用它:

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.