public static ExcelSheetDiff Diff(ExcelSheet src, ExcelSheet dst, ExcelSheetDiffConfig config) { var srcColumns = src.CreateColumns(); var dstColumns = dst.CreateColumns(); var columnStatusMap = CreateColumnStatusMap(srcColumns, dstColumns, config); var option = new DiffOption <ExcelRow>(); option.EqualityComparer = new RowComparer(new HashSet <int>(columnStatusMap.Where(i => i.Value != ExcelColumnStatus.None).Select(i => i.Key))); foreach (var row in src.Rows.Values) { var shifted = new List <ExcelCell>(); var index = 0; var queue = new Queue <ExcelCell>(row.Cells); while (queue.Any()) { if (columnStatusMap[index] == ExcelColumnStatus.Inserted) { shifted.Add(new ExcelCell(string.Empty, 0, 0)); } else { shifted.Add(queue.Dequeue()); } index++; } row.UpdateCells(shifted); } foreach (var row in dst.Rows.Values) { var shifted = new List <ExcelCell>(); var index = 0; var queue = new Queue <ExcelCell>(row.Cells); while (queue.Any()) { if (columnStatusMap[index] == ExcelColumnStatus.Deleted) { shifted.Add(new ExcelCell(string.Empty, 0, 0)); } else { shifted.Add(queue.Dequeue()); } index++; } row.UpdateCells(shifted); } var r = DiffUtil.Diff(src.Rows.Values, dst.Rows.Values, option); r = DiffUtil.Order(r, DiffOrderType.LazyDeleteFirst); var resultArray = DiffUtil.OptimizeCaseDeletedFirst(r).ToArray(); if (resultArray.Length > 10000) { var count = 0; var indices = Enumerable.Range(0, 100).ToList(); foreach (var result in resultArray) { if (result.Status != DiffStatus.Equal) { indices.AddRange(Enumerable.Range(Math.Max(0, count - 100), 200)); } count++; } indices = indices.Distinct().ToList(); resultArray = indices.Where(i => i < resultArray.Length).Select(i => resultArray[i]).ToArray(); } var sheetDiff = new ExcelSheetDiff(); DiffCells(resultArray, sheetDiff, columnStatusMap); return(sheetDiff); }
private static Dictionary <int, ExcelColumnStatus> CreateColumnStatusMap( IEnumerable <ExcelColumn> srcColumns, IEnumerable <ExcelColumn> dstColumns, ExcelSheetDiffConfig config) { var option = new DiffOption <ExcelColumn>(); if (config.SrcHeaderIndex >= 0) { option.EqualityComparer = new HeaderComparer(); foreach (var sc in srcColumns) { sc.HeaderIndex = config.SrcHeaderIndex; } } if (config.DstHeaderIndex >= 0) { foreach (var dc in dstColumns) { dc.HeaderIndex = config.DstHeaderIndex; } } var results = DiffUtil.Diff(srcColumns, dstColumns, option); results = DiffUtil.Order(results, DiffOrderType.LazyDeleteFirst); results = DiffUtil.OptimizeCaseDeletedFirst(results); var ret = new Dictionary <int, ExcelColumnStatus>(); var columnIndex = 0; foreach (var result in results) { var status = ExcelColumnStatus.None; if (result.Status == DiffStatus.Deleted) { status = ExcelColumnStatus.Deleted; } else if (result.Status == DiffStatus.Inserted) { status = ExcelColumnStatus.Inserted; } ret.Add(columnIndex, status); columnIndex++; } return(ret); }