我被困在一个公式上。基本上我想要做的是根据从另一张纸上提取的数据,计算特定值在一张纸上出现的次数。
E.g。我有三张床单。一张工作表包含一个作业列表和一个与客户端关联的代码。第二张表有客户端列表和客户端的详细信息。第三张是我的结果表。
我想计算每家公司的How Heards。例如,在下面的表1中,Apple有3个客户。如果我们使用客户代码ID并转到表2,我们可以看到它将共有2个在线和0个Facebook。此结果显示在工作表3上。结果表。
第1页示例
第2页示例
工作表3示例(我希望结果从计算中看起来如何)
答案 0 :(得分:2)
为了真正为这个问题提供合适的答案,这里有一些VBA代码允许工作簿创建与自身的ADO连接并使用SELECT,DISTINCT,WHERE,INNER JOIN,GROUP BY和ORDER生成报告BY条款。
Sub Inner_Join()
Dim cnx As Object, rs As Object
Dim sWS1 As String, sWS2 As String, sWB As String, sCNX As String, sSQL As String
Dim ws1TBLaddr As String, ws2TBLaddr As String
'Collect some string literals that will be used to build SQL
ws1TBLaddr = Worksheets("Sheet1").Cells(1, 1).CurrentRegion.Address(0, 0)
sWS1 = Worksheets("Sheet1").Name
ws2TBLaddr = Worksheets("Sheet2").Cells(1, 1).CurrentRegion.Address(0, 0)
sWS2 = Worksheets("Sheet2").Name
sWB = ThisWorkbook.FullName
'Build the connection string
'The first is for 64-bit Office; the second is more universal
sCNX = "Provider=Microsoft.Jet.OLEDB.12.0;Data Source=" & sWB _
& ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
sCNX = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sWB _
& ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
'Debug.Print sCNX
'Create the necessary ADO objects
Set cnx = CreateObject("ADODB.Connection") 'late binding; for early binding add
Set rs = CreateObject("ADODB.Recordset") 'Microsoft AxtiveX Data Objects 6.1 library
'Open the connection to itself
cnx.Open sCNX
With Worksheets("Sheet3")
'Clear the reporting area
.Cells(1, 1).CurrentRegion.ClearContents
'get [Business Name] list from Sheet1
sSQL = "SELECT DISTINCT w1.[Business Name]"
sSQL = sSQL & " FROM [" & sWS1 & "$" & ws1TBLaddr & "] w1"
sSQL = sSQL & " ORDER BY w1.[Business Name]"
'Debug.Print sSQL
'Populate Sheet3!A:A
rs.Open sSQL, cnx
Do While Not rs.EOF
'Debug.Print rs.Fields("Business Name")
.Cells(.Rows.Count, 1).End(xlUp).Offset(1, 0) = rs.Fields("Business Name")
rs.MoveNext
Loop
rs.Close
'get [How Heard] list from Sheet2
sSQL = "SELECT DISTINCT w2.[How Heard]"
sSQL = sSQL & " FROM [" & sWS2 & "$" & ws2TBLaddr & "] w2"
sSQL = sSQL & " WHERE w2.[How Heard] NOT LIKE 'None'"
sSQL = sSQL & " ORDER BY w2.[How Heard]"
'Debug.Print sSQL
'Populate Sheet3!1:1
rs.Open sSQL, cnx
Do While Not rs.EOF
'Debug.Print rs.Fields("How Heard")
.Cells(1, .Columns.Count).End(xlToLeft).Offset(0, 1) = rs.Fields("How Heard")
rs.MoveNext
Loop
rs.Close
'start by seeding zeroes for all
With .Cells(1, 1).CurrentRegion
With .Resize(.Rows.Count - 1, .Columns.Count - 1).Offset(1, 1)
.Cells = 0
End With
End With
'get the counts for the [Business Name]×[How Heard] combinations
sSQL = "SELECT COUNT(w1.[Business Name]), w1.[Business Name], w2.[How Heard]"
sSQL = sSQL & " FROM [" & sWS1 & "$" & ws1TBLaddr & "] w1"
sSQL = sSQL & " INNER JOIN [" & sWS2 & "$" & ws2TBLaddr & "] w2 ON w1.[Client Code] = w2.[Client Code]"
sSQL = sSQL & " WHERE w2.[How Heard] <> 'None'"
sSQL = sSQL & " GROUP BY w1.[Business Name], w2.[How Heard]"
'Debug.Print sSQL
'Populate Sheet3 data matrix area
rs.Open sSQL, cnx
With .Cells(1, 1).CurrentRegion
Do While Not rs.EOF
'Debug.Print rs.Fields(0) & ":" & rs.Fields(1) & ":" & rs.Fields(2)
.Cells(Application.Match(rs.Fields(1), .Columns(1), 0), _
Application.Match(rs.Fields(2), .Rows(1), 0)) = rs.Fields(0)
rs.MoveNext
Loop
End With
rs.Close
End With
Final_Cleanup:
Set rs = Nothing
cnx.Close: Set cnx = Nothing
End Sub
结果应类似于以下内容。
答案 1 :(得分:2)
好的,所以我对@Jeeped的回答印象非常深刻 我的答案不像使用任意SQL那样灵活,但它没有使用VBA,所以它在某些情况下也可能有用。
基本上我的回答是:
从Sheet1创建一个数组,其中包含每个匹配单元格的客户端代码
(或非匹配单元格的0)
X = ((Sheet1!$B$2:$B$1000=$A2)*Sheet1!$A$2:$A$1000)
从Sheet2创建一个数组,其中包含每个匹配单元格的客户端代码
(或非匹配单元格的0)
Y = ((Sheet2!$B$2:$B$2000=B$1)*Sheet2!$A$2:$A$2000)
比较两个数组中的每个单元格,其中第一个数组的值不是&lt; t 0 0
Z = (X<>0)*(X=TRANSPOSE(Y))
然后总结匹配数量:
=SUM(Z)
因此,Sheet3!B2的最终公式为:
=SUM((((Sheet1!$B$2:$B$1000=$A2)*Sheet1!$A$2:$A$1000)<>0)*(((Sheet1!$B$2:$B$1000=$A2)*Sheet1!$A$2:$A$1000)=TRANSPOSE(((Sheet2!$B$2:$B$2000=B$1)*Sheet2!$A$2:$A$2000))))
这是一个数组公式,因此您需要按Control-Shift-Enter而不是Enter。然后你需要将它从B2复制到C2,B3等等。
显然,您必须将1000更改为大于Sheet1上的最大rwo,将2000更改为大于Sheet2上最大行的内容。