Domanda

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.

È stato utile?

Soluzione 2

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
    );
);

Altri suggerimenti

If you own the code for the view model I would change it so that the ColX properties only have a getter that returns CurrentQuantity - (X * subtractedValues) where subtractedValues is a required value for the constructor.

That way, you won't have to set all the column values. They are automatically calculated.

It would look something like this:

class StockForecastReportExport
{
    private decimal subtractedValue;

    public StockForecastReportExport(decimal subtractedValue)
    {
        this.subtractedValue = subtractedValue; 
    }

    [ExcelCol("F")]
    public decimal Col1 { get { return CurrentQuantity - (1 * subtractedValue); } }

    [ExcelCol("G")]
    public decimal Col2 { get { return CurrentQuantity - (2 * subtractedValue); } }

    [ExcelCol("H")]
    public decimal Col3 { get { return CurrentQuantity - (3 * subtractedValue); } }

    public decimal CurrentQuantity { get; set; }
}

Of course you could go nuts with reflection but I don't think that's required in this case.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top