-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExcelDiffEngine.cs
More file actions
126 lines (110 loc) · 4.98 KB
/
Copy pathExcelDiffEngine.cs
File metadata and controls
126 lines (110 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System;
using System.Collections.Generic;
using System.Threading;
namespace eWorkhelper
{
/// <summary>
/// 参考 diff-excel 的纯托管坐标比较器。
/// 不持有 Excel COM、WinForms 或 Ribbon 对象。
/// </summary>
internal sealed class ExcelDiffEngine
{
internal ExcelDiffResult Compare(ExcelSheetData baseline, ExcelSheetData candidate)
{
return Compare(baseline, candidate, CancellationToken.None, null);
}
internal ExcelDiffResult Compare(ExcelSheetData baseline, ExcelSheetData candidate, CancellationToken cancellationToken, Action<long> progress)
{
if (baseline == null)
{
throw new ArgumentNullException("baseline");
}
if (candidate == null)
{
throw new ArgumentNullException("candidate");
}
int rowCount = Math.Max(baseline.Rows.Count, candidate.Rows.Count);
int maxColumnCount = 0;
IList<ExcelDiffCell> differences = new List<ExcelDiffCell>();
IList<ExcelDiffRow> rows = new List<ExcelDiffRow>();
long processed = 0;
for (int row = 0; row < rowCount; row++)
{
cancellationToken.ThrowIfCancellationRequested();
int baselineColumnCount = GetColumnCount(baseline, row);
int candidateColumnCount = GetColumnCount(candidate, row);
int columnCount = Math.Max(baselineColumnCount, candidateColumnCount);
maxColumnCount = Math.Max(maxColumnCount, columnCount);
int rowDifferenceCount = 0;
bool baselineHasContent = RowHasContent(baseline, row, cancellationToken);
bool candidateHasContent = RowHasContent(candidate, row, cancellationToken);
for (int column = 0; column < columnCount; column++)
{
if ((column & 255) == 0) cancellationToken.ThrowIfCancellationRequested();
ExcelCellValue baselineValue = baseline.GetCell(row, column);
ExcelCellValue candidateValue = candidate.GetCell(row, column);
processed++;
if (progress != null && (processed & 255) == 0) progress(processed);
if (string.Equals(
baselineValue.ComparisonText,
candidateValue.ComparisonText,
StringComparison.Ordinal))
{
continue;
}
differences.Add(new ExcelDiffCell(
new ExcelCellCoordinate(row + 1, column + 1),
baselineValue,
candidateValue,
GetDiffKind(baselineValue, candidateValue)));
rowDifferenceCount++;
}
ExcelDiffRowStatus status = ExcelDiffRowStatus.Unchanged;
if (!baselineHasContent && candidateHasContent) status = ExcelDiffRowStatus.Added;
else if (baselineHasContent && !candidateHasContent) status = ExcelDiffRowStatus.Deleted;
else if (baselineHasContent && candidateHasContent && rowDifferenceCount > 0) status = ExcelDiffRowStatus.Changed;
if (status != ExcelDiffRowStatus.Unchanged)
rows.Add(new ExcelDiffRow(row + 1, status, rowDifferenceCount));
}
return new ExcelDiffResult(
baseline.SheetName,
candidate.SheetName,
rowCount,
maxColumnCount,
differences,
rows);
}
private static bool RowHasContent(ExcelSheetData sheet, int row, CancellationToken cancellationToken)
{
int columnCount = GetColumnCount(sheet, row);
for (int column = 0; column < columnCount; column++)
{
if ((column & 255) == 0) cancellationToken.ThrowIfCancellationRequested();
if (!string.IsNullOrEmpty(sheet.GetCell(row, column).ComparisonText)) return true;
}
return false;
}
private static int GetColumnCount(ExcelSheetData sheet, int row)
{
if (row < 0 || row >= sheet.Rows.Count || sheet.Rows[row] == null)
{
return 0;
}
return sheet.Rows[row].Count;
}
private static ExcelDiffKind GetDiffKind(ExcelCellValue baseline, ExcelCellValue candidate)
{
bool baselineEmpty = string.IsNullOrEmpty(baseline.ComparisonText);
bool candidateEmpty = string.IsNullOrEmpty(candidate.ComparisonText);
if (baselineEmpty && !candidateEmpty)
{
return ExcelDiffKind.Added;
}
if (!baselineEmpty && candidateEmpty)
{
return ExcelDiffKind.Removed;
}
return ExcelDiffKind.Changed;
}
}
}