Read only cells not sorted with the data in Grit Web

Using Grid Web component, V2.3.2.20031.

We have a couple of business rules that require us to set some cells (rather than entire columns) as read-only. We are using databound grids and allow sorting of data by clicking on the column name. When data is sorted, the read-only status of the cells appears to be not sorted with the data, and, as a result, we violate the business rule. Is there a way sync the view side cell’s read-only attribute with the sorted data? Do i have to revert to Javascript to set cell’s attributes so I can sync view with the business rule as the grid is rendered? I am currently not sure if the sort is even generating a postback, and if so, what event I should be hooking if I have to do it on the server side.

Our code is generally something like this:

private void BindData(SortableCollection ediData)
{
WebWorksheet wks = gridEDI.WebWorksheets[0];
wks.Cells.Clear();

wks.EnableRowAddDelete = false;
wks.DataSource = histories;

wks.DataBind();

// set select checkbox status based on a business rule
for (int row = 0; row < histories.Count; row++)
wks.Cells[row, 0].IsReadonly = !ediData[row].CanIncludeInEDI();

}
}

A simple example would be something like this: say 2 row grid: ‘Can include’ checkbox is normally read-only, Unless Completed Status = ‘Completed’. All is good until the data is sorted. Using our bind code cell [0, 0] will not be read only, cell [1,0] us always read-only. Basically we need to either re-bind based on the newly re-sorted data, or apply the rule on the client side AFTER sorting…


Can Include in EDI Status
====================================
[] Competed
[] Error

Hi,

Thanks for your inquiry.

For "When data is sorted, the read-only status of the cells appears to be not sorted with the data, and, as a result, we violate the business rule. Is there a way sync the view side cell’s read-only attribute with the sorted data? Do i have to revert to Javascript to set cell’s attributes so I can sync view with the business rule as the grid is rendered?.."

Well, we follow MS Excel standards. For your information, if we have some data protected / locked in a worksheet, for example, some cells in a column are not locked (that does allow read/write in the column), we protect the sheet. Now, when you try to sort the data range, you won’t allowed to include the locked cells/range in the Sorting area. Same behavior is with Aspose.Cells.GridWeb.


Anyways, we will look into it further and analyzing it if something can be done for your case, if we found anything we will let you know.

Thank you

Ok, I then have to handle the postback event and set readonly state after data is sorted, based on the sorted bound data object. I noticed that the sorting does a postback, so I may as well do it on the server side. But I don’t see any server side events dealing with sorting - is there? Which event should I be using? Is it ‘SheetDataUpdated’?

Ok, I tried using pre-render event and certainly seems that the the datasource is always in the original order, so it seems all sorting is on the client/view side… Is client side script working with HTML table cells the only way I could handle it? Any other way to accomplish what I need?

<!–[if gte mso 10]> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman","serif";}

<![endif]–>

Hi,


Please try the following code snippet, hopefully it can help you.

protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{
base.RaisePostBackEvent(sourceControl, eventArgument);

string[] args = eventArgument.Split(new char[] { ':' });
// Check if DataBind sort
if (args.Length > 0 && args[0] == "CELLCMD" && args[1].StartsWith("_BCSORT"))
{
// get sorting column index
//string coli = args[1].Split(new char[] { '#' })[1];
//int colIndex = int.Parse(coli);

GridWeb1.WebWorksheets[0].Cells["b2"].IsReadonly = true;
}
}

Thank you.

Should this code be in a control derived from GridWeb?

I tried the following solution, using the PreRender event. Basically I get a unique id that allows me to select the proper record from our collection and set the readonly flag based on the business rule. But this only works once - first column sort postback hits PreRender, it sets the proper cells’ read only status and the page looks correct. but after the next sort, even though via the debugger I see all the right cells getting ‘not read only’ status, on, the screen they are all showing as read only. What is going on here? Here is the code:

void acgwHeader_PreRender(object sender, EventArgs e)
{
SortableCollection histories = acgwHeader.WebWorksheets[0].DataSource as SortableCollection;

int rows = acgwHeader.WebWorksheets[0].Cells.MaxRow;
int cols = acgwHeader.WebWorksheets[0].Cells.MaxColumn;
int vendorColumn = -1;

// Find which column is the vendor id
for (int col = acgwHeader.WebWorksheets[0].Cells.MinColumn; col <= cols; col++)
{
if (acgwHeader.WebWorksheets[0].Cells.GetColumnCaption(col).ToLowerInvariant().Contains(“vendor id”))
vendorColumn = col;
}

if (vendorColumn >= 0)
{

for (int row = acgwHeader.WebWorksheets[0].Cells.MinRow; row <= rows; row++)
{
string vendorId = “”;

vendorId = acgwHeader.WebWorksheets[0].Cells[row, vendorColumn].UnformattedStringValue;

if (vendorId != “” ) // make sure there is a vendor ID
{
// Find the right collection element
int ix = histories.Find (“VendorId”, vendorId);

// The below code is what sets the red only flag. “CanIncludeInEDI” returns the right value
// that I have verified in the debugger, I can see that the cells are properly set as NOT read only
// but after the 1st sort post -back, ALL cells show up as read-only.
//1st postback, on the other hand, always works
if (ix >= 0)
acgwHeader.WebWorksheets[0].Cells[row, 1].IsReadonly = !histories[ix].CanIncludeInEDI(); // include in EDI checkbox
}
}

}


Hi,

Thanks for your feedback.

We will further look into it and get back to you soon.

Thank you.

Hi,

We have tested the code in my previous reply, We could not find the other cells are set to readonly whether we sort any time. So, try that code. If you have the issue, create a sample project and post it here. We will check it soon.

Thank you.

I have tried using the RaisePostBackEvent approach, however it will not work for us. We are running under an SAP portal, which is not a true Asp.Net environment and all our pages a controls derived from an SAP control (SAP.Portal.Web.UI.PortalComponent), which is hosted by a yet another SAP control, which does not appear to handle the RaisePostBackEvent quite right. Basically, the event fires (if I add RegisterRequiresRaiseEvent(this); in the control's OnInit), however, the eventArguments string in the RaisePostBackEvent is allways null, so I can't tell a sort from any other postback.

I also debugged/stepped thru the pre_render approach I have posted above and while the cells' ReadOnly attribute is set correctly, the checkboxes, as rendered by the browser , are not getting their 'disabled' attribute set correctly when the grid is displayed, so that puzzles me. Do you know why my pre-render approach is not working? I am getting a lot of pressure to get this issue fixed, but still don't have a viable solution...

Hi,

Thanks for your feedback and providing us details.

We will further look into your issue and get back to you soon.

Thank you.

Hi,

Well, we handle the GridWeb’s OnPreRender event as shown in the following code. There are only “b2” and “b3” cells set to read-only after every sorting. Hopefully, it can suit your need accordingly now.

protected void GridWeb1_PreRender(object sender, EventArgs e)
{
string eventTarget = Request.Params["__EVENTTARGET"];
string eventArgument = Request.Params["__EVENTARGUMENT"];

if (eventTarget == “GridWeb1”)
{
string[] args = eventArgument.Split(new char[] { ‘:’ });
// Check if DataBind sort
if (args.Length > 0 && args[0] == “CELLCMD” && args[1].StartsWith("_BCSORT"))
{
// get sorting column index
string coli = args[1].Split(new char[] { ‘#’ })[1];
int colIndex = int.Parse(coli);

GridWeb1.WebWorksheets[0].Cells[“b2”].IsReadonly = true;
GridWeb1.WebWorksheets[0].Cells[“b3”].IsReadonly = true;
}
}
}

Thank you.

We have investigated this a little more and looks kind of odd on our end. The “pre render” event handler setting the cell’s ReadOnly property works 2 times. After 2 sorts on the client side, ALL cells are set as ‘read only’, even if our code sets ReadOnly=FALSE. All cells are then rendered with a ‘protected=true’ HTML attribute. 2st two sorts are always correct, it is after 2 client side sorts that things get out of sync. As I said, very odd. I had my code reviewed by a peer within my company and it is correct;we have stepped thru it and it only sets certain cells as ReadOnly=false, yet all cells end up read-only.

As I said we are getting a lot of pressure to resolve this issue; if you can look into this (try sorting multiple times on your end) we’d truly appreciate this.

Hi,

Could you give us a sample project to show the issue, we will check it soon.

Thank you.

Here you go. This project includes the latest gridweb DLL. But here is what I have noticed: it does not work with V5.1+ versions of the grid DLL, BUT IT WORKS fine with older ones. My GAC v4.8, (file v 2.0.2.2002) so a ref to the GAC version works, if I make a reference to a yet another pre v5 version on my hard drive, it works. But as soon as a reference anything that I have with a V5 or later (file V2.3.+ Sep 2010 file data or later, then the code does not work.

PS - The demo should keep the row with vendorid=1/First Vendor with an enabled checkbox

FYI: Latest Aspose.Cells.GridWeb v2.4.1.2004

<!–[if gte mso 10]> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman","serif";}

<![endif]–>Hi,

We have fixed the issue in Aspose.Cells.GridWeb v2.4.1.2005 (attached). Your sample project works fine now. Please update the Aspose.Cells.GridWeb.dll file first, and then remove all files in /acw_client/ virtual directory, update it with /acw_client directory in the zip file.

Also, please remove the sample project as it contains a license file.

Thank you.

The sorting issue is solved, but now I get a 'firstChild.className is null or not an object" javascript runtime error from when I attempt to edit a text value. I modified the demo to allow editing of the text column and I can duplicate the error in my little test. just change the code in the loop at the end of prerender to set/clear IsReadOnly for the other cells in the row.:
string column2 = acgwHeader.WebWorksheets[0].Cells[row, 1].UnformattedStringValue;

if (column2 == “1”)
{
acgwHeader.WebWorksheets[0].Cells[row, 0].IsReadonly = false; // enable checkbox on item 1 only
acgwHeader.WebWorksheets[0].Cells[row, 1].IsReadonly = false; // enable checkbox on item 1 only
acgwHeader.WebWorksheets[0].Cells[row, 2].IsReadonly = false; // enable checkbox on item 1 only
}
else
{
acgwHeader.WebWorksheets[0].Cells[row, 0].IsReadonly = true;
acgwHeader.WebWorksheets[0].Cells[row, 1].IsReadonly = true;
acgwHeader.WebWorksheets[0].Cells[row, 2].IsReadonly = true;
}
Just try typing into the 2nd or 3d column of the raw which is NOT read only and you will get a runtime error shown in the attachment. I am running MS script debugger, so the specific source line/stack trace is shown there.


Hi Garrick,

Can you please test your case with latest version Aspose.Cells.GridWeb v2.4.2.2001 and let me know your findings. Thanks for your help.

Yes, it works. But it seems MUCH slower, both on the server side (binding to a List collection), as well as on the client side. We have some fairly largecollections (5,000-10,000 records) that we bind to the grid (using paging, of course) and the performance was marginally acceptable before, but now it is way too slow…

I have tried binding to datasets rather than lists and it is a just bit faster. . I have also determined that it is the worksheet.DataBind method that is slow. But what’s worse is that it is nonlinear - it takes approximately 30 seconds to bind to a an about 3000 row collection ( a bit faster if bound to a dataset), but for a 7500 row collection it takes 3 minutes 15 seconds (again a tad faster if binding to a data set rather than a collection). 8100 collection takes 3:50 (8% more data, 18% more time). Either way, it is just too slow…Your winform grid takes much less to bind to a much larger data set - I have bound 10000 (ten thousand) row data sets in a few seconds…