如何查找两列之间的匹配值和不匹配值,并按以下方式设置其格式?
输入:
| expected | match | forward | backward | actual |
|----------|-------|---------|----------|--------|
| a | | | | b |
| b | | | | c |
| c | | | | r |
| d | | | | s |
| e | | | | |
输出:
| expected | match | forward | backward | actual |
|----------|-------|---------|----------|--------|
| a | b | a | r | b |
| b | c | d | s | c |
| c | | e | | r |
| d | | | | s |
| e | | | | |
forward
-存在于expected
中,但没有出现在actual
(SQL left outer join
)
backward
-存在于actual
中,但没有出现在expected
(SQL right outer join
)
match
-在expected
和actual
(SQL inner join
)中都出现
expected
是我从SQL
查询中获得的。在RDBMS中没有actual
列的情况下,我有很多情况,因此我必须使用excel进行比较。我通常可以使用VLOOKUP
进行比较,但是这很耗时,并且没有提供我想要的格式。我想要一种可以重要使用上述格式进行操作的解决方案。
我愿意提出建议。我个人使用python / pandas来执行此操作,但是我的同事不习惯使用python,因此我更喜欢一种解决方案,该解决方案可以通过单击按钮来完成,或者通过VBA自动化,或者通过Excel来实现,基本上可以我可以与我的Excel同事共享,这可以使他们的流程更快。目前,他们对所有三列都执行VLOOKUP->Filter->Copy->Paste to another sheet
漂洗重复操作。
提供了一个解决方案-https://superuser.com/a/1417235/954024,但是它运行非常缓慢且效率低下,我的系统只使用了该方法:(
我的python解决方案:
import pandas as pd
import sys
def find_discrepancies(input_file):
"""
input: df
output: formatted df
"""
df = pd.read_excel(input_file)
df['match'] = df.loc[df['expected'].isin(df['actual'])].reset_index()[
'expected']
df['forward'] = df.loc[df['expected'].isin(
df['actual']) == False].reset_index()['expected']
df['backward'] = df.loc[df['actual'].isin(
df['expected']) == False].reset_index()['actual']
df = df[['expected', 'match', 'forward', 'backward', 'actual']]
counts = df.count()
df.columns = [df.columns[i].capitalize() + ' - ' + str(counts.values[i]) for i in range(5)]
df.fillna('', inplace=True)
return df
def main(inputFile, outputFile):
df = find_discrepancies(inputFile)
df.to_excel(outputFile, index=False)
if __name__ == '__main__':
inputFile = sys.argv[1]
outputFile = sys.argv[2]
main(inputFile, outputFile)
答案 0 :(得分:1)
这不是最干净的解决方案,但这足够了。我将需要更多有关您的数据设置的信息以进行配置。
Option Explicit
Sub PopulateColumns()
Dim i As Long, lastrow As Long
Dim testitem As String
For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
testitem = Cells(i, 1).Value
If Application.CountIf(Range("E:E"), testitem) = 0 Then
lastrow = Cells(Rows.Count, 3).End(xlUp).Row
Cells(lastrow + 1, 3).Value = testitem
ElseIf Application.CountIf(Range("E:E"), testitem) > 0 Then
lastrow = Cells(Rows.Count, 2).End(xlUp).Row
Cells(lastrow + 1, 2).Value = testitem
End If
Next i
For i = 2 To Cells(Rows.Count, 5).End(xlUp).Row
testitem = Cells(i, 5).Value
If Application.CountIf(Range("A:A"), testitem) = 0 Then
lastrow = Cells(Rows.Count, 4).End(xlUp).Row
Cells(lastrow + 1, 4).Value = testitem
End If
Next i
Cells(1, 1).Value = "Expected - " & Cells(Rows.Count, 1).End(xlUp).Row - 1
Cells(1, 2).Value = "Match - " & Cells(Rows.Count, 2).End(xlUp).Row - 1
Cells(1, 3).Value = "Forward - " & Cells(Rows.Count, 3).End(xlUp).Row - 1
Cells(1, 4).Value = "Backward - " & Cells(Rows.Count, 4).End(xlUp).Row - 1
Cells(1, 5).Value = "Actual - " & Cells(Rows.Count, 5).End(xlUp).Row - 1
Columns("A:E").AutoFit
For i = 1 To 5
Cells(1, i).Interior.Color = RGB(168, 207, 141)
Cells(1, i).Font.Bold = True
Cells(1, i).HorizontalAlignment = xlCenter
Cells(1, i).Borders.LineStyle = xlContinuous
Next i
End Sub