Using Calculated_CheckBox in a uBAQ Dashboard to Sum a Field

Good afternoon, everyone!
I hope you all had a great holiday. Today I am back at an old dashboard that I gave up on in the past.

My goal is to simply add up the OpenValue field for each row that is checked in the dashboard. I have built the uBAQ to include a blank checkbox (calculated as 0). I think that I need to use an EpiViewNotification event from Wizards > Form Event Wizard. But can’t find a wizard that triggers on a field change. (I see the Before/After field change events there, but my table is not listed.**)

I would like to trigger on the user clicking a check box in the uBAQ’s grid. Once triggered, the event should review all the other rows with a check box and add up the OpenValue column for just those that are checked.

Once I have that value, I would like to place it into a text field for the user to see. Ideally the user just clicks a bunch of rows then the text box shows a sort of running total of those checked. If the user unchecks, the total should update accordingly.

Questions:

  1. How do I trigger on the user clicking a calculated field checkbox on the uBAQs grid inside a dashboard?
  2. Once triggered, I have to pull the value from the checked box and store it someplace so that I can add it to the rest of the values that are checked. Where do I store the variable that holds the value to display in the textbox?

Eventually, once this is working correctly the UBAQ will use those check boxes to “what-if” schedule the jobs that the user selected using a new date. This part of my uBAQ works just fine. I just need to use those check boxes to pull a total before I run my custom action to do the WI scheduling.

** My dashboard is actually made of 2 BAQs. One UBAQ that does the WI scheduling and the checkboxes, and another BAQ (not UBAQ) that just shows a summary from the ResourceTimeUsed table showing the updated WI schedule load. So, I can’t use the Before/After FieldChange events, because the only tables listed are BpmData, Client, and Results. I tried to use the template created by the AfterFieldChange Event and swap in my dataview that has the checkboxes. But bastardizing the wizard template never works out the way you want it to…

Thank you for your time!
Nate

I’m not understanding why you can’t use the results table? I’m doing basically the same thing in one of my dashboards, and using the results table. You’ll probably have to show more details for anyone to understand what you are tying to do.

Are you able to get it to work with a single BAQ?

1 Like

The fields don’t exist in my results table. The results table seems to only have the fields from my second BAQ, and none of the fields from my first UBAQ. Maybe if i build the dashboard the other way around, and add my UBAQ first, then my regular BAQ?

For S’s and giggles, add that that guy to MessageBox.Show() after you make an after field change event, (pick whatever random field just to make the event), then see if anything pops when you change what you want to change. Put it before the switch so it goes off without any filtering.

1 Like

Nothing. I even rebuilt the dash with the other BAQ first, but the fields in Results are only from my second BAQ. Dang!

I should be more specific. When I added that message box, I got a popup that just says SysRowID, it pops up a bunch of times. Maybe as many times as I have columns in one of my tables! But clicking my check box inside the ubaq doesn’t seem to trigger any field change, at least not in Results.

	private void Results_AfterFieldChange(object sender, DataColumnChangeEventArgs args)
	{
		// ** Argument Properties and Uses **
		// args.Row["FieldName"]
		// args.Column, args.ProposedValue, args.Row
		// Add Event Handler Code
		MessageBox.Show(args.Column.ColumnName.ToString());		
		switch (args.Column.ColumnName)
		{
... yadda yadda

On second thought it might be related to the number of rows in the Results table. I swapped out the message box like this:

MessageBox.Show(sender.ToString());

And it just said “Results” over and over again.

Yes! After I deleted my second BAQ inside my dashboard, the results table now shows the fields I need. So strange! I guess I have to have them use two dashboards instead of one.

I have this code:


public class Script
{
public EpiTextBox myString;
decimal totOpenValue;

	// ** Wizard Insert Location - Do Not Remove 'Begin/End Wizard Added Module Level Variables' Comments! **
	// Begin Wizard Added Module Level Variables **

	// End Wizard Added Module Level Variables **

	// Add Custom Module Level Variables Here **

	public void InitializeCustomCode()
	{
		// ** Wizard Insert Location - Do not delete 'Begin/End Wizard Added Variable Initialization' lines **
		// Begin Wizard Added Variable Initialization

		this.Results_Column.ColumnChanged += new DataColumnChangeEventHandler(this.Results_AfterFieldChange);
		// End Wizard Added Variable Initialization

		// Begin Wizard Added Custom Method Calls

		// End Wizard Added Custom Method Calls
	}

	public void DestroyCustomCode()
	{
		// ** Wizard Insert Location - Do not delete 'Begin/End Wizard Added Object Disposal' lines **
		// Begin Wizard Added Object Disposal

		this.Results_Column.ColumnChanged -= new DataColumnChangeEventHandler(this.Results_AfterFieldChange);
		// End Wizard Added Object Disposal

		// Begin Custom Code Disposal

		// End Custom Code Disposal
	}

	private void Results_AfterFieldChange(object sender, DataColumnChangeEventArgs args)
	{
		// ** Argument Properties and Uses **
		// args.Row["FieldName"]
		// args.Column, args.ProposedValue, args.Row
		// Add Event Handler Code
		EpiDataView edv = (EpiDataView)this.oTrans.EpiDataViews["Results"];

		switch (args.Column.ColumnName)
		{
			case "Calculated_CheckBox":
			MessageBox.Show(args.Column.ColumnName.ToString());
			
				foreach (DataRow x in edv.dataView)
				{
					MessageBox.Show(((decimal)x["Calculated_TotalOpenValue"]).ToString());
					if((bool)x["Calculated_CheckBox"] == true)
					{
						MessageBox.Show(((decimal)x["Calculated_TotalOpenValue"]).ToString());						
						totOpenValue += (decimal)x["Calculated_TotalOpenValue"];
					}
				}
				myString = (Ice.Lib.Framework.EpiTextBox)csm.GetNativeControlReference("f510f4b0-adb9-4259-8b83-f3d3737d3c89");

				myString.Value = totOpenValue.ToString();
				break;
		}
	}
}

The Message box after the case shows up, but neither of the message boxes inside the foreach shows up. You can see I defined edv inside the event. Should I define this outside the event, or should it be defined to something else?

Also tried to used this instead with similar lack of results:

foreach (DataRowView x in edv.dataView)

I replaced the first messagebox that was showing up with this, and now it doesn’t show up anymore, but compiles fine and produces no error:

	MessageBox.Show(edv.dataView[0]["Calculated_TotalOpenValue"].ToString());

Woo! I got it working! Posted working code below. Thank you!

// **************************************************
// Custom code for MainController
// Created: 11/29/2022 8:33:46 AM
// **************************************************
using System;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
using Ice.BO;
using Ice.UI;
using Ice.Lib;
using Ice.Adapters;
using Ice.Lib.Customization;
using Ice.Lib.ExtendedProps;
using Ice.Lib.Framework;
using Ice.Lib.Searches;
using Ice.UI.FormFunctions;




public class Script
{
decimal totOpenValue = 0;
EpiDataView edv;

	// ** Wizard Insert Location - Do Not Remove 'Begin/End Wizard Added Module Level Variables' Comments! **
	// Begin Wizard Added Module Level Variables **

	// End Wizard Added Module Level Variables **

	// Add Custom Module Level Variables Here **

	public void InitializeCustomCode()
	{
		// ** Wizard Insert Location - Do not delete 'Begin/End Wizard Added Variable Initialization' lines **
		// Begin Wizard Added Variable Initialization

		this.Results_Column.ColumnChanged += new DataColumnChangeEventHandler(this.Results_AfterFieldChange);
		// End Wizard Added Variable Initialization

		// Begin Wizard Added Custom Method Calls

		// End Wizard Added Custom Method Calls
	}

	public void DestroyCustomCode()
	{
		// ** Wizard Insert Location - Do not delete 'Begin/End Wizard Added Object Disposal' lines **
		// Begin Wizard Added Object Disposal

		this.Results_Column.ColumnChanged -= new DataColumnChangeEventHandler(this.Results_AfterFieldChange);
		// End Wizard Added Object Disposal

		// Begin Custom Code Disposal

		// End Custom Code Disposal
	}

	private void Results_AfterFieldChange(object sender, DataColumnChangeEventArgs args)
	{
		// ** Argument Properties and Uses **
		// args.Row["FieldName"]
		// args.Column, args.ProposedValue, args.Row
		// Add Event Handler Code
		

		switch (args.Column.ColumnName)
		{
			case "Calculated_CheckBox":

			if ((bool)args.Row["Calculated_CheckBox"] == true)
			{
				totOpenValue += (decimal)args.Row["Calculated_TotalOpenValue"];
			}
			else
			{
				totOpenValue -= (decimal)args.Row["Calculated_TotalOpenValue"];
			}

			epiNumericEditorC1.Value = totOpenValue.ToString();
			break;
		}
	}

	private void MainController_Load(object sender, EventArgs args)
	{
		edv = (EpiDataView)this.oTrans.EpiDataViews["Results"];
	}
}

Would you like to know how to display that custom sum in the grid as well?

Sure! That might be helpful. Thanks!

I’ll try to dig out some code this afternoon. In the meantime, I can point you to the relevant documentation.

It turned out to be relatively painless.

https://www.infragistics.com/help/winforms/infragistics.win.ultrawingrid~infragistics.win.ultrawingrid.summarysettings~customsummarycalculator

https://www.infragistics.com/help/winforms/infragistics.win.ultrawingrid~infragistics.win.ultrawingrid.icustomsummarycalculator

1 Like

@NateS Better late than never?


using Infragistics.Shared;
using Infragistics.Win;
using Infragistics.Win.UltraWinGrid;

//Extend the interface so we can pass variables
public interface ICustomSummaryCalculator_Ext : ICustomSummaryCalculator
{
    void PassVariables(string colSum, string colCheck, bool colCheckVal);
}

//Implement our Interface Extension(ICustomSummaryCalculator_Ext) of ICustomSummaryCalculator
class CustomTotalsSummary : ICustomSummaryCalculator_Ext
{
	private decimal totals = 0;
	private string columnToSum = "";
	private string columnToCheck = "";
	private bool columnToCheckValue = false;

	internal CustomTotalsSummary()
	{
	}

	public void BeginCustomSummary( SummarySettings summarySettings, RowsCollection rows )
	{
		this.totals = 0;
	}

	public void AggregateCustomSummary( SummarySettings summarySettings, UltraGridRow row )
	{
		// Here is where we process each row that gets passed in.

		object colSum = row.GetCellValue(summarySettings.SourceColumn.Band.Columns[columnToSum]);
		object colCheck = row.GetCellValue(summarySettings.SourceColumn.Band.Columns[columnToCheck]);

		// Handle null values
		if ( colSum is DBNull || colCheck is DBNull )
		{
			return;
		}

		// Convert to decimal.
		try
		{
			decimal _colSum = Convert.ToDecimal( colSum );
			bool _colCheck   = Convert.ToBoolean( colCheck );

			this.totals += _colCheck == columnToCheckValue ? _colSum : 0;

		}
		catch ( Exception )
		{
			Debug.Assert( false, "Exception thrown while trying to convert cell's value to decimal !" );
		}
	}

	
	public object EndCustomSummary( SummarySettings summarySettings, RowsCollection rows )		
	{
		return this.totals;
	}

	public void PassVariables(string colSum, string colCheck, bool colCheckVal)
	{
		columnToSum = colSum;
		columnToCheck = colCheck;
		columnToCheckValue = colCheckVal;
	}

}

public class Script
{
	EpiUltraGrid lotGrid;

	public void InitializeCustomCode()
	{
		lotGrid = (EpiUltraGrid)csm.GetNativeControlReference("yourguidhere");
	}


	private void MainController_Shown(object sender, EventArgs args)
	{
		//Add Custom Summaries
		AddCustomSummary(lotGrid, "PoundsTotals",   "Calculated_Pounds",   "Calculated_Deleted", false);
		AddCustomSummary(lotGrid, "FeetBagsTotals", "Calculated_FeetBags", "Calculated_Deleted", false);
		AddCustomSummary(lotGrid, "ItemQtyTotals",  "Calculated_ItemQty",  "Calculated_Deleted", false);
	}


	private void AddCustomSummary(EpiUltraGrid grid, string id, string colToSum, string colToCheck, bool colToCheckValue)
	{
		try
		{
			UltraGridBand band = grid.DisplayLayout.Bands[0];

			ICustomSummaryCalculator_Ext customSum = new CustomTotalsSummary();
			customSum.PassVariables(colToSum, colToCheck, colToCheckValue);

			SummarySettings summary = band.Summaries.Add( 
					id,							 			// Give an identifier (key) for this summary
					SummaryType.Custom,						 // Summary type is custom
					customSum,				 				 // Our custom summary calculator
					band.Columns[colToSum],		  // Column being summarized. Just use Unit Price column.
					SummaryPosition.UseSummaryPositionColumn,   // Position the summary on the left of summary footer
					null										// Since SummaryPosition is Left, pass in null
					);

			summary.DisplayFormat = "Sum = {0:n0}";
			summary.Appearance.TextHAlign = HAlign.Right;
		}
		catch {}
	}

}//END
1 Like