ReportViewer Nested SubReport - nested

I have 4 reports Report A, Report B, Report C and Report D with datasources dsA, dsB, dsC and dsD respectively.
Report A is a Main Report which has the subreport B has a subreport C ...
The Report A fills the datasource dsB in the SubreportProcessingEvent with the parameter from ReportA.
i would need an event which is fired for every row in Report B so that I pass parameter from Report B and fill the Report C and C parameter to Report D....
code in SubreportProcessingEventArg
SearchValue = new SqlParameter[2];
SqlConnection thisConnection = new SqlConnection(thisConnectionString);
DataSet thisDataSet = new DataSet();
SearchValue[0] = new SqlParameter("#TPlanId", e.Parameters[1].Values[0]);
SearchValue[1] = new SqlParameter("#ProblemId", e.Parameters[0].Values[0]);
thisDataSet = SqlHelper.ExecuteDataset(thisConnection, "Proc_TP_Goal", SearchValue);
/* Associate thisDataSet (now loaded with the stored procedure result) with the ReportViewer datasource */
ReportDataSource datasource = new ReportDataSource("Goal_Proc_TP_Goal", thisDataSet.Tables[0]);
e.DataSources.Add(datasource);
i was not able to figure out the 3rd and 4th level of event handler any suggestion or examples would be greatly appreciated.
Thanks

I do this, I have a parameter in the sub-subreports that pass the row of the subreport. I hope you understand, if not let me know and I will post a sourcecode.
if ("RendicionDetalleCodigosReporte".Equals(e.ReportPath))
{
if (data != null)
{
RendicionDetalleData detalle = new RendicionDetalleData();
detalle.row = 0;
int row = Convert.ToInt32(e.Parameters[0].Values[0]);
foreach (var det in data.Detalles)
{
if (det.row.Equals(row))
{
detalle = det;
break;
}
}
if (detalle.row == 0)
{
e.DataSources.Add(new ReportDataSource("RendicionDetalleCodigo", new List<RendicionDetalleCodigosData>()));
}
else
{
e.DataSources.Add(new ReportDataSource("RendicionDetalleCodigo", detalle.Codigos));
}
}
else
{
e.DataSources.Add(new ReportDataSource("RendicionDetalleCodigo", new List<RendicionDetalleCodigosData>()));
}
}
else
{
if (data != null)
{
e.DataSources.Add(new ReportDataSource("RendicionDetalle", data.Detalles));
}
else
{
e.DataSources.Add(new ReportDataSource("RendicionDetalle", new List<RendicionDetalleData>()));
}
}

Related

How can I save a custom field on ARCashSale after the Release process is complete?

When I release a Cash Sales document, after everything verifies successfully and the GL Batch is created, I execute code which created a second GL Batch that handles other transactions related to the cash sale. After that batch is created, I want to save the second GL Batch's Ref Nbr on the Cash Sales document as well. When I try to save it, I get an error:
Here is my code overriding the normal Release process:
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
ARCashSale cashSale = Base.Document.Current;
PXGraph.InstanceCreated.AddHandler<JournalEntry>(delegate (JournalEntry oldJournalEntry)
{
oldJournalEntry.RowPersisted.AddHandler<Batch>(delegate (PXCache sender, PXRowPersistedEventArgs e)
{
Batch oldBatch = oldJournalEntry.BatchModule.Current;
if (oldBatch != null && isCreated == false && e.Operation == PXDBOperation.Insert && e.TranStatus == PXTranStatus.Completed)
{
isCreated = true;
if (CFBSAdjustments.Select().Count > 0)
{
JournalEntry newJournalEntry = PXGraph.CreateInstance<JournalEntry>();
Batch newBatch = new Batch();
newBatch = newJournalEntry.BatchModule.Insert(newBatch);
Customer customer = PXSelect<Customer, Where<Customer.bAccountID, Equal<Required<Customer.bAccountID>>>>.Select(Base, cashSale.CustomerID);
newBatch.Description = "Fund Entry for Cash Sales Reference " + cashSale.RefNbr;
newBatch.FinPeriodID = oldBatch.FinPeriodID;
newBatch.LedgerID = oldBatch.LedgerID;
newBatch.DateEntered = oldBatch.DateEntered;
decimal? debit = 0;
decimal? credit = 0;
foreach (CFBSCashSalesAdjustment row in CFBSAdjustments.Select())
{
GLTran tran = newJournalEntry.GLTranModuleBatNbr.Insert();
tran.SummPost = true;
tran.BranchID = cashSale.BranchID;
tran.TranType = GLTran.tranClass.Normal;
tran.TranClass = GL.Messages.RoundingDiff;
tran.LedgerID = newBatch.LedgerID;
tran.FinPeriodID = newBatch.FinPeriodID;
tran.TranDate = newBatch.DateEntered;
tran.CuryInfoID = Base.currencyinfo.Current.CuryInfoID;
tran.AccountID = row.Account;
tran.SubID = row.Subaccount;
tran.DebitAmt = row.DebitAmt;
tran.CuryDebitAmt = row.DebitAmt;
debit += row.DebitAmt;
tran.CreditAmt = row.CreditAmt;
tran.CuryCreditAmt = row.CreditAmt;
credit += row.CreditAmt;
tran.RefNbr = row.CashSalesRefNbr;
tran.TranDesc = customer.AcctCD + " - " + customer.AcctName;
newJournalEntry.GLTranModuleBatNbr.Update(tran);
}
newBatch = newJournalEntry.BatchModule.Update(newBatch);
if (GLSetup.Current.GetExtension<GLSetupExt>().UsrAutoRelease == true)
{
newJournalEntry.BatchModule.Current.Hold = false;
newJournalEntry.release.Press();
}
newJournalEntry.Save.Press();
if (isCreated)
isCreated = false;
cashSale.GetExtension<ARRegisterExt>().UsrFundBatch = newJournalEntry.BatchModule.Current.BatchNbr;
//Base.Document.Current.GetExtension<ARRegisterExt>().UsrFundBatch = newJournalEntry.BatchModule.Current.BatchNbr;
//Base.dummy_CATran.View.RequestRefresh();
Base.Document.Update(cashSale);
//TODO - Figure out why the fund batch isn't saving to the Cash Sale
Base.Actions.PressSave();
//Base.dummy_CATran.Cache.ClearQueryCache();
//Base.Persist(typeof(ARCashSale), PXDBOperation.Update);
}
}
});
});
return baseMethod(adapter);
}
I left in all of the different methods I've tried to get the ref nbr to save. I've ever tried to add a field updated handler for the BatchNbr field and force the new number in that way, but it did not work.
EDIT: I also noticed that I cannot successfully set an extended field on the Batch DAC. For example, I have the line newBatch.GetExtension<BatchExt>().ExtRefNbr = cashSale.RefNbr; to set the ref nbr in that document as well, but any time I run 'NewJournal.Press.Save()' it changes the set value of the extended field to null. If anyone knows how to set the extension field, I may be able to work with that instead to go down a different path that may do what I need.
I believe the appropriate place to perform your update is in graph ARDocumentRelease. Try something like this....
public class ARDocumentReleaseExtension : PXGraphExtension<ARDocumentRelease>
{
public override void Initialize()
{
ARSetup setup = Base.arsetup.Current;
Base.ARDocumentList.SetProcessDelegate(
delegate (List<BalancedARDocument> list)
{
List<ARRegister> newlist = new List<ARRegister>(list.Count);
foreach (BalancedARDocument doc in list)
{
newlist.Add(doc);
}
ARDocumentRelease.ReleaseDoc(newlist, true);
CreateSecondBatch(newlist);
}
);
Base.ARDocumentList.SetProcessCaption(PX.Objects.AR.Messages.Release);
Base.ARDocumentList.SetProcessAllCaption(PX.Objects.AR.Messages.ReleaseAll);
}
private void CreateSecondBatch(List<ARRegister> docs)
{
foreach(BalancedARDocument register in docs)
{
if (register.DocType == ARDocType.CashSale)
{
//create the second batch and assign the 2nd ref nbr to the cash sale user field
}
}
}
}

Netsuite Transaction search performance

I am using Netsuite API (version v2016_2) to search data. With below code, it seems that Netsuite taking much time to give response for the query. I am searching GL transaction of periticular period that has 149 MainLine record and 3941 LineItem (Journal Entries) record and Netsuite takes almost 22 minutes to give this data in response. Below is code snippet that I am using to search transaction.
public void GetTransactionData()
{
DataTable dtData = new DataTable();
string errorMsg = "";
LoginToService(ref errorMsg);
TransactionSearch objTransSearch = new TransactionSearch();
TransactionSearchBasic objTransSearchBasic = new TransactionSearchBasic();
SearchEnumMultiSelectField semsf = new SearchEnumMultiSelectField();
semsf.#operator = SearchEnumMultiSelectFieldOperator.anyOf;
semsf.operatorSpecified = true;
semsf.searchValue = new string[] { "Journal" };
objTransSearchBasic.type = semsf;
objTransSearchBasic.postingPeriod = new RecordRef() { internalId = "43" };
objTransSearch.basic = objTransSearchBasic;
//Set Search Preferences
SearchPreferences _searchPreferences = new SearchPreferences();
Preferences _prefs = new Preferences();
_serviceInstance.preferences = _prefs;
_serviceInstance.searchPreferences = _searchPreferences;
_searchPreferences.pageSize = 1000;
_searchPreferences.pageSizeSpecified = true;
_searchPreferences.bodyFieldsOnly = false;
//Set Search Preferences
try
{
SearchResult result = _serviceInstance.search(objTransSearch);
/*
Above line taking almost 22 minutes for below record count
result.recordList.Length = 149
Total JournalEntryLine = 3941
*/
List<JournalEntry> lstJEntry = new List<JournalEntry>();
List<JournalEntryLine> lstLineItems = new List<JournalEntryLine>();
if (result.status.isSuccess)
{
for (int i = 0; i <= result.recordList.Length - 1; i += 1)
{
JournalEntry JEntry = (JournalEntry)result.recordList[i];
lstJEntry.Add((JournalEntry)result.recordList[i]);
if (JEntry.lineList != null)
{
foreach (JournalEntryLine line in JEntry.lineList.line)
{
lstLineItems.Add(line);
}
}
}
}
try
{
_serviceInstance.logout();
}
catch (Exception ex)
{
}
}
catch (Exception ex)
{
throw ex;
}
}
I am unable to know that If I am missing something in my code or this is something about the data. Please suggest me some sort of solution for this.
Thanks.
You should set _searchPreferences.bodyFieldsOnly = true. It will improve the performance with searching because it doesn't return the related or sublist data
I think you are doing this search from the outside of the Netsuite to get journal entries data or lines. Instead of doing a direct search outside, do maintain RESTLET in NETSUITE and call that RESTLET. In the RESTLET DO that search you wanted and return results. Within the NETSUITE, search performance gives fast results.

Create advanced filter

I am trying to create an advanced filter in Excel from C# to copy unique data from one sheet to another, at least I get it in Excel and if I use Interop like this :
Excel.Range rang = sheet2.get_Range("A2");
Excel.Range oRng = sheet.get_Range("I2", "I" + (lst.Count + 1));
oRng.AdvancedFilter(Excel.XlFilterAction.xlFilterCopy, CriteriaRange: Type.Missing,
CopyToRange: rang, Unique: true);
Works fine but I'm doing all my application with EPPlus and it will be better if I can do the same without Interop.
So, it is possible?
Since Advanced Filter is an excel function you need the full Excel DOM to access it. Epplus doesnt have that - it just generated the XML to feed to excel which will then apply its "interpretation", so to speak.
But since you have the power of .NET at your disposal, you can use linq fairly easily to do the same thing by querying the cell store and using .distinct() to get the unique list. The only wrinkle is you have to create your own IEquitableComparer. This will do it:
[TestMethod]
public void Distinct_Filter_Test()
{
//Throw in some data
var datatable = new DataTable("tblData");
datatable.Columns.AddRange(new[]
{
new DataColumn("Col1", typeof (int)), new DataColumn("Col2", typeof (string))
});
var rnd = new Random();
for (var i = 0; i < 10; i++)
{
var row = datatable.NewRow();
row[0] = rnd.Next(1, 3) ;row[1] = i%2 == 0 ? "even": "odd";
datatable.Rows.Add(row);
}
//Create a test file
var fi = new FileInfo(#"c:\temp\Distinct_Filter.xlsx");
if (fi.Exists)
fi.Delete();
using (var pck = new ExcelPackage(fi))
{
//Load the random data
var workbook = pck.Workbook;
var worksheet = workbook.Worksheets.Add("data");
worksheet.Cells.LoadFromDataTable(datatable, true);
//Cells only contains references to cells with actual data
var rows = worksheet.Cells
.GroupBy(cell => cell.Start.Row)
.Skip(1) //Exclude header
.Select(cg => cg.Select(c => c.Value).ToArray())
.Distinct(new ArrayComparer())
.ToArray();
//Copy the data to the new sheet
var worksheet2 = workbook.Worksheets.Add("Distinct");
worksheet2.Cells.LoadFromArrays(rows);
pck.Save();
}
}
public class ArrayComparer: IEqualityComparer<object[]>
{
public bool Equals(object[] x, object[] y)
{
return !x.Where((o, i) => !o.Equals(y[i])).Any();
}
public int GetHashCode(object[] obj)
{
//Based on Jon Skeet Stack Overflow Post
unchecked
{
return obj.Aggregate((int) 2166136261, (acc, next) => acc*16777619 ^ next.GetHashCode());
}
}
}

Sub Grid Total In Crm

I have a primary Entity (Self-Insurance) and a secondary entity (Compensation). They have a 1:N relationship. So in my main form of Self Insurance I have a sub-grid with the name 'Worker_Compensation' where i am adding up some payroll values.
I have 2 questions. . .
1: The thing I want is that when I add some values in the sub-grid. I need to show a sum of all payrolls in the text below of my main form named as 'TOTAL'.
2: Where should i call this java script(On which event) Onload or Onsave of form ? or else where because I can seems to locate the events on Subgrid.
I am using a java script for this purpose.
enter code here
function setupGridRefresh() {
var targetgrid = document.getElementById("Worker_Compensation");
// If already loaded
if (targetgrid.readyState == 'complete') {
targetgrid.attachEvent("onrefresh", subGridOnload);
}
else {
targetgrid.onreadystatechange = function applyRefreshEvent() {
var targetgrid = document.getElementById("Worker_Compensation");
if (targetgrid.readyState == 'complete') {
targetgrid.attachEvent("onrefresh", subGridOnload);
}
}
}
subGridOnload();
}
function subGridOnload() {
//debugger;
var grid = Xrm.Page.ui.controls.get('Worker_Compensation')._control;
var sum = 0.00;
if (grid.get_innerControl() == null) {
setTimeout(subGridOnload, 1000);
return;
}
else if (grid.get_innerControl()._element.innerText.search("Loading") != -1) {
setTimeout(subGridOnload, 1000);
return;
}
var ids = grid.get_innerControl().get_allRecordIds();
var cellValue;
for (i = 0; i < ids.length; i++) {
if (grid.get_innerControl().getCellValue('new_estannualpayroll', ids[i]) != "") {
cellValue = grid.get_innerControl().getCellValue('new_estannualpayroll', ids[i]);
cellValue = cellValue.substring(2);
cellValue = parseFloat(cellValue);
sum = sum + cellValue;
}
}
var currentSum = Xrm.Page.getAttribute('new_payrolltotal').getValue();
if (sum > 0 || (currentSum != sum && currentSum != null)) {
Xrm.Page.getAttribute('new_payrolltotal').setValue(sum);
}
}
This piece of code is not working. after i add values in the grid my textbox remains empty!
Thanks in advance
If you are upgrading to Microsoft CRM 2015 soon or are already on Microsoft CRM 2015, you can do this without any JavaScript by simply creating a new calculated rollup field and placing that underneath the sub grid, or wherever you wish to place it on the form. Note that this field is calculated ever 12 hours, but if you wish to, it could be calculated on form load via JavaScript. You can see details about that at https://msdn.microsoft.com/en-us/library/dn817863.aspx -"Calculated and Rollup Attributes". The TechNet document, "Define rollup fields" at https://technet.microsoft.com/library/dn832162.aspx has some good examples, scenarios, and discussion about the limitations of the rollup fields.
You can do it with subgrid's onRefresh. This is also unsupportted way but it works. You must add this functions to your javascript
function AddEventToGridRefresh(gridName, functionToCall) {
// retrieve the subgrid
var grid = document.getElementById(gridName);
// if the subgrid still not available we try again after 1 second
if (grid == null) {
setTimeout(function () {AddEventToGridRefresh(gridName, functionToCall);}, 1000);
return;
}
// add the function to the onRefresh event
grid.control.add_onRefresh(functionToCall);
}
// function used in this example
function AdviseUser() {
alert("Sub-Grid refreshed");
}
For more information, here is the link

Watin: Iterating through text boxes in a telerik gridview

I am currently developing a testing framework for a web data entry application that is using the Telerik ASP.Net framework and have run into a blocker. If I step through my code in debug mode the test will find the text box that I am looking for and enter some test data and then save that data to the database. The problem that I am running into is that when I let the test run on it's own the test fails saying that it couldn't fine the column that was declared. Here is my code:
/*Method to enter test data into cell*/
private TableCell EditFieldCell(string columnHeader)
{
var columnIndex = ColumnIndex(columnHeader);
if (columnIndex == -1)
throw new InvalidOperationException(String.Format("Column {0} not found.", columnHeader));
return NewRecordRow.TableCells[columnIndex];
}
/*Method to return column index of column searching for*/
public int ColumnIndex(string columnHeader)
{
var rgTable = GridTable;
var rgCount = 0;
var rgIndex = -1;
foreach (var rgRow in rgTable.TableRows)
{
foreach (var rgElement in rgRow.Elements)
{
if (rgElement.Text != null)
{
if (rgElement.Text.Equals(columnHeader))
{
rgIndex = rgCount;
break;
}
}
rgCount++;
}
return rgIndex;
}
My thinking is that something with my nested for loops is presenting the problem because the rgIndex value that is returned when I let the program run is -1 which tells me that the code in the for loops isn't being run.
TIA,
Bill Youngman
Code that gets the table Column index. You need to pass the Table(verify that the table exists while debug):
public int GetColumnIndex(Table table, string headerName)
{
ElementCollection headerElements = table.TableRows[0].Elements; //First row contains the header
int counter = 0;
foreach (var header in headerElements)
{
if (header.ClassName != null && header.ClassName.Contains(headerName)) //In this case i use class name of the header you can use the text
{
return counter;
}
counter++;
}
// If not found
return -1;
}

Resources