Используя MVVM и SOLID декомпозируй этот код: [using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace ParsForAlwaysRegularBigSalaryPls.Services
{
    class ExcelProcessingService : IExcelProcessingService
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public ExcelProcessingService()
        {
            ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
        }

        public void ProcessExcelFile(string inputFilePath, string outputFilePath)
        {
            if (!File.Exists(inputFilePath) || string.IsNullOrWhiteSpace(outputFilePath))
                return;

            FileInfo inputFile = new FileInfo(inputFilePath);
            FileInfo outputFile = new FileInfo(outputFilePath);

            ExcelPackage package = null;
            try
            {
                package = new ExcelPackage(inputFile);
                var worksheet = package.Workbook.Worksheets[0];
                int rowCount = worksheet.Dimension.Rows;

                for (int row = 7; row <= rowCount; row++)
                {
                    double realKtu = worksheet.Cells[row, 22].GetValue<double>();
                    double currentKtu = worksheet.Cells[row, 21].GetValue<double>();
                    double difference = realKtu - currentKtu;

                    if (Math.Abs(difference) > 1e-9)
                    {
                        AdjustKValues(worksheet, row, difference);
                    }
                }

                package.SaveAs(outputFile);
            }
            finally
            {
                package?.Dispose();
            }
        }

        private void AdjustKValues(ExcelWorksheet worksheet, int row, double difference)
        {
            var (yellowColumns, originalValues, minValues, maxValues) = GetColumnValues(worksheet, row);
            if (!yellowColumns.Any()) return;

            double originalYellowSum = yellowColumns.Sum(idx => originalValues[idx]);
            double targetSum = originalYellowSum + difference;

            double sumOfMins = yellowColumns.Sum(idx => minValues[idx]);
            double sumOfMaxs = yellowColumns.Sum(idx => maxValues[idx]);

            if (targetSum < sumOfMins - 1e-9 || targetSum > sumOfMaxs + 1e-9)
            {
                return;
            }

            double[] newValues = new double[originalValues.Length];
            Array.Copy(originalValues, newValues, originalValues.Length);

            Random rnd = new Random();

            foreach (var idx in yellowColumns)
            {
                double colMin = minValues[idx];
                double colMax = maxValues[idx];
                newValues[idx] = GenerateRandomValue(rnd, colMin, colMax);
            }

            AdjustValuesToMatchSum(rnd, yellowColumns, newValues, minValues, maxValues, targetSum);

            BalanceFirstColumn(rnd, yellowColumns, newValues, minValues, maxValues);

            IntroduceGranularAdjustments(rnd, yellowColumns, newValues, minValues, maxValues);

            ApplyNewValues(worksheet, row, yellowColumns, newValues);
            UpdateKtuValues(worksheet, row, difference);
        }

        private (List<int> yellowColumns, double[] originalValues, double[] minValues, double[] maxValues) GetColumnValues(ExcelWorksheet worksheet, int row)
        {
            const int startCol = 5, endCol = 15;
            const int rowMinValues = 1, rowMaxValues = 2;

            var yellowColumns = new List<int>();
            var originalValues = new double[endCol - startCol + 1];
            var minValues = new double[endCol - startCol + 1];
            var maxValues = new double[endCol - startCol + 1];

            for (int col = startCol; col <= endCol; col++)
            {
                minValues[col - startCol] = worksheet.Cells[rowMinValues, col].GetValue<double>();
                maxValues[col - startCol] = worksheet.Cells[rowMaxValues, col].GetValue<double>();

                var cell = worksheet.Cells[row, col];
                var backgroundColor = cell.Style.Fill.BackgroundColor.LookupColor();
                originalValues[col - startCol] = cell.GetValue<double>();

                if (backgroundColor == "#FFFFFF00")
                {
                    yellowColumns.Add(col - startCol);
                }
            }

            return (yellowColumns, originalValues, minValues, maxValues);
        }

        private double GenerateRandomValue(Random rnd, double min, double max)
        {
            double mean = (min + max) / 2.0;
            double sigma = (max - min) / 6.0;
            double value;

            int attempts = 0;
            do
            {
                double u1 = 1.0 - rnd.NextDouble();
                double u2 = 1.0 - rnd.NextDouble();
                double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
                value = mean + sigma * randStdNormal;

                attempts++;
                if (attempts > 1000)
                {
                    value = min + rnd.NextDouble() * (max - min);
                    break;
                }
            } while (value < min || value > max);

            return value;
        }

        private void AdjustValuesToMatchSum(Random rnd, List<int> yellowColumns, double[] newValues, double[] minValues, double[] maxValues, double targetSum)
        {
            double currentSum = yellowColumns.Sum(idx => newValues[idx]);
            double remaining = targetSum - currentSum;

            int iterations = 300;
            for (int iter = 0; iter < iterations && Math.Abs(remaining) > 1e-9; iter++)
            {
                foreach (var colIdx in yellowColumns.OrderBy(_ => rnd.Next()))
                {
                    double currentVal = newValues[colIdx];
                    double colMin = minValues[colIdx];
                    double colMax = maxValues[colIdx];

                    double delta;
                    if (remaining > 0)
                    {
                        double canIncrease = colMax - currentVal;
                        delta = Math.Min(canIncrease, remaining) * rnd.NextDouble();
                    }
                    else
                    {
                        double canDecrease = currentVal - colMin;
                        delta = -Math.Min(canDecrease, -remaining) * rnd.NextDouble();
                    }

                    currentVal += delta;
                    newValues[colIdx] = currentVal;
                    remaining -= delta;

                    if (Math.Abs(remaining) <= 1e-9) break;
                }
            }
        }

        private void BalanceFirstColumn(Random rnd, List<int> yellowColumns, double[] newValues, double[] minValues, double[] maxValues)
        {
            if (yellowColumns.Count < 2) return;

            int firstCol = yellowColumns[0];
            double firstVal = newValues[firstCol];

            double neighborAvg = yellowColumns.Skip(1).Average(idx => newValues[idx]);

            if (firstVal > neighborAvg * 1.1)
            {
                double maxDecrease = firstVal - minValues[firstCol];
                double adjustment = Math.Min(maxDecrease, (firstVal - neighborAvg) * rnd.NextDouble());
                newValues[firstCol] -= adjustment;
            }
            else if (firstVal < neighborAvg * 0.9)
            {
                double maxIncrease = maxValues[firstCol] - firstVal;
                double adjustment = Math.Min(maxIncrease, (neighborAvg - firstVal) * rnd.NextDouble());
                newValues[firstCol] += adjustment;
            }

            newValues[firstCol] = Clamp(newValues[firstCol], minValues[firstCol], maxValues[firstCol]);
        }

        private static double Clamp(double value, double min, double max)
        {
            if (value < min) return min;
            if (value > max) return max;
            return value;
        }

        private void IntroduceGranularAdjustments(Random rnd, List<int> yellowColumns, double[] newValues, double[] minValues, double[] maxValues)
        {
            for (int i = 0; i < 100; i++)
            {
                if (yellowColumns.Count < 2) break;

                int colIdx1 = yellowColumns[rnd.Next(yellowColumns.Count)];
                int colIdx2 = yellowColumns[rnd.Next(yellowColumns.Count)];

                if (colIdx1 == colIdx2) continue;

                double v1 = newValues[colIdx1];
                double v2 = newValues[colIdx2];
                double min1 = minValues[colIdx1], max1 = maxValues[colIdx1];
                double min2 = minValues[colIdx2], max2 = maxValues[colIdx2];

                double adjustment = (rnd.NextDouble() - 0.5) * (max1 - min1 + max2 - min2) * 0.01;

                if (v1 - adjustment >= min1 && v1 - adjustment <= max1 &&
                    v2 + adjustment >= min2 && v2 + adjustment <= max2)
                {
                    newValues[colIdx1] -= adjustment;
                    newValues[colIdx2] += adjustment;
                }
            }
        }

        private void ApplyNewValues(ExcelWorksheet worksheet, int row, List<int> yellowColumns, double[] newValues)
        {
            int startCol = 5;
            foreach (var idx in yellowColumns)
            {
                worksheet.Cells[row, startCol + idx].Value = Math.Round(newValues[idx], 6);
            }
        }

        private void UpdateKtuValues(ExcelWorksheet worksheet, int row, double difference)
        {
            worksheet.Cells[row, 21].Value = worksheet.Cells[row, 21].GetValue<double>() + difference;
            worksheet.Cells[row, 23].Value = 0;
        }

    }
}
    
]