Search code examples
c#export-to-excel

Subtraction on object initiation


I have a ViewModel which represents a spreadsheet as shown below.

I am looping through a dataList to populate its values row by row/ column by column.

As you see the first six columns are straight forward assignment of corresponding values from the datalist.

The remaining ones however, i.e., Col1, Col2, Col3, Col3...etc, are calculated as shown here:

foreach (var stockMaterial in materialDataList)
{
     var initialQuantity = stockMaterial.CurrentQuantity;
     var subtractedValues = GetSubtractedValues(stockMaterial.CurrentQuantity, stockMaterial.AvarageUsage,
     stockMaterial.QuantityReserved);


     exportedFile.Rows.Add(new StockForecastReportExport
     {
          MaterialName = stockMaterial.MaterialName,
          CurrentStockLevel = initialQuantity,
          OrderThreshold = stockMaterial.OrderThreshold,
          AvarageUsage = stockMaterial.AvarageUsage,
          QuantityReserved = stockMaterial.QuantityReserved,
          Col1 = stockMaterial.CurrentQuantity - subtractedValues,
          Col2 = stockMaterial.CurrentQuantity - subtractedValues - subtractedValues,
          Col3 = stockMaterial.CurrentQuantity - subtractedValues - subtractedValues - subtractedValues,
     });
}

As you see the currentQuantity which is specific to a Material (a row), is decremented by a number for every column that is next. There are 20 columns at least.

I wonder what can I do to do this efficiently and neatly. Of course, in no way the above is clean acceptable!

Please help with ideas. For example may be looping through the Col(x) properties and assign the values.

Here is the view model I mentioned:

 public class StockForecastReportExport
    {
        [ExcelCol("A")]
        public string MaterialName { get; set; }

        [ExcelCol("B")]
        public int CurrentStockLevel { get; set; }

        [ExcelCol("C")]
        public int OrderThreshold { get; set; }

        [ExcelCol("D")]
        public int AvarageUsage { get; set; }

        [ExcelCol("E")]
        public int QuantityReserved { get; set; }

        [ExcelCol("F")]
        public decimal Col1 { get; set; }

        [ExcelCol("G")]
        public decimal Col2 { get; set; }

        [ExcelCol("H")]
        public decimal Col3 { get; set; }

        [ExcelCol("I")]
        public decimal Col4 { get; set; }

        [ExcelCol("J")]
        public decimal Col5 { get; set; }

        [ExcelCol("K")]
        public decimal Col6 { get; set; }

        [ExcelCol("L")]
        public decimal Col7 { get; set; }

        [ExcelCol("M")]
        public decimal Col8 { get; set; }

        [ExcelCol("N")]
        public decimal Col9 { get; set; }

        [ExcelCol("O")]
        public decimal Col10 { get; set; }

        [ExcelCol("P")]
        public decimal Col11 { get; set; }

        [ExcelCol("Q")]
        public decimal Col12 { get; set; }

        [ExcelCol("R")]
        public decimal Col13 { get; set; }

        [ExcelCol("S")]
        public decimal Col14 { get; set; }

        [ExcelCol("T")]
        public decimal Col15 { get; set; }

        [ExcelCol("U")]
        public decimal Col16 { get; set; }

        [ExcelCol("V")]
        public decimal Col17 { get; set; }

        [ExcelCol("W")]
        public decimal Col18 { get; set; }

        [ExcelCol("X")]
        public decimal Col19 { get; set; }

        [ExcelCol("Y")]
        public decimal Col20 { get; set; }

    }

Many thanks in advance.


Solution

  • I'd suggest to obfuscate the calculations within the class itself. Add a constructor and pass SubtractedValues and CurrentQuantity, and use a multiplication function to set the columns:

    Note that this solution still only does the calculations once and sets the results to all of your ColN properties at time of instantiation.

    public class StockForecastReportExport
    {
        public StockForecastReportExport(
            string materialName, 
            int currentStockLevel, 
            int orderThreshold, 
            int averageUsage, 
            int quantityReserved, 
            int currentQuantity, 
            int subtractedValues)
        {
            MaterialName = materialName;
            CurrentStockLevel = currentStockLevel;
            OrderThreshold = orderThreshold;
            AvarageUsage = averageUsage;
            QuantityReserved = quantityReserved;
    
            Func<int, int> multiplyFunc = mf => 
                currentQuantity - (subtractedValues * mf);
    
            // Calculate the rest
            Col1 = multiplyFunc(1);
            Col2 = multiplyFunc(2);
            Col3 = multiplyFunc(3);
            ...
        }
    
        [ExcelCol("A")]
        public string MaterialName { get; set; }
    
        ...
    }
    

    Then your creation code will be much more elegant:

    exportedFile.Rows.Add(
        new StockForecastReportExport
        (
            materialName: stockMaterial.MaterialName,
            currentStockLevel: initialQuantity,
            orderThreshold: stockMaterial.OrderThreshold,
            averageUsage: stockMaterial.AvarageUsage,
            quantityReserved: stockMaterial.QuantityReserved,
            currentQuantity: stockMaterial.CurrentQuantity,
            subtractedValues: subtractedValues
        );
    );