Unplanned
Last Updated: 31 Jul 2023 10:53 by ADMIN
Dimitar
Created on: 12 Mar 2020 09:43
Category: SpreadProcessing
Type: Bug Report
1
SpreadProcessing: Adding a formula with the SetValueAsFormula method is slow
Adding a formula with the SetValueAsFormula method is slow
2 comments
ADMIN
Nikolay Demirev
Posted on: 31 Jul 2023 10:53

Hello,

We understand the significance of this feature for you. Thank you for the feedback, but I am afraid this issue will be fixed when the Calculation Chain feature is implemented. Developing this feature would involve comprehensive research and timely implementation. Currently, our team is dedicated to addressing more pressing tasks, but we will certainly consider your input for future releases. In the meantime, follow the item so you get notified when its status change.

Please excuse us for the inconvenience caused by the absence of this functionality at this time.

Regards,
Nikolay Demirev
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Dev
Posted on: 28 Jul 2023 04:04

Is there any progress with this issue. I currently using the document processing and i have to insert multiple formula into columns and it is slowing down the process by a significant amount starting from the part where Im inserting Total Columns formula. Below is my code for reference

[HttpGet("download/wip")]
        [AuthorizeRole(RoleDef.FinanceUser)]
        public async Task<IActionResult> OnDownloadWIPInventoryHistoryAsync(
            DateTime shipmentPickupStartDate,
            DateTime shipmentPickupEndDate,
            DateTime poApprovalStartDate,
            DateTime poApprovalEndDate)
        {
            #region Load Inventory Data

            using var db = await _dbFactory.CreateDbContextAsync();

            List<WIPInventoryReportViewModel> inventoryList = new();

            var quotationTable = await db.DbQuotations.AsNoTracking().ToDictionaryAsync(x => x.Sku + x.SupplierId);

            var purchaseOrderItemQuery = from poi in db.DbPurchaseOrderItems.AsNoTracking()
                                         join po in db.DbPurchaseOrders.AsNoTracking() on poi.PurchaseOrderId equals po.Id into poJoin
                                         from po in poJoin.DefaultIfEmpty()
                                         join p in db.DbProducts.AsNoTracking() on poi.Sku equals p.Sku into pJoin
                                         from p in pJoin.DefaultIfEmpty()
                                         join d in db.DbDestinations.AsNoTracking() on po.DestinationId equals d.Id into dJoin
                                         from d in dJoin.DefaultIfEmpty()
                                         where po.ApprovalDate != null
                                         where po.ApprovalDate >= poApprovalStartDate && po.ApprovalDate <= poApprovalEndDate
                                         select new WIPInventoryReportViewModel
                                         {
                                             PurchaseOrderItemId = poi.ItemId,
                                             PurchaseOrderId = poi.PurchaseOrderId,
                                             PurchaseOrderIdString = poi.PurchaseOrderId.ToString(),
                                             SupplierId = po.SupplierId,
                                             ApprovalDate = po.ApprovalDate,
                                             InvoiceNo = po.InvoiceId,
                                             Sku = poi.Sku,
                                             ShortName = p.ShortName,
                                             Quantity = poi.Quantity,
                                             PricePerUnit = poi.PricePerUnit,
                                             TotalCost = poi.Quantity * poi.PricePerUnit,
                                         };

            var purchaseOrderItemTable = await purchaseOrderItemQuery.ToDictionaryAsync(x => x.PurchaseOrderItemId);

            List<string> poItemIds = new();
            foreach (var poDic in purchaseOrderItemTable)
            {
                var poItem = poDic.Value;

                poItemIds.Add(poItem.PurchaseOrderItemId);
                inventoryList.Add(poItem);
            }

            var shipmentItemQuery = from si in db.DbShipmentItems.AsNoTracking()
                                    join s in db.DbShipments.AsNoTracking() on si.ShipmentId equals s.Id into sJoin
                                    from s in sJoin.DefaultIfEmpty()
                                    join d in db.DbDestinations.AsNoTracking() on s.DestinationId equals d.Id into dJoin
                                    from d in dJoin.DefaultIfEmpty()
                                    where poItemIds.Contains(si.PurchaseOrderItemId)
                                    where s.PickUpDate != null
                                    where s.PickUpDate >= shipmentPickupStartDate && s.PickUpDate <= shipmentPickupEndDate
                                    select new PickUpInfoViewModel
                                    {
                                        PurchaseOrderItemId = si.PurchaseOrderItemId,
                                        PickupDate = s.PickUpDate,
                                        PickupRef = s.CaptainKeaId,
                                        PickupLocation = d.CountryCode,
                                        PickupQuantity = si.Delivered
                                    };

            var shipmentItemList = await shipmentItemQuery.GroupBy(x => x.PurchaseOrderItemId).ToListAsync();

            List<int> specialCompensateUnitSupplierId = new List<int> { 8, 22 };

            foreach (var inventoryItem in inventoryList)
            {
                var shipmentItems = shipmentItemList.FirstOrDefault(x => x.Key == inventoryItem.PurchaseOrderItemId);
                int totalPickUpQuantity = 0;
                inventoryItem.PickUpInfo ??= new();

                if (shipmentItems != null)
                {
                    foreach (var item in shipmentItems)
                    {
                        if (inventoryItem.PricePerUnit == 0m)
                        {
                            if (specialCompensateUnitSupplierId.Contains(inventoryItem.SupplierId))
                            {
                                var list = inventoryList.Where(x => x.PurchaseOrderId == inventoryItem.PurchaseOrderId).ToList();
                                inventoryItem.PricePerUnit = CompensationUnitCalculator.CalculateSpecialCompensationUnitPrice(inventoryItem.Sku, list);
                            }
                            else
                            {
                                inventoryItem.PricePerUnit = CompensationUnitCalculator.CalculateCompensationUnitPrice(inventoryItem.SupplierId, inventoryItem.Sku, inventoryItem.Quantity, quotationTable);
                            }
                        }

                        item.PickupTotalCost = Math.Round((decimal)(item.PickupQuantity * inventoryItem.PricePerUnit), 2);

                        inventoryItem.PickUpInfo.Add(item);

                        totalPickUpQuantity += item.PickupQuantity;
                    }
                }

                inventoryItem.PickupStatus = GetPickUpStatus(totalPickUpQuantity, inventoryItem.Quantity);
            }

            #endregion Load Inventory Data

            #region Load Template (Not used)

            Workbook workbook = new Workbook();
            IWorkbookFormatProvider formatProvider = new XlsxFormatProvider();
            var applicationPath = _webHostEnvironment.ContentRootPath;
            var templatePath = Path.Combine(applicationPath, "ReportsAndTemplates", "Templates", "WIP Inventory Template.xlsx");

            using (Stream input = new FileStream(templatePath, FileMode.Open))
            {
                workbook = formatProvider.Import(input);
            }

            Worksheet worksheet = workbook.ActiveWorksheet;

            #endregion Load Template

            int currentRow = 5;
            int formulaRow = currentRow + 1;
            int pickupColumn = 11;
            ThemableColor borderColor = new ThemableColor(ThemeColorType.Text1);
            CellBorder border = new CellBorder(CellBorderStyle.Medium, borderColor);

            foreach (var item in inventoryList)
            {
                worksheet.Cells[currentRow, 0].SetValue(item.PurchaseOrderId);
                worksheet.Cells[currentRow, 1].SetValue((DateTime)item.ApprovalDate);
                worksheet.Cells[currentRow, 2].SetValue(item.InvoiceNo);
                worksheet.Cells[currentRow, 3].SetValue(item.Sku);
                worksheet.Cells[currentRow, 4].SetValue(item.ShortName);
                worksheet.Cells[currentRow, 5].SetValue(item.Quantity);
                worksheet.Cells[currentRow, 6].SetValue((double)item.PricePerUnit);
                worksheet.Cells[currentRow, 7].SetValue((double)item.TotalCost);

                worksheet.Cells[currentRow, 9].SetValue(item.PickupStatus);

                worksheet.Cells[currentRow, 10].SetBorders(new CellBorders(null, null, border, null, null, null, null, null));
                
                for (int i = 0; i < item.PickUpInfo?.Count; i++)
                {
                    var pickUpInfo = item.PickUpInfo[i];

                    worksheet.Cells[currentRow, pickupColumn].SetValue((DateTime)pickUpInfo.PickupDate);
                    worksheet.Cells[currentRow, pickupColumn + 1].SetValue(pickUpInfo.PickupRef);
                    worksheet.Cells[currentRow, pickupColumn + 2].SetValue(pickUpInfo.PickupLocation);
                    worksheet.Cells[currentRow, pickupColumn + 3].SetValue(pickUpInfo.PickupQuantity);
                    string index = GetExcelColumnName(pickupColumn + 4);
                    worksheet.Cells[currentRow, pickupColumn + 4].SetValueAsFormula($"=ROUND({index}{formulaRow}*G{formulaRow},2)");

                    worksheet.Cells[currentRow, pickupColumn + 5].SetBorders(new CellBorders(null, null, border, null, null, null, null, null));

                    pickupColumn += 6;
                }


                #region Total Columns

                worksheet.Cells[currentRow, 131].SetValueAsFormula($"=O{formulaRow}+U{formulaRow}+AA{formulaRow}+AG{formulaRow}+AM{formulaRow}+AS{formulaRow}+AY{formulaRow}+BE{formulaRow}+BK{formulaRow}+BQ{formulaRow}+BW{formulaRow}+CC{formulaRow}+CO{formulaRow}+CU{formulaRow}+CI{formulaRow}+DA{formulaRow}+DG{formulaRow}+DM{formulaRow}+DS{formulaRow}+DY{formulaRow}");
                worksheet.Cells[currentRow, 132].SetValueAsFormula($"=ROUND(EB{formulaRow}*G{formulaRow},2)");
                worksheet.Cells[currentRow, 133].SetValueAsFormula($"=F{formulaRow}-EB{formulaRow}");
                worksheet.Cells[currentRow, 134].SetValueAsFormula($"=H{formulaRow}-EC{formulaRow}");
                worksheet.Cells[currentRow, 135].SetValueAsFormula($"=EC{formulaRow}-P{formulaRow}-V{formulaRow}-AB{formulaRow}-AH{formulaRow}-AN{formulaRow}-AT{formulaRow}-AZ{formulaRow}-BF{formulaRow}-BL{formulaRow}-BR{formulaRow}-BX{formulaRow}-CD{formulaRow}-CJ{formulaRow}-CP{formulaRow}-CV{formulaRow}-DB{formulaRow}-DH{formulaRow}-DN{formulaRow}-DT{formulaRow}-DZ{formulaRow}");

                #endregion

                pickupColumn = 11;
                currentRow++;
                formulaRow++;
            }

            byte[] xlsxBytes = null;

            using (MemoryStream stream = new MemoryStream())
            {
                #region Add Rule

                ContainsRule partialRule = new ContainsRule("Partial");
                DifferentialFormatting partialFormatting = new DifferentialFormatting();
                partialFormatting.Fill = new PatternFill(PatternType.Solid, Color.FromHex("#FFC7CE"), Colors.Transparent);
                partialFormatting.ForeColor = new ThemableColor(Color.FromHex("#9C0006"));
                partialRule.Formatting = partialFormatting;
                ConditionalFormatting partialConditionalFormatting = new ConditionalFormatting(partialRule);

                ContainsRule fullyRule = new ContainsRule("Fully Pick Up");
                DifferentialFormatting fullyFormatting = new DifferentialFormatting();
                fullyFormatting.Fill = new PatternFill(PatternType.Solid, Color.FromHex("#C6EFCE"), Colors.Transparent);
                fullyFormatting.ForeColor = new ThemableColor(Color.FromHex("#006100"));
                fullyRule.Formatting = fullyFormatting;
                ConditionalFormatting fullyConditionalFormatting = new ConditionalFormatting(fullyRule);

                worksheet.Cells[0, 9, currentRow, 0].AddConditionalFormatting(partialConditionalFormatting);
                worksheet.Cells[0, 9, currentRow, 0].AddConditionalFormatting(fullyConditionalFormatting);

                #endregion

                formatProvider.Export(workbook, stream);
                xlsxBytes = stream.ToArray();
            }

            return File(xlsxBytes, "text/csv", $"Inventory Report (WIP).xlsx");
        }